【题解】—— 每日一道题目栏
上接:【题解】—— LeetCode一周小结24
17.最长特殊序列 II
题目链接:522. 最长特殊序列 II
给定字符串列表 strs ,返回其中 最长的特殊序列 的长度。如果最长特殊序列不存在,返回 -1 。
特殊序列 定义如下:该序列为某字符串 独有的子序列(即不能是其他字符串的子序列)。
s 的 子序列可以通过删去字符串 s 中的某些字符实现。
例如,“abc” 是 “aebdc” 的子序列,因为您可以删除"aebdc"中的下划线字符来得到 “abc” 。“aebdc"的子序列还包括"aebdc”、 “aeb” 和 “” (空字符串)。
示例 1:
示例 2:
提示:
题解:
方法:枚举
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"、"
6"表示价格,而"100"、"” 和 "$1e5 不是。
给你一个字符串 sentence 表示一个句子和一个整数 discount 。对于每个表示价格的单词,都在价格的基础上减免 discount% ,并 更新 该单词到句子中。所有更新后的价格应该表示为一个 恰好保留小数点后两位 的数字。
返回表示修改后句子的字符串。
注意:所有价格 最多 为 10 位数字。
示例 1:
示例 2:
提示:
题解:
方法:模拟
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:
示例 2:
示例 3:
提示:
题解:
方法:动态规划
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:
示例 2:
提示:
题解:
方法:数论
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:
示例 2:
提示:
题解:
方法:数学
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:
示例 2:
提示:
题解:
方法:贪心
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:
示例 2:
提示:
题解:
方法:
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