G
N
I
D
A
O
L

给出一个单词数组 words ,其中每个单词都由小写英文字母组成。

如果我们可以 不改变其他字符的顺序 ,在 wordA 的任何地方添加 恰好一个 字母使其变成 wordB ,那么我们认为 wordA 是 wordB 的 前身 。

  • 例如,"abc" 是 "abac" 的 前身 ,而 "cba" 不是 "bcad" 的 前身

词链是单词  [word_1, word_2, ..., word_k]  组成的序列, k >= 1 ,其中 word1 是 word2 的前身,word2 是 word3 的前身,依此类推。一个单词通常是 k = 1 的 单词链 。

从给定单词列表 words 中选择单词组成词链,返回词链的最长可能长度 。

题目链接:https://leetcode.cn/problems/longest-string-chain/

# 方法一

# 解题思路

  1. 先按长度升序排序,这样最长的数组一定出现在靠后的位置
  2. 动态规划:
  • dp[i] 表示以 words[i] 结尾的最长字符串链的长度

PS:有点像最长上升子数组

# 提交结果

image.png

# 代码

a
class Solution {
    public int longestStrChain(String[] words) {
        Arrays.sort(words, (s1, s2) -> s1.length() - s2.length());
        int n = words.length;
        int[] dp = new int[n];
        int max = 0;
        for(int i = 1; i < n; ++i) {
            for (int j = i - 1; j >= 0; --j) {
                if (check(words[j], words[i])) {
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                }
            }
            max = Math.max(max, dp[i]);
        }
        return max + 1;
    }
    private boolean check(String s, String t) {
        if (s == null || t == null || s.length() < 1 || s.length() + 1 != t.length()) 
            return false;
        
        char[] schs = s.toCharArray();
        int lens = schs.length;
        int lost = 0;
        int j = 0;
        for (char c : t.toCharArray()) {
            if (j >= lens || schs[j] != c) {
                ++lost;
            } else {
                ++j;
            }
        }
        return j == lens && lost == 1;
    }
}

# 方法二

# 解题思路

  • 使用哈希表存储【以每个字符串结尾的最长字符串链的长度】
  • 排序后直接对当前的单词进行枚举每一个可能的前身,即逐个去掉一个字符,再与哈希表中的字符串链进行比对,取最大值即可

# 代码

a
class Solution {
    public int longestStrChain(String[] words) {
        Map<String, Integer> cntMap = new HashMap<>();
        Arrays.sort(words, (a, b) -> a.length() - b.length());
        int res = 0;
        for (String w : words) {
            int maxLen = 1;
            // 一次去调一个字符,再进行比对
            for (int i = w.length() - 1; i >= 0; --i) {
                String s = w.substring(0, i) + w.substring(i + 1);
                maxLen = Math.max(maxLen, cntMap.getOrDefault(s, 0) + 1);
            }
            // 加上本身
            res = Math.max(res, maxLen);
            cntMap.put(w, maxLen);
        }
        return res;
    }
}
更新于 阅读次数

😉觉得写的还不错,请我喝杯咖啡吧😁

独步凌波 微信支付

微信支付

独步凌波 支付宝

支付宝