【题解】—— LeetCode一周小结25

简介: LeetCode每日一道一周小结25

🌟欢迎来到 我的博客 —— 探索技术的无限可能!

🌟博客的简介(文章目录)


【题解】—— 每日一道题目栏


上接:【题解】—— LeetCode一周小结24

17.最长特殊序列 II

题目链接:522. 最长特殊序列 II

给定字符串列表 strs ,返回其中 最长的特殊序列 的长度。如果最长特殊序列不存在,返回 -1 。

特殊序列 定义如下:该序列为某字符串 独有的子序列(即不能是其他字符串的子序列)。

s 的 子序列可以通过删去字符串 s 中的某些字符实现。

例如,“abc” 是 “aebdc” 的子序列,因为您可以删除"aebdc"中的下划线字符来得到 “abc” 。“aebdc"的子序列还包括"aebdc”、 “aeb” 和 “” (空字符串)。

示例 1:

输入: strs = [“aba”,“cdc”,“eae”]

输出: 3

示例 2:

输入: strs = [“aaa”,“aaa”,“aa”]

输出: -1

提示:

2 <= strs.length <= 50

1 <= strs[i].length <= 10

strs[i] 只包含小写英文字母

题解:

方法:枚举

       

class Solution {
    public int findLUSlength(String[] strs) {
        int ans = -1;
        next:
        for (int i = 0; i < strs.length; i++) {
            if (strs[i].length() <= ans) { // 不会让 ans 变大
                continue;
            }
            for (int j = 0; j < strs.length; j++) {
                if (j != i && isSubseq(strs[i], strs[j])) {
                    continue next;
                }
            }
            ans = strs[i].length();
        }
        return ans;
    }
    // 判断 s 是否为 t 的子序列
    private boolean isSubseq(String s, String t) {
        int i = 0;
        for (char c : t.toCharArray()) {
            if (s.charAt(i) == c && ++i == s.length()) { // 所有字符匹配完毕
                return true; // s 是 t 的子序列
            }
        }
        return false;
    }
}

18.价格减免

题目链接:2288. 价格减免

句子 是由若干个单词组成的字符串,单词之间用单个空格分隔,其中每个单词可以包含数字、小写字母、和美元符号 ‘$’ 。如果单词的形式为美元符号后跟着一个非负实数,那么这个单词就表示一个 价格 。

例如 “$100”、“$23” 和 “6"表示价格,而"100"、"6"表示价格,而"100""” 和 "$1e5 不是。

给你一个字符串 sentence 表示一个句子和一个整数 discount 。对于每个表示价格的单词,都在价格的基础上减免 discount% ,并 更新 该单词到句子中。所有更新后的价格应该表示为一个 恰好保留小数点后两位 的数字。

返回表示修改后句子的字符串。

注意:所有价格 最多 为 10 位数字。

示例 1:

输入:sentence = “there are $1 2𝑎𝑛𝑑52and5 candies in the shop”, discount =

50

输出:“there are $0.50 1.00𝑎𝑛𝑑51.00and5 candies in the shop”

解释:

表示价格的单词是 “$1” 和 “$2” 。

  • “$1” 减免 50% 为 “$0.50” ,所以 “$1” 替换为 “$0.50” 。
  • “$2” 减免 50% 为 “$1” ,所以 “$2” 替换为 “$1.00” 。

示例 2:

输入:sentence = “1 2 $3 4 $5 678678 $9 1010”, discount = 100

输出:“1 2 $0.00 4 $0.00 0.00780.0078 $0.00 1010

解释:

任何价格减免 100% 都会得到 0 。

表示价格的单词分别是 “$3”、“$5”、“$6” 和 “$9”。

每个单词都替换为 “$0.00”。

提示:

1 <= sentence.length <= 105

sentence 由小写英文字母、数字、’ ’ 和 ‘$’ 组成

sentence 不含前导和尾随空格

sentence 的所有单词都用单个空格分隔

所有价格都是 正 整数且不含前导零

所有价格 最多 为 10 位数字

