1. K次取反后最大化的数组和
这个题目的贪心就体现在最小的负数取反之后对整个数组和的贡献是最大的,直接上思路:
直接上代码:
cpp
class Solution {
public:
int largestSumAfterKNegations(vector<int>& nums, int k) {
int m = 0;
int n = nums.size();
int minNum = INT_MAX;
int ret = 0;
for(auto& e : nums)
{
if(e < 0) m++;
minNum = min(minNum, abs(e)); // 求绝对值最小元素
}
// 分类讨论
if(m > k)
{
sort(nums.begin(), nums.end());
for(int i = 0; i < k; i++) // 前k⼩个负数,变成正数
{
ret += -nums[i];
}
for(int i = k; i < n; i++) // 后⾯的数不变
{
ret += nums[i];
}
}
else
{
// 把所有的负数变成正数
for(auto x : nums) ret += abs(x);
if((k - m) % 2 != 0) // 判断是否处理最⼩的正数
{
ret -= minNum * 2;
}
}
return ret;
}
};
2. 按身高排序
这个题目比较简单,按照贪心的思想我们只需要按照身高的最大值排序即可,但是仍有一些细节问题,我们不能直接按照i位置对应的heights来排序,因为排序过程是会移动元素的,但是names内的元素是不会移动的。由题意可知,names 数组和heights数组的下标是一一对应的, 因此我们可以重新创建出来一个下标数组,将这个下标数组按照heights[i]的大小排序。那么,当下标数组排完序之后,里面的顺序就相当于heights这个数组排完序之后的下标。之后通过排序后的下标,依次找到原来的name,完成对名字的排序。
直接上代码:
cpp
class Solution{
public:
vector<string> sortPeople(vector<string>& names, vector<int>& heights)
{
// 1. 创建⼀个下标数组
int n = names.size();
vector<int> index(n);
for (int i = 0; i < n; i++) index[i] = i;
// 2. 对下标进⾏排序
sort(index.begin(), index.end(), [&](int i, int j)
{
return heights[i] > heights[j];
});
// 3. 提取结果
vector<string> ret;
for (int i : index)
{
ret.push_back(names[i]);
}
return ret;
}
};
3.优势洗牌(田忌赛马)
此时我们有了这个概念,我们就来模拟一遍流程
直接上代码:
cpp
class Solution {
public:
vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2) {
vector<int> index(nums1.size());
// 1.排序
for(int i = 0; i < nums1.size(); i++)
index[i] = i;
sort(nums1.begin(), nums1.end());
sort(index.begin(), index.end(), [&](int x, int y)
{
return nums2[x] < nums2[y];
});
// 田忌赛马
int left = 0;
int right = nums1.size() - 1;
vector<int> ret(nums1.size());
for(auto e : nums1)
{
// index[left] 代表最小值的下标
// nums2[index[left]] 代表nums2中的最小值
if(e > nums2[index[left]]) ret[index[left++]] = e;
// index[right] 代表最大值的下标
// ret[index[right]] 代表nums2中的最大值
else ret[index[right--]] = e;
}
return ret;
}
};
4.最长回文串
这个题目比较简单,根据回文串的特点,我们只需要统计字符出现的次数,再判断奇数和偶数的情况即可,直接上思路:
直接上代码:
cpp
class Solution{
public:
int longestPalindrome(string s){
// 1. 计数-⽤数组模拟哈希表
int hash[127] = { 0 };
for (char ch : s) hash[ch]++;
// 2. 统计结果
int ret = 0;
for (int x : hash)
{
ret += x / 2 * 2;
}
return ret < s.size() ? ret + 1 : ret;
}
};
5. 增减字符串匹配
⭐贪心策略算法思路:
- a. 当遇到 "I" 的时候,为了让下⼀个上升的数可选择的「范围更多」,当前选择「最小」的那 个数;
- b. 当遇到 "D" 的时候,为了让下⼀个下降的数可选择的「范围更多」,选择当前「最大」的那 个数。
直接上代码:
cpp
class Solution
{
public:
vector<int> diStringMatch(string s)
{
int left = 0, right = s.size(); // 用left,right标记最小值和最⼤值
vector<int> ret;
for (auto ch : s)
{
if (ch == 'I') ret.push_back(left++);
else ret.push_back(right--);
}
ret.push_back(left); // 把最后⼀个数放进去
return ret;
}
};