贪心算法专题练习

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;
	}
};
相关推荐
DuHz5 小时前
论文精读:大语言模型 (Large Language Models, LLM) —— 一项调查
论文阅读·人工智能·深度学习·算法·机器学习·计算机视觉·语言模型
加农炮手Jinx5 小时前
LeetCode 72. Edit Distance 题解
算法·leetcode·力扣
借雨醉东风5 小时前
程序分享--常见算法/编程面试题:旋转矩阵
c++·线性代数·算法·面试·职场和发展·矩阵
_深海凉_5 小时前
LeetCode热题100-打家劫舍
算法·leetcode·职场和发展
jghhh016 小时前
使用 MATLAB 实现支持向量回归 (SVR) 预测未来数据
算法·matlab
云泽8086 小时前
笔试算法 - 双指针篇(二):四大经典求和题型 + 有效三角形计数问题
c++·算法
刀法如飞7 小时前
【合并已排序数组的三种实现策略,哪一种更可取?】
算法·程序员
王老师青少年编程8 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【区间贪心】:种树
c++·算法·贪心·csp·信奥赛·区间贪心·种树
hi_ro_a8 小时前
C++ 哈希表封装 unordered_map /unordered_set
数据结构·c++·算法·哈希算法
Jasmine_llq12 小时前
《B4447 [GESP202512 二级] 环保能量球》
数据结构·算法·数学公式计算(核心)·整数除法算法·多组数据循环处理·输入输出算法·简单模拟算法