0 <= discount <= 100

题解:

方法:模拟

       

class Solution {
    public String discountPrices(String sentence, int discount) {
        String[] words = sentence.split(" ");
        for (int i = 0; i < words.length; ++i) {
            if (check(words[i])) {
                double t = Long.parseLong(words[i].substring(1)) * (1 - discount / 100.0);
                words[i] = String.format("$%.2f", t);
            }
        }
        return String.join(" ", words);
    }
    private boolean check(String s) {
        if (s.charAt(0) != '$' || s.length() == 1) {
            return false;
        }
        for (int i = 1; i < s.length(); ++i) {
            if (!Character.isDigit(s.charAt(i))) {
                return false;
            }
        }
        return true;
    }
}

19.矩阵中严格递增的单元格数

题目链接:2713. 矩阵中严格递增的单元格数

给你一个下标从 1 开始、大小为 m x n 的整数矩阵 mat,你可以选择任一单元格作为 起始单元格 。

从起始单元格出发,你可以移动到 同一行或同一列 中的任何其他单元格,但前提是目标单元格的值 严格大于 当前单元格的值。

你可以多次重复这一过程,从一个单元格移动到另一个单元格,直到无法再进行任何移动。

请你找出从某个单元开始访问矩阵所能访问的 单元格的最大数量 。

返回一个表示可访问单元格最大数量的整数。

示例 1:

输入:mat = [[3,1],[3,4]]

输出:2

解释:上图展示了从第 1 行、第 2 列的单元格开始,可以访问 2 个单元格。可以证明,无论从哪个单元格开始,最多只能访问 2

个单元格,因此答案是 2 。

示例 2:

输入:mat = [[1,1],[1,1]]

输出:1

解释:由于目标单元格必须严格大于当前单元格,在本示例中只能访问 1 个单元格。

示例 3:

输入:mat = [[3,1,6],[-9,5,7]]

输出:4

解释:上图展示了从第 2 行、第 1 列的单元格开始,可以访问 4 个单元格。可以证明,无论从哪个单元格开始,最多只能访问 4

个单元格,因此答案是 4 。

提示:

m == mat.length

n == mat[i].length

1 <= m, n <= 105

1 <= m * n <= 105

-105 <= mat[i][j] <= 105

题解:

方法:动态规划

       

class Solution {
    public int maxIncreasingCells(int[][] mat) {
        int m = mat.length, n = mat[0].length;
        TreeMap<Integer, List<int[]>> g = new TreeMap<>();
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                g.computeIfAbsent(mat[i][j], k -> new ArrayList<>()).add(new int[] {i, j});
            }
        }
        int[] rowMax = new int[m];
        int[] colMax = new int[n];
        int ans = 0;
        for (var e : g.entrySet()) {
            var pos = e.getValue();
            int[] mx = new int[pos.size()];
            int k = 0;
            for (var p : pos) {
                int i = p[0], j = p[1];
                mx[k] = Math.max(rowMax[i], colMax[j]) + 1;
                ans = Math.max(ans, mx[k++]);
            }
            for (k = 0; k < mx.length; ++k) {
                int i = pos.get(k)[0], j = pos.get(k)[1];
                rowMax[i] = Math.max(rowMax[i], mx[k]);
                colMax[j] = Math.max(colMax[j], mx[k]);
            }
        }
        return ans;
    }
}

20.美丽下标对的数目

题目链接:2748. 美丽下标对的数目

给你一个下标从 0 开始的整数数组 nums 。如果下标对 i、j 满足 0 ≤ i < j < nums.length ,如果 nums[i] 的 第一个数字 和 nums[j] 的 最后一个数字 互质 ,则认为 nums[i] 和 nums[j] 是一组 美丽下标对 。

返回 nums 中 美丽下标对 的总数目。

对于两个整数 x 和 y ,如果不存在大于 1 的整数可以整除它们,则认为 x 和 y 互质 。换而言之,如果 gcd(x, y) == 1 ,则认为 x 和 y 互质,其中 gcd(x, y) 是 x 和 y 的 最大公因数 。

