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=∑
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)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。