贪心算法,先从后往前找到第一个可以变的位置,然后在从该位置往后找到最大的值进行调整
class Solution {
public:
vector<int> prevPermOpt1(vector<int>& arr) {
int n = arr.size(), idx = -1;
for(int i=n-1; i>=1; i--){
if(arr[i] < arr[i-1]){
idx = i-1;
break;
}
}
if(idx == -1) return arr;
int maxv = 0, t = arr[idx], pos = idx;
for(int i = idx+1; i<n; i++){
if(arr[i] < arr[idx]){
if(arr[i] > maxv){
maxv = arr[i];
pos = i;
}
}
}
swap(arr[idx], arr[pos]);
return arr;
}
};
哈希+堆
class Solution {
public:
vector<int> rearrangeBarcodes(vector<int>& barcodes) {
unordered_map<int,int>num2cnt;
int n=barcodes.size();
for(int i=0;i<n;i++){
num2cnt[barcodes[i]]++;
}
priority_queue<pair<int,int>>maxHeap;
for(auto mPair:num2cnt)maxHeap.push({mPair.second,mPair.first});
vector<int>ans;
while(maxHeap.empty()==false){
auto [firstCnt,firstNum]=maxHeap.top();maxHeap.pop();
if(ans.empty()||ans.back()!=firstNum){
ans.push_back(firstNum);
firstCnt--;
if(firstCnt==0)continue;
maxHeap.push({firstCnt,firstNum});
}else {
auto [secondCnt,secondNum]=maxHeap.top();maxHeap.pop();
maxHeap.push({firstCnt,firstNum});
ans.push_back(secondNum);
secondCnt--;
if(secondCnt==0)continue;
maxHeap.push({secondCnt,secondNum});
}
}
return ans;
}
};
字符串两种顺序拼接后相等,则一定是可以找到公共子串,然后求其长度的公约数,即为最大字串。
class Solution {
public:
string gcdOfStrings(string str1, string str2) {
if (str1 + str2 != str2 + str1) return "";
return str1.substr(0, __gcd((int)str1.length(), (int)str2.length())); // __gcd() 为c++自带的求最大公约数的函数
}
};
1、每一行都是一个0-1串,计算各行的特征,特征可以用字符串形式表示
2、建立哈希表,key为特征值,value为特征是key的行的个数
3、最大的value即为所求
class Solution {
public:
int maxEqualRowsAfterFlips(vector<vector<int>>& matrix) {
int m=matrix.size(), n=matrix[0].size();
unordered_map<string, int> map; // 统计具有某特征的行的个数
for(int i=0;i<m;++i){
string feature; // 特征以字符串表示
for(int j=0;j<n;++j)
feature.push_back(matrix[i][j]);
// 若当前行的首位为0,需要进行翻转
if(feature[0]==0){
for(int j=0;j<n;++j)
feature[j]=1-feature[j];
}
++map[feature]; // 计数
}
int ans=0;
for(auto p:map)
ans=max(ans, p.second);// 取最大值
return ans;
}
};
class Solution {
public:
vector<int> addNegabinary(vector<int>& arr1, vector<int>& arr2) {
int n1 = arr1.size();
int n2 = arr2.size();
int n = max(n1,n2)+4;
vector<int> res(n, 0);
// 和arr1和arr2 倒序的计算,低位在前面
for (int i = n1-1; i >= 0; --i)
{
res[n1-1-i] += arr1[i];
}
for (int i = n2-1; i >= 0; --i)
{
res[n2-1-i] += arr2[i];
}
// 从低位开始计算
for (int i = 0; i +2 < n; ++i)
{
// 进位
int carry = res[i] >> 1;
res[i] &= 1;
res[i+1] += carry;
res[i+2] += carry;
}
// 观察最高位连续零需要移除
int k = n-3;
// 这里结束是0,来避免0,0->空的情况
while (k > 0 && res[k] == 0)
{
--k;
}
reverse(res.begin(), res.begin()+k+1);
// 移除末尾的为0的部分
int i = n-k-1;
while(i > 0)
{
--i;
res.pop_back();
}
return res;
}
};
前缀和的二维应用
class Solution {
private:
int subarraySum(vector<int> &nums, int k) {
unordered_map<int, int> mp;
mp[0] = 1;
int count = 0, pre = 0;
for (auto &x:nums) {
pre += x;
if (mp.find(pre - k) != mp.end()) {
count += mp[pre - k];
}
mp[pre]++;
}
return count;
}
public:
int numSubmatrixSumTarget(vector<vector<int>> &matrix, int target) {
int ans = 0;
int m = matrix.size(), n = matrix[0].size();
for (int i = 0; i < m; ++i) { // 枚举上边界
vector<int> sum(n);
for (int j = i; j < m; ++j) { // 枚举下边界
for (int c = 0; c < n; ++c) {
sum[c] += matrix[j][c]; // 更新每列的元素和
}
ans += subarraySum(sum, target);
}
}
return ans;
}
};
先按空格分组单词,然后遍历即可
class Solution {
public:
vector<string> findOcurrences(string text, string first, string second) {
vector<string> words;
int s = 0, e = 0, len = text.length();
while (true) {
while (s < len && text[s] == ' ') {
s++;
}
if (s >= len) {
break;
}
e = s + 1;
while (e < len && text[e] != ' ') {
e++;
}
words.push_back(text.substr(s, e - s));
s = e + 1;
}
vector<string> ret;
for (int i = 2; i < words.size(); i++) {
if (words[i - 2] == first && words[i - 1] == second) {
ret.push_back(words[i]);
}
}
return ret;
}
};