示例 1:

输入:nums = [2,5,1,4]

输出:5

解释:nums 中共有 5 组美丽下标对:

i = 0 和 j = 1 :nums[0] 的第一个数字是 2 ,nums[1] 的最后一个数字是 5 。2 和 5 互质,因此

gcd(2,5) == 1 。

i = 0 和 j = 2 :nums[0] 的第一个数字是 2 ,nums[2] 的最后一个数字是 1 。2 和 1 互质,因此

gcd(2,1) == 1 。

i = 1 和 j = 2 :nums[1] 的第一个数字是 5 ,nums[2] 的最后一个数字是 1 。5 和 1 互质,因此

gcd(5,1) == 1 。

i = 1 和 j = 3 :nums[1] 的第一个数字是 5 ,nums[3] 的最后一个数字是 4 。5 和 4 互质,因此

gcd(5,4) == 1 。

i = 2 和 j = 3 :nums[2] 的第一个数字是 1 ,nums[3] 的最后一个数字是 4 。1 和 4 互质,因此

gcd(1,4) == 1 。

因此,返回 5 。

示例 2:

输入:nums = [11,21,12]

输出:2

解释:共有 2 组美丽下标对:

i = 0 和 j = 1 :nums[0] 的第一个数字是 1 ,nums[1] 的最后一个数字是 1 。gcd(1,1) == 1 。

i = 0 和 j = 2 :nums[0] 的第一个数字是 1 ,nums[2] 的最后一个数字是 2 。gcd(1,2) == 1 。

因此,返回 2 。

提示:

2 <= nums.length <= 100

1 <= nums[i] <= 9999

nums[i] % 10 != 0

题解:

方法:数论

       

class Solution {
    public int countBeautifulPairs(int[] nums) {
        int ans = 0;
        int[] cnt = new int[10];
        for (int x : nums) {
            for (int y = 1; y < 10; y++) {
                if (cnt[y] > 0 && gcd(y, x % 10) == 1) {
                    ans += cnt[y];
                }
            }
            while (x >= 10) {
                x /= 10;
            }
            cnt[x]++; // 统计最高位的出现次数
        }
        return ans;
    }
    private int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }
}

21.气温变化趋势

题目链接:LCP 61. 气温变化趋势

力扣城计划在两地设立「力扣嘉年华」的分会场,气象小组正在分析两地区的气温变化趋势,对于第 i ~ (i+1) 天的气温变化趋势,将根据以下规则判断:

若第 i+1 天的气温 高于 第 i 天,为 上升 趋势

若第 i+1 天的气温 等于 第 i 天,为 平稳 趋势

若第 i+1 天的气温 低于 第 i 天,为 下降 趋势

已知 temperatureA[i] 和 temperatureB[i] 分别表示第 i 天两地区的气温。 组委会希望找到一段天数尽可能多,且两地气温变化趋势相同的时间举办嘉年华活动。请分析并返回两地气温变化趋势相同的最大连续天数。

即最大的 n,使得第 i~i+n 天之间,两地气温变化趋势相同

示例 1:

输入: temperatureA = [21,18,18,18,31] temperatureB = [34,32,16,16,17]

输出:2

解释:如下表所示, 第 2~4 天两地气温变化趋势相同,且持续时间最长,因此返回 4-2=2

示例 2:

输入: temperatureA = [5,10,16,-6,15,11,3] temperatureB =

[16,22,23,23,25,3,-16]

输出:3

提示:

2 <= temperatureA.length == temperatureB.length <= 1000

-20 <= temperatureA[i], temperatureB[i] <= 40

题解:

方法:数学

       

public class Solution {
    public int temperatureTrend(int[] a, int[] b) {
        int ans = 0;
        int same = 0;
        for (int i = 1; i < a.length; i++) {
            if (Integer.compare(a[i - 1], a[i]) == Integer.compare(b[i - 1], b[i])) {
                ans = Math.max(ans, ++same);
            } else {
                same = 0;
            }
        }
        return ans;
    }
}

