题目:
Given a list of words, each word consists of English lowercase letters.
Let's say word1
is a predecessor of word2
if and only if we can add exactly one letter anywhere in word1
to make it equal to word2
. For example, "abc"
is a predecessor of "abac"
.
A word chain is a sequence of words [word_1, word_2, ..., word_k]
with k >= 1
, where word_1
is a predecessor of word_2
, word_2
is a predecessor of word_3
, and so on.
Return the longest possible length of a word chain with words chosen from the given list of words
.
Example 1:
Input: ["a","b","ba","bca","bda","bdca"] Output: 4 Explanation: one of the longest word chain is "a","ba","bda","bdca".
解法:
这题看上去和LIS差不多,但是要注意题意里的predecessor的含义是,only add one letter。清楚了这一点,就可以分析出状态转移方程。
对于第n个字符串来说,需要做的是遍历该字符串中的每一个char,去掉该char之后组成一个新字符串。将这个新字符串与前n-1个字符串比较,如果能对应上,就在对应上的基础上+1。
这里也可以用传统的dp方法,创建一个dp数组,每次循环更新。但是由于需要不停地比对字符串,循环过多。所以可以采用HASHMAP来存储。需要注意的是,在hashmap取对应的key时,使用getOrdefault方法,表示取不到该字符串时返回长度0。
/*
* 1048. Longest String Chain
* https://leetcode.com/problems/longest-string-chain/
* 看上去和LIS差不多。注意题意是only add exactly one letter!!
*/
public int longestStrChain(String[] words) {
if(words == null || words.length == 0){
return 0;
}
int res = 0;
HashMap<String,Integer> dp = new HashMap<>();
//注意这种写法!!
Arrays.sort(words,(a,b) -> a.length() - b.length());
for(int i = 0; i < words.length ; i++) {
int max = 0;
for(int j = 0 ;j < words[i].length();j++) {
String prev = words[i].substring(0,j) + words[i].substring(j+1);
max = Math.max(max, dp.getOrDefault(prev, 0) + 1);
//System.out.println(prev + "->" + words[i] );
}
dp.put(words[i], max);
res = Math.max(res, max);
}
return res;
}