贪心算法(4)

题一.K次取反后最大化的数组和(LeetCode)

题目描述

给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组:

  • 选择某个下标 i 并将 nums[i] 替换为 -nums[i]

重复这个过程恰好 k 次。可以多次选择同一个下标 i

以这种方式修改数组后,返回数组 可能的最大和
示例 1:

输入: nums = 4,2,3, k = 1
输出: 5
**解释:**选择下标 1 ,nums 变为 4,-2,3

示例 2:

输入: nums = 3,-1,0,2, k = 3
输出: 6
**解释:**选择下标 (1, 2, 2) ,nums 变为 3,1,0,2

示例 3:

输入: nums = 2,-3,-1,5,-4, k = 2
输出: 13
**解释:**选择下标 (1, 4) ,nums 变为 2,3,-1,5,4

题目分析

由于我们希望数组的和尽可能大,因此除非万不得已,我们应当总是修改负数,并且优先修改值最小的负数。因为将负数 −x 修改成 x 会使得数组的和增加 2x,所以这样的贪心操作是最优的。

题解

cpp 复制代码
class Solution {
public:
	int largestSumAfterKNegations(vector<int>& nums, int k) {
		int m = 0;
		int ret = 0;
		for (auto x : nums)
		{
			if (x < 0) m++;
		}
		sort(nums.begin(), nums.end());
		if (k > m)
		{
			for (int i = 0; i < m; i++)
			{
				nums[i] *= -1;
			}
			sort(nums.begin(), nums.end());
			for (int i = 0; i < k - m; i++)
			{
				nums[0] *= -1;
			}
		}
		else
		{
			for (int i = 0; i < k; i++)
			{
				nums[i] *= -1;
			}
		}
		for (auto x : nums)
		{
			ret += x;
		}
		return ret;
	}
};

题二.按身高排序(LeetCode)

题目描述

给你一个字符串数组 names ,和一个由 互不相同 的正整数组成的数组 heights 。两个数组的长度均为 n

对于每个下标 inames[i]heights[i] 表示第 i 个人的名字和身高。

请按身高 降序 顺序返回对应的名字数组 names
示例 1:

输入: names = "Mary","John","Emma", heights = 180,165,170
输出: "Mary","Emma","John"
**解释:**Mary 最高,接着是 Emma 和 John 。

示例 2:

输入: names = "Alice","Bob","Bob", heights = 155,185,150
输出: "Bob","Alice","Bob"
**解释:**第一个 Bob 最高,然后是 Alice 和第二个 Bob 。

题解一.哈希表

cpp 复制代码
class Solution1 {
public:
	vector<string> sortPeople(vector<string>& names, vector<int>& heights) {
		map<int, string> hash;
		vector<string> ans;
		for (int i = 0; i < names.size(); ++i) hash[heights[i]] = names[i];
		for (auto &i : hash) ans.push_back(i.second);
		reverse(ans.begin(), ans.end());
		return ans;
	}
};

*题解二.对下标排序

1.创建一个下标数组。

2.仅需对下标数组排序。

3.根据下标数组排序后的结果,找到原数组的信息。

cpp 复制代码
class Solution2 {
public:
	vector<string> sortPeople(vector<string>& names, vector<int>& heights) {
		int n = names.size();
		vector<int> index(n);
		for (int i = 0; i < n; i++) index[i] = i;
		sort(index.begin(), index.end(), [&](int i, int j)
		{
			return heights[i] > heights[j];
		});
		vector<string> ret;
		for (int i : index)
		{
			ret.push_back(names[i]);
		}
		return ret;
	}
};

**题三.优势洗牌(LeetCode)

题目描述

给定两个长度相等的数组 nums1nums2nums1 相对于 nums2优势 可以用满足 nums1[i] > nums2[i] 的索引 i 的数目来描述。

返回 nums1 的任意 排列,使其相对于 nums2 的优势最大化。
示例 1:

输入: nums1 = 2,7,11,15, nums2 = 1,10,4,11
输出:2,11,7,15

示例 2:

输入: nums1 = 12,24,8,32, nums2 = 13,25,32,11
输出:24,32,8,12

题目分析

先把nums1从小到大排序,并把nums2下标排序(因为需要num2原数组的信息)

然后将nums1与nums2比较,采用left、right双指针进行比较。

  • 比不过,就去拖累最大的一个。
  • 能比过,则直接比

需要注意的是,nums2的调用方式 nums2index2\[i]。

题解

cpp 复制代码
class Solution {
public:
    vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2) {
        int n=nums1.size();
        sort(nums1.begin(),nums1.end());
        vector<int> index2(n);
        for(int i=0;i<n;i++) index2[i]=i;
        sort(index2.begin(),index2.end(),[&](int i,int j)
        {
            return nums2[i]<nums2[j];
        });

        vector<int> ret(n);
        int left=0,right=n-1;
        for(auto x : nums1)
        {
            if(x>nums2[index2[left]]) ret[index2[left++]]=x;
            else ret[index2[right--]]=x;
        }
        return ret;
    }
};
相关推荐
淡海水3 小时前
07-04-并发-ConcurrentBag-T-工作窃取WorkStealing算法
开发语言·算法·c#·bag·concurrent·workstealing
leobertlan4 小时前
好玩系列:训练一个神经网络模型指导小孩玩游戏2-大局观教练
算法
Tisfy4 小时前
LeetCode 3876.构造奇偶一致的数组 II:三种情况分类讨论(其实还是脑筋急转弯)
算法·leetcode·题解·脑筋急转弯
乐迪信息5 小时前
智慧港口船舶AI算法实现在线状态监测
大数据·人工智能·深度学习·算法·计算机视觉
木井巳7 小时前
【BFS/DFS 解决 FloodFill 算法】太平洋大西洋水流问题
java·算法·leetcode·深度优先·广度优先·宽度优先·推荐算法
心抵鹊7 小时前
归并排序之翻转对(hard)
数据结构·算法
白山编程大哥7 小时前
Java 集合算法:从排序、查找到底层原理的实战指南
java·python·算法
_Twink1e7 小时前
openJiuwen 实训营 Day 1 · WorkSwarm 入门教程
开发语言·c++·openjiuwen
shehuiyuelaiyuehao7 小时前
算法34,位运算符操作,总结
算法
FfHUCisI8 小时前
Golang Map 哈希表实现
golang·哈希算法·散列表