22.字典序最小的美丽字符串

题目链接:2663. 字典序最小的美丽字符串

如果一个字符串满足以下条件,则称其为 美丽字符串 :

它由英语小写字母表的前 k 个字母组成。

它不包含任何长度为 2 或更长的回文子字符串。

给你一个长度为 n 的美丽字符串 s 和一个正整数 k 。

请你找出并返回一个长度为 n 的美丽字符串,该字符串还满足:在字典序大于 s 的所有美丽字符串中字典序最小。如果不存在这样的字符串,则返回一个空字符串。

对于长度相同的两个字符串 a 和 b ,如果字符串 a 在与字符串 b 不同的第一个位置上的字符字典序更大,则字符串 a 的字典序大于字符串 b 。

例如,“abcd” 的字典序比 “abcc” 更大,因为在不同的第一个位置(第四个字符)上 d 的字典序大于 c 。

示例 1:

输入:s = “abcz”, k = 26

输出:“abda”

解释:字符串 “abda” 既是美丽字符串,又满足字典序大于 “abcz” 。 可以证明不存在字符串同时满足字典序大于

“abcz”、美丽字符串、字典序小于 “abda” 这三个条件。

示例 2:

输入:s = “dc”, k = 4

输出:“”

解释:可以证明,不存在既是美丽字符串,又字典序大于 “dc” 的字符串。

提示:

1 <= n == s.length <= 105

4 <= k <= 26

s 是一个美丽字符串

题解:

方法:贪心

       

class Solution {
    public String smallestBeautifulString(String S, int k) {
        k += 'a';
        char[] s = S.toCharArray();
        int n = s.length;
        int i = n - 1; // 从最后一个字母开始
        s[i]++; // 先加一
        while (i < n) {
            if (s[i] == k) { // 需要进位
                if (i == 0) { // 无法进位
                    return "";
                }
                // 进位
                s[i] = 'a';
                s[--i]++;
            } else if (i > 0 && s[i] == s[i - 1] || i > 1 && s[i] == s[i - 2]) {
                s[i]++; // 如果 s[i] 和左侧的字符形成回文串,就继续增加 s[i]
            } else {
                i++; // 反过来检查后面是否有回文串
            }
        }
        return new String(s);
    }
}

23.检测大写字母

题目链接:520. 检测大写字母

我们定义,在以下情况时,单词的大写用法是正确的:

全部字母都是大写,比如 “USA” 。

单词中所有字母都不是大写,比如 “leetcode” 。

如果单词不只含有一个字母,只有首字母大写, 比如 “Google” 。

给你一个字符串 word 。如果大写用法正确,返回 true ;否则,返回 false 。

示例 1:

输入:word = “USA”

输出:true

示例 2:

输入:word = “FlaG”

输出:false

提示:

1 <= word.length <= 100

word 由小写和大写英文字母组成

题解:

方法:

class Solution {
    public boolean detectCapitalUse(String word) {
        int cnt = 0;
        for (char c : word.toCharArray()) {
            if (Character.isUpperCase(c)) {
                ++cnt;
            }
        }
        return cnt == 0 || cnt == word.length()
            || (cnt == 1 && Character.isUpperCase(word.charAt(0)));
    }
}

下接:【题解】—— LeetCode一周小结26


相关文章
|
2月前
|
人工智能 BI
|
2月前
|
测试技术 索引
【题解】—— LeetCode一周小结40
LeetCode每日一道一周小结40
【题解】—— LeetCode一周小结41
【题解】—— LeetCode一周小结41
|
3月前
|
人工智能 BI
|
4月前
|
Perl
|
6月前
|
算法
|
5月前
|
测试技术 索引
|
7月前
|
存储 测试技术 索引
【题解】—— LeetCode一周小结21
LeetCode每日一道一周小结21
|
7月前
|
机器学习/深度学习 测试技术 C++
【题解】—— LeetCode一周小结14
【题解】—— LeetCode一周小结14