做题记录——贪心

1. lc1403:非递增顺序的最小子序列(2022/8/4)

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-subsequence-in-non-increasing-order

题目

给你一个数组 nums,请你从中抽取一个子序列,满足该子序列的元素之和 严格 大于未包含在该子序列中的各元素之和。

如果存在多个解决方案,只需返回 长度最小 的子序列。如果仍然有多个解决方案,则返回 元素之和最大 的子序列。

与子数组不同的地方在于,「数组的子序列」不强调元素在原数组中的连续性,也就是说,它可以通过从数组中分离一些(也可能不分离)元素得到。

注意,题目数据保证满足所有约束条件的解决方案是 唯一 的。同时,返回的答案应当按 非递增顺序 排列。

示例 :

输入:nums = [4,3,10,9,8]
输出:[10,9] 
解释:子序列 [10,9] 和 [10,8] 是最小的、满足元素之和大于其他各元素之和的子序列。但是 [10,9] 的元素之和最大。 

思路

要返回长度最小且元素之和最大的子序列,显然需要采用贪心的思想,将数组排序后,从大到小把元素取出,直到子序列的元素之和严格大于剩下元素之和。

代码:

class Solution {
public:
    vector<int> minSubsequence(vector<int>& nums) {
        vector<int>ans;
        sort(nums.begin(),nums.end());
        int sum=accumulate(nums.begin(),nums.end(),0),tmp=0;
        int size=nums.size(),i;
        for(i=size-1;i>=0;i--){
            tmp+=nums[i];
            ans.push_back(nums[i]);
            if(sum-tmp<tmp) break;
        }
        return ans;
    }
};

2.lc1413:逐步求和得到正数的最小值(2022/8/9)

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-value-to-get-positive-step-by-step-sum

题目:给你一个整数数组 nums 。你可以选定任意的 正数 startValue 作为初始值。

你需要从左到右遍历 nums 数组,并将 startValue 依次累加上 nums 数组中的值。

请你在确保累加和始终大于等于 1 的前提下,选出一个最小的 正数 作为 startValue 。

示例

输入:nums = [-3,2,-3,4,2]
输出:5
解释:如果你选择 startValue = 4,在第三次累加时,和小于 1 。
                累加求和
                startValue = 4 | startValue = 5 | nums
                  (4 - 3  ) = 1    | (5 - 3  ) = 2    |  -3
                  (1 +2  ) = 3    | (2 +2  ) = 4    |   2
                  (3 - 3  ) = 0    | (4 - 3  ) = 1    |  -3
                  (0 +4  ) = 4    | (1 +4  ) = 5    |   4
                  (4 +2  ) = 6    | (5 +2  ) = 7    |   2

思路:采用贪心的思想,把累加过程中的最小值记录下来,则startValue只需要等于最小值的相反数加一。一个注意点是,startValue必须是正数,所以可以把最小值的初始值设为0,当累加的最小值大于0时,返回1(-0+1)即可。

代码

class Solution {
public:
    int minStartValue(vector<int>& nums) {
        int min=0,sum=0;
        for(int num:nums){
            sum+=num;
            if(sum<min) min=sum;
        }
        return min*-1+1;
    }
};

3.lc670:最大交换(2022/9/13)

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/maximum-swap

题目:给定一个非负整数,你至多可以交换一次数字中的任意两位。返回你能得到的最大值。

示例 :

输入: 2736
输出: 7236
解释: 交换数字2和数字7

思路:【官方题解】

设整数 num 从右向左的数字分别为 (d 
0

 ,d 
1

 ,d 
2

 ,⋯,d 
n−1

 ),则此时我们可以知道: num=∑ val=\sum_{i=0}^{n-1}(d_{i}\times10^{i} )+(d_{j}-d_{k})\times10^{k} -(d_{j}-d_{k})\times10^{j} =\sum_{i=0}^{n-1}(d_{i}\times10^{i} )+(d_{j}-d_{k})\times(10^{k}-10^{j})
i=0
n−1

 d 
i

 ×10 
i
 ,假设我们对位于 j,k 位上的数字进行交换,其中满足 0≤j<k<n,则可以知道交换后的值 val 如下:

\text{val} = \sum_{i=0}^{n-1} (d_{i} \times 10^{i}) + (d_j - d_k) \times 10 ^ k - (d_j - d_k) \times 10 ^ j \\ = \sum_{i=0}^{n-1} (d_{i} \times 10^{i}) + (d_j - d_k) \times (10 ^ k - 10 ^ j)
val= 
i=0

n−1

 (d 
i

 ×10 
i
 )+(d 
j

 −d 
k

 )×10 
k
 −(d 
j

 −d 
k

 )×10 
j
 

i=0

n−1

 (d 
i

 ×10 
i
 )+(d 
j

 −d 
k

 )×(10 
k
 −10 
j
 )

根据以上等式我们可以看出,若使得 \textit{val}val 的值最大,应依次满足如下条件:

最优的交换一定需要满足 d_j > d_kd 
j

 >d 
k

 ;
在满足 d_j > d_kd 
j

 >d 
k

  时,应该保证索引 kk 越大从而使得数字 \textit{val}val 越大;
在同样大小的数字 d_kd 
k

  时,应使得数字 d_jd 
j

  越大从而使得 \textit{val}val 越大;
在同样大小的数字 d_jd 
j

  时,应使得索引 jj 越小从而使得 \textit{val}val 越大;
通过以上可以观察到右边越大的数字与左边较小的数字进行交换,这样产生的整数才能保证越大。因此我们可以利用贪心法则,尝试将数字中右边较大的数字与左边较小的数字进行交换,这样即可保证得到的整数值最大。具体做法如下:

我们将从右向左扫描数字数组,并记录当前已经扫描过的数字的最大值的索引为 \textit{maxId}maxId 且保证 \textit{maxId}maxId 越靠近数字的右侧,此时则说明 \textit{charArray}[\textit{maxId}]charArray[maxId] 则为当前已经扫描过的最大值。
如果检测到当前数字 \textit{charArray}[i] < \textit{charArray}[\textit{maxId}]charArray[i]<charArray[maxId],此时则说明索引 ii 的右侧的数字最大值为 \textit{charArray}[\textit{maxId}]charArray[maxId],此时我们可以尝试将 \textit{charArray}[i]charArray[i] 与 \textit{charArray}[\textit{maxId}]charArray[maxId] 进行交换即可得到一个比 \textit{num}num 更大的值。我们尝试记录当前可以交换的数对 (i, \textit{maxId})(i,maxId),根据贪心法则,此时最左边的 ii 构成的可交换的数对进行交换后形成的整数值最大。

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/maximum-swap/solution/zui-da-jiao-huan-by-leetcode-solution-lnd5/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值