题目1:
[可运行]最直观的想法:将字符串中等于digit的位置对应字符删除,并将结果都存入一个res中,通过排序找出删除字符后值最大的字符串。
class Solution {
public:
string removeDigit(string number, char digit) {
vector<string> res;
for(int i = 0; i < number.size(); i ++)
if(number[i] == digit){
string tmp = number;
tmp.erase(i,1);
res.push_back(tmp);
}
sort(res.begin(), res.end());
return res[res.size()-1];
}
};
题目2:
[可运行]这道题实际上是寻找整个数组中距离最近的两个元素之间的距离,所以只需要不断记录元素上一次出现的位置,拿当前位置与上一次出现的位置做长度计算,不断用最小长度来更新结果。
class Solution {
public:
int minimumCardPickup(vector<int>& cards) {
unordered_map<int,int> prevs;
int result = INT_MAX;
for(int i = 0; i < cards.size(); i++){
//cards[i]在之前的位置出现过
if(prevs.count(cards[i]))
//计算cards[i]距离上一次出现的距离,如果小于现存结果则更新
result = min(result, i - prevs[cards[i]] + 1);
prevs[cards[i]] = i; //更新cards[i]出现的索引
}
return result == INT_MAX ? -1 : result;
}
};
题目3:
[可运行]数组哈希+滑动窗口,因为题目要求的是连续的子数组,所以通过滑动窗口来选取符合不大于k个能整除p的一个窗口,窗口内的所有子数组都符合要求,最后用哈希表来确保子数组的唯一性。返回哈希表的长度就是符合要求的所有子数组的数量。
class Solution {
public:
int countDistinct(vector<int>& nums, int k, int p) {
set<vector<int>> subarrays;
int left = 0, right = 0;
int count = 0; //窗口内可以整除p的数字的个数
while(right < nums.size()){
//可以整除p的数字
if(nums[right] % p == 0) count ++;
//可以整除p的数字数量大于k,调整窗口到合理大小
while(left <= right && count > k){
if(nums[left] % p == 0) count --;
left ++;
}
//不重复的子数组加入set
for(int i = left; i <= right; i ++)
subarrays.insert(vector<int>(nums.begin() + i, nums.begin() + right + 1));
right ++;
}
return subarrays.size();
}
};
题目4:
[超时]直观的想法,穷举所有可能的字符串,然后统计求和每个字符串中的引力。果不其然,遇到很长的字符串会超时。
class Solution {
public:
long long appealSum(string s) {
long long count = 0;
for(int i = 0; i < s.size(); i ++)
for(int j = 1; j <= s.size() - i; j ++){
//穷举所有子字符串
string tmp = s.substr(i, j);
//求和引力
count += theNumOfCharacters(tmp);
}
return count;
}
//统计字符串中出现的不同字符的个数
int theNumOfCharacters(string& s){
int count = 0;
bool arr[26] = {0};
for(int i = 0; i < s.size(); i ++) arr[s[i] - 'a'] = true;
for(int i = 0; i < 26; i ++) count += arr[i];
return count;
}
};
[可运行]对于当前字符,从它的上一个相同字符的下一个索引到当前字符,该字符的增加会对包括当前字符在内的新构成的i - prevs[idx]个字符串分别贡献一个引力值。我们每次将引力值累积。
很多题还是要学着变换思维,我老是题上说什么我就怎么跟着做。
class Solution {
public:
long long appealSum(string& s) {
//取值-1为字符第一次出现计算引力值+1
vector<int> prevs(26, -1);
long long res = 0;
//考虑字符s[i],它前面一个相同字符的索引为prev
for (int i = 0, sum = 0; i < s.size(); i ++) {
int idx = s[i] - 'a';
//在区间[prev + 1, i]会为包含s[i]在内的i - prevs[idx]个字符串各贡献一个引力值
sum += i - prevs[idx];
res += sum; //将每一个字符的贡献汇总
prevs[idx] = i; //更新当前字符的索引
}
return res;
}
};