最长字符串链【LC1048】
给出一个单词数组
words,其中每个单词都由小写英文字母组成。如果我们可以 不改变其他字符的顺序 ,在
wordA的任何地方添加 恰好一个 字母使其变成wordB,那么我们认为wordA是wordB的 前身 。
- 例如,
"abc"是"abac"的 前身 ,而"cba"不是"bcad"的 前身词链是单词
[word_1, word_2, ..., word_k]组成的序列,k >= 1,其中word1是word2的前身,word2是word3的前身,依此类推。一个单词通常是k == 1的 单词链 。从给定单词列表
words中选择单词组成词链,返回 词链的 最长可能长度 。
到家啦 happy
-
思路
某个单词的前身单词的长度一定比该单词少1,因此可以将单词根据长度升序排列。然后通过动态规划找到词链的最长长度,定义dp[i]为以words[i]为词链末尾的最长词链长度,如果words[j]是words[i]的前身,那么判断是否需要更新dp[i]。
-
实现
class Solution { public int longestStrChain(String[] words) { Arrays.sort(words, (o1, o2) -> o1.length() - o2.length()); int n = words.length; int[] dp = new int[n]; Arrays.fill(dp, 1); int res = 0; for (int i = 0; i < n; i++){ for (int j = 0; j < i; j++){ if (isPredecessor(words[i], words[j])){ dp[i] = Math.max(dp[i], dp[j] + 1); } } res = Math.max(res, dp[i]); } return res; } // 判断s2是否是s1的前身 public boolean isPredecessor(String s1, String s2){ int n = s1.length(), m = s2.length(); if (n != m + 1) return false; int i = 0, j = 0; while (i < n && j < m){ if (s1.charAt(i) == s2.charAt(j)){ j++; } i++; } return j == m; } }-
复杂度
- 时间复杂度: O ( n l o g n + n 2 L ) O(nlogn+n^2L) O(nlogn+n2L), n n n为数组长度, L L L为字符串的长度,排序需要的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),动态规划的时间复杂度为 O ( n 2 L ) O(n^2L) O(n2L)
- 空间复杂度: O ( l o g n + n ) O(logn+n) O(logn+n)
-

该问题通过将单词按长度排序后,使用动态规划求解最长词链。动态规划数组dp[i]表示以words[i]结尾的最长词链长度,遍历比较每个单词的前身并更新dp值,最终返回最大长度。
404

被折叠的 条评论
为什么被折叠?



