贪心算法专题练习

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数组的下标是一一对应的, 因此我们可以重新创建出来一个下标数组,将这个下标数组按照heightsi的大小排序。那么,当下标数组排完序之后,里面的顺序就相当于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;
	}
};
相关推荐
科学实验家29 分钟前
二叉树的几道题
算法
abcy0712131 小时前
flink state实例
大数据·算法·flink
qizayaoshuap1 小时前
# [特殊字符] 密码生成器 — 鸿蒙ArkTS安全算法与密码强度评估系统
java·算法·安全·华为·harmonyos
良木林1 小时前
滑动窗口 - LeetCode hot 100
javascript·算法·leetcode·双指针·滑动窗口
2401_841495641 小时前
【数据结构】B*树
数据结构·c++·b树·算法·删除·插入·三分分裂
QXWZ_IA3 小时前
**电力登高作业高空失保实时监管:千寻智能安全带高挂低用监测方案**
人工智能·科技·算法·能源·智能硬件
爱刷碗的苏泓舒3 小时前
FFRT:固定失败率比率检验、宽巷模糊度固定及 Ratio Test
算法·相位偏差·模糊度固定·ppp-ar·ffrt·ratio test·wlnl
小园子的小菜3 小时前
深入理解 JVM 垃圾回收:从对象判定、回收算法到经典收集器全解析
jvm·算法
2601_954526753 小时前
【硬核长文】从卡门涡街物理方程到边缘网关温压补偿算法:工业蒸汽测控实战,深度解密靠谱的涡街流量计厂家有哪些
算法
吞下星星的少年·-·4 小时前
牛客技能树:区间翻转
算法·滑动窗口