力扣524(java)-通过删除字母匹配到字典里最长单词(中等)
题目:
给你一个字符串 s 和一个字符串数组 dictionary ,找出并返回 dictionary 中最长的字符串,该字符串可以通过删除 s 中的某些字符得到。
如果答案不止一个,返回长度最长且字母序最小的字符串。如果答案不存在,则返回空字符串。
示例 1:
输入:s = "abpcplea", dictionary = ["ale","apple","monkey","plea"]
输出:"apple"
示例 2:
输入:s = "abpcplea", dictionary = ["a","b","c"]
输出:"a"
提示:
1 <= s.length <= 1000
1 <= dictionary.length <= 1000
1 <= dictionary[i].length <= 1000
s 和 dictionary[i] 仅由小写英文字母组成
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-word-in-dictionary-through-deleting
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
一、排序+双指针
1.首先将字符串数组dictionary中的每个字符串进行排序,如果字符串长度不相等,则按照长度降序排序,如果字符串相等,则按字符升序排序;
2.遍历排好序后的dictionary中每个字符串,定义两个指针 i 和 j ,分别指向字符串 s 和 dictionary中每个字符串 s1的起始位置,如果
![](https://img2022.cnblogs.com/blog/2546223/202206/2546223-20220609102239207-996086891.png)
二、动态规划
1.先使用动态规划对 s 中的字符位置进行预处理,设s的字符串长度为n,建立一个 n+1*26 大小的矩阵,初始化二维数组的最后一行dp[n][i] 都为n,从后往前填充数组,其他每个位置上的值代表s中每个字符第一次出现的位置;
2.设定一个标志位表示是否匹配成功,初始值为true,遍历字符数组dictionary中每个字符串的每个字符,如果当前值为初始化值n,表示不匹配,
![](https://img2022.cnblogs.com/blog/2546223/202206/2546223-20220609190632832-1927734710.jpg)
1 class Solution { 2 public String findLongestWord(String s, List<String> dictionary) { 3 int n = s.length(); 4 int[][] dp = new int[n+1][26]; 5 //初始化二维数组最后一行 6 for(int i = 0; i < 26; i++){ 7 dp[n][i] = n; 8 } 9 //动态填充二维数组,从后往前遍历 10 for(int i = n-1; i >= 0; i--){ 11 for(int j = 0; j < 26; j++){ 12 //如果当前字符与26字母中的一个相同,则当前行号就为当前位置的值 13 if(s.charAt(i) == (char)(j + 'a')){ 14 dp[i][j] = i; 15 }else{ 16 //如果不同,则将下一行的值给当前行 17 dp[i][j] = dp[i + 1][j]; 18 } 19 } 20 } 21 String res = ""; 22 //开始匹配 23 for(String d1 : dictionary){ 24 //设定一个标志位表示是否匹配成功,初始值为匹配 25 boolean match = true; 26 int j = 0; 27 //遍历字符数组中每个字符串的每个字符 28 for(int i = 0; i < d1.length(); i++){ 29 //如果当前值为初始化值,表示不匹配 30 if(dp[j][d1.charAt(i) - 'a'] == n){ 31 match = false; 32 break; 33 } 34 //如果查找到,,则从s的下一位继续匹配 35 j = dp[j][d1.charAt(i) - 'a'] + 1; 36 } 37 if(match){ 38 //在匹配的条件下,如果长度大或者在长度相等的情况下选择字母序小的, 39 if(d1.length() > res.length() || (d1.length() == res.length() && d1.compareTo(res) < 0)){ 40 res = d1; 41 } 42 } 43 } 44 return res; 45 46 } 47 }
小知识:
1.以下两种写法是一个意思,都是将字符数组中长度不等的每个字符串进行升序排序,长度相等的按字母顺序降序排序。
Collections.sort(list, new Comparator<>()):
第一个参数:需要排序的list
第二个参数:比较器,实现Comparator接口的类,返回一个int型的值,就相当于一个标志,告诉sort方法按什么顺序来对list进行排序。Comparator是个接口,可重写compare()及equals()这两个方法,用于比较功能。
- compare(a,b)方法:根据第一个参数小于、等于或大于第二个参数分别返回负整数(升序)、零(不变)或正整数(降序)。
升序: list.sort((a,b)->a-b); 或者 list.sort((a,b)->a.compareTo(b));
降序:list.sort((a,b)->b-a); 或者 list.sort((a,b)->b.compareTo(a));
- equals(obj)方法:仅当指定的对象也是一个 Comparator,并且强行实施与此 Comparator 相同的排序时才返回 true。
a.compareTo(b) 来“比较a和b的大小”,方便记忆为"x-y"。若返回“负数”,意味着“a比b小”;返回“零”,意味着“a等于b”;返回“正数”,意味着“a大于b”。
- *升序排的话就是第一个参数.compareTo(第二个参数);
-
*降序排的话就是第二个参数.compareTo(第一个参数);
// 1. Collections.sort(dictionary, new Comparator<String>() { public int compare(String a, String b) { if (a.length() != b.length()) { return b.length() - a.length(); } else { return a.compareTo(b); } } }); //2. Collections.sort(dictionary, (a,b)->{ if(a.length() != b.length()) return b.length() - a.length(); return a.compareTo(b); });
1 string str1 = ""; //空字符串,分配了内存,分配了一个空间 str1.length() 等于 0 2 string str2 = null; //NULL 3 string str3 = " "; //空格串,分配了内存,分配了一个空间 str2.length() 等于 1