力扣-第291场周赛
第1题
6047. 移除指定数字得到的最大结果
给你一个表示某个正整数的字符串 number 和一个字符 digit 。
从 number 中 恰好 移除 一个 等于 digit 的字符后,找出并返回按 十进制 表示 最大 的结果字符串。生成的测试用例满足 digit 在 number 中出现至少一次。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-digit-from-number-to-maximize-result
示例 1:
输入:number = "123", digit = "3"
输出:"12"
解释:"123" 中只有一个 '3' ,在移除 '3' 之后,结果为 "12" 。
示例 2:
输入:number = "1231", digit = "1"
输出:"231"
解释:可以移除第一个 '1' 得到 "231" 或者移除第二个 '1' 得到 "123" 。
由于 231 > 123 ,返回 "231" 。
示例 3:
输入:number = "551", digit = "5"
输出:"51"
解释:可以从 "551" 中移除第一个或者第二个 '5' 。
两种方案的结果都是 "51" 。
提示:
2 <= number.length <= 100
number 由数字 '1' 到 '9' 组成
digit 是 '1' 到 '9' 中的一个数字
digit 在 number 中出现至少一次
题解
遍历字符串的每个字符,把 digit 前后的字符串连接起来,构成新的字符串,放到 list中,再通过Collections
对 list 进行排序,取出最大值即可。
点击查看代码
c++
class Solution {
public:
string removeDigit(string number, char digit) {
vector<string> v;
for(int i=0, len=number.length(); i<len; i++){
if(number[i] == digit){
v.push_back(number.substr(0,i) + number.substr(i+1,len));
}
}
string maxv = v[0];
for(int i=1; i<v.size(); i++){
if(compareAB(maxv, v[i])==-1) maxv = v[i];
}
return maxv;
}
// 比较字符串数字a,b大小,a>b返回1,a=b返回0,a<b返回-1;
int compareAB(string a, string b){
if(a.length()>b.length()) return 1;
else if(a.length()<b.length()) return -1;
for(int i=0; i<a.length(); i++){
if(a[i]>b[i]) return 1;
else if(a[i]<b[i]) return -1;
}
return 0;
}
};
java:
class Solution {
public String removeDigit(String number, char digit) {
int n = number.length();
List<String> list = new ArrayList<>();
for (int i = 0; i < n; i++) {
if (number.charAt(i) == digit) {
String s = number.substring(0, i) + number.substring(i + 1, n);
list.add(s);
}
}
Collections.sort(list);
return list.get(list.size() - 1);
}
}
看到一个比较妙的方法
class Solution {
public:
string removeDigit(string number, char digit) {
int pre = -1;
for (int i = 0; i < number.length(); i += 1) {
if (number[i] == digit) {
pre = i;
if (i + 1 < number.length() && number[i + 1] > number[i]) // 只需要比较下一位就可,而非字串
break;
}
}
return number.substr(0, pre) + number.substr(pre + 1);
}
};
第2题
6048. 必须拿起的最小连续卡牌数
给你一个整数数组 cards ,其中 cards[i] 表示第 i 张卡牌的 值 。如果两张卡牌的值相同,则认为这一对卡牌 匹配 。
返回你必须拿起的最小连续卡牌数,以使在拿起的卡牌中有一对匹配的卡牌。如果无法得到一对匹配的卡牌,返回 -1
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-consecutive-cards-to-pick-up
示例 1:
输入:cards = [3,4,2,3,4,7]
输出:4
解释:拿起卡牌 [3,4,2,3] 将会包含一对值为 3 的匹配卡牌。注意,拿起 [4,2,3,4] 也是最优方案。
示例 2:
输入:cards = [1,0,5,3]
输出:-1
解释:无法找出含一对匹配卡牌的一组连续卡牌。
提示:
1 <= cards.length <= 1e5
0 <= cards[i] <= 1e6
题解
题目意思实际上就是求数组中任意2个重复元素的最短距离,没有重复就返回-1;
解题思路:
- 遍历数组cards,使用map存储数组的每个元素,key为元素的值 cards[i],value为元素的下标 i;
- 当map中已经存在对应的key时(即遇到重复元素时),计算当前遍历到的元素的下标与前一个相同元素的下标的差dist
- 判断当前差值与之前的差值ans哪个小,并更新 ans 变量为最小的差值
- 更新map中对应key为当前遍历的元素的下标
class Solution {
public int minimumCardPickup(int[] cards) {
int ans = Integer.MAX_VALUE;
HashMap<Integer,Integer> m = new HashMap<>();
for (int i = 0; i < cards.length; i++) {
if(!m.containsKey(cards[i])){
m.put(cards[i], i);
} else {
int dist = i - m.get(cards[i]) + 1;
ans = Math.min(dist, ans);
m.put(cards[i], i);
}
}
return ans==Integer.MAX_VALUE?-1:ans;
}
}
第4题
6050. 字符串的总引力
字符串的 引力 定义为:字符串中不同字符的数量。
例如,"abbca" 的引力为 3 ,因为其中有 3 个不同字符 'a'、'b' 和 'c' 。
给你一个字符串 s ,返回 其所有子字符串的总引力 。
子字符串定义为:字符串中的一个连续字符序列。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/total-appeal-of-a-string
示例 1:
输入:s = "abbca"
输出:28
解释:"abbca" 的子字符串有:
- 长度为 1 的子字符串:"a"、"b"、"b"、"c"、"a" 的引力分别为 1、1、1、1、1,总和为 5 。
- 长度为 2 的子字符串:"ab"、"bb"、"bc"、"ca" 的引力分别为 2、1、2、2 ,总和为 7 。
- 长度为 3 的子字符串:"abb"、"bbc"、"bca" 的引力分别为 2、2、3 ,总和为 7 。
- 长度为 4 的子字符串:"abbc"、"bbca" 的引力分别为 3、3 ,总和为 6 。
- 长度为 5 的子字符串:"abbca" 的引力为 3 ,总和为 3 。
引力总和为 5 + 7 + 7 + 6 + 3 = 28 。
提示:
1 <= s.length <= 1e5
s 由小写英文字母组成
题解
题解源自作者:endlesscheng
链接:https://leetcode-cn.com/problems/total-appeal-of-a-string/solution/by-endlesscheng-g405/
思路:从左往右遍历 s,将 s[i] 添加到以 s[i-1] 结尾的子串的末尾后,引力值增加多少?
分类讨论:
- 如果 s[i] 之前没有遇到过,那么每个子串的引力值都会增加 1,引力值之和会增加 i,再加上 1,即 s[i] 单独组成的子串的引力值。
- 如果 s[i] 之前遇到过,设其上次出现的下标为 j,那么向子串 s[0...i-1], s[1...i-1], s[2...i-1],...,s[j...i-1] 的末尾添加 s[i]后,引力值是不会变化的,因为 s[i] 已经在 s[j] 处出现过了;而子串 s[j+1...i-1], s[j+2...i-1], ..., s[i-1...i-1] 由于不包含字符 s[i],这些子串的引力值都会增加 1,因此有
i-j-1
个子串的引力值会增加 1,引力值之和会增加i-j-1
,再加上 1,即 s[i] 单独组成的子串的引力值。
模拟上述过程,遍历 s 的过程中用一个变量 sumG 维护以 s[i] 结尾的子串的引力值之和,同时用一个数组 pos 记录每个字符最近一次出现的下标。
累加遍历中的 sumG 即为答案。
public long appealSum(String s) {
long ans = 0L, sumG = 0L;
int[] pos = new int[26];
Arrays.fill(pos, -1);
for (int i = 0; i < s.length(); i++) {
int c = (s.charAt(i) - 'a'); // 把s中的一个字符映射成一个0~25的数字
sumG += i - pos[c]; // pos中值在未被修改之前都是-1,只有遇到重复字符时才会用对应字符的下标(下面第2行代码)覆盖掉-1
ans += sumG;
pos[c] = i;
}
return ans;
}
本文来自博客园,作者:aJream,转载请记得标明出处:https://www.cnblogs.com/ajream/p/16212791.html