3.11《LeetCode零基础指南》第六讲贪心学习反思

一、

1913. 两个数对之间的最大乘积差

难度简单15

两个数对 (a, b) 和 (c, d) 之间的 乘积差 定义为 (a * b) - (c * d) 。

  • 例如,(5, 6) 和 (2, 7) 之间的乘积差是 (5 * 6) - (2 * 7) = 16 。

给你一个整数数组 nums ,选出四个 不同的 下标 wxy 和 z ,使数对 (nums[w], nums[x]) 和 (nums[y], nums[z]) 之间的 乘积差 取到 最大值 。

返回以这种方式取得的乘积差中的 最大值 。

class Solution {
public:
    int maxProductDifference(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        if(nums.size()<4)return 0;
        return nums[nums.size()-1]*nums[nums.size()-2]-nums[0]*nums[1];
    }
};
class Solution {
public:
    int maxProductDifference(vector<int>& nums) {

        int Max1 = 0;
        int Max0 = 0;

        int Min0 = 10000000;
        int Min1 = 10000000;
        for(int i=0;i<nums.size();i++)
        {
            if(Max1<nums[i])
            {
                Max0=Max1;
                Max1=nums[i];
            }
            else if(Max0<nums[i])
            Max0=nums[i];
            if(Min0>nums[i])
            {
                Min1=Min0;
                Min0=nums[i];
            }
            else if(Min1>nums[i])Min1=nums[i];
        }
        return Max1*Max0-Min0*Min1;
    }
};

---------------------------------------------------------------------------------------------------------------------------------

二、

561. 数组拆分 I

难度简单286

给定长度为 2n 的整数数组 nums ,你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) ,使得从 1 到 n 的 min(ai, bi) 总和最大。

返回该 最大总和 。

示例 1:

输入:nums = [1,4,3,2]
输出:4
解释:所有可能的分法(忽略元素顺序)为:
1. (1, 4), (2, 3) -> min(1, 4) + min(2, 3) = 1 + 2 = 3
2. (1, 3), (2, 4) -> min(1, 3) + min(2, 4) = 1 + 2 = 3
3. (1, 2), (3, 4) -> min(1, 2) + min(3, 4) = 1 + 3 = 4
所以最大总和为 4

示例 2:

输入:nums = [6,2,6,5,1,2]
输出:9
解释:最优的分法为 (2, 1), (2, 5), (6, 6). min(2, 1) + min(2, 5) + min(6, 6) = 1 + 2 + 6 = 9

排序就完了

class Solution {
public:
    int arrayPairSum(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int num=0;
        for(int i=0;i<nums.size();i=i+2)
        {
            num+=min(nums[i],nums[i+1]);
        }
        return num;
    }
};

---------------------------------------------------------------------------------------------------------------------------------

三、

324. 摆动排序 II

难度中等324

给你一个整数数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]... 的顺序。

你可以假设所有输入数组都可以得到满足题目要求的结果。

示例 1:

输入:nums = [1,5,1,1,6,4]
输出:[1,6,1,5,1,4]
解释:[1,4,1,5,1,6] 同样是符合题目要求的结果,可以被判题程序接受。

示例 2:

输入:nums = [1,3,2,2,3,1]
输出:[2,3,1,3,1,2]
class Solution {
public:
    void wiggleSort(vector<int>& nums) {
        auto midptr = nums.begin() + nums.size() / 2;
        nth_element(nums.begin(), midptr, nums.end());

        int mid=*midptr;
        int i=0,j=0,k=nums.size()-1;
        while(j<k)//乱顺数组,若只有中位数位于中间,则将大于mid的数放在右边,反之;
        {
            if(nums[j]>mid)
            {
                swap(nums[j],nums[k]);
                --k;
            }
            else if(nums[j]<mid)
            {
                swap(nums[i],nums[j]);
                ++i;
                ++j;
            }
            else
            {
                ++j;
            }
        }
        if(nums.size()%2)midptr++;
        vector<int> tmp1(nums.begin(), midptr);
        vector<int> tmp2(midptr, nums.end());
        for(int i = 0; i < tmp1.size(); ++i){
            nums[2 * i] = tmp1[tmp1.size() - 1 - i];
        }
        for(int i = 0; i < tmp2.size(); ++i){
            nums[2 * i + 1] = tmp2[tmp2.size() - 1 - i];
        }
    }
};

几个问题:

1.nth_element()函数

在C++中,可以用STL的nth_element()函数进行快速选择,这一函数的效果是将数组中第n小的元素放在数组的第n个位置,同时保证其左侧元素不大于自身,右侧元素不小于自身。

2.使用三个参数i,j,k来控制数组,第一个if:nums[j]大于mid,则其一定得在右边,与nums[k]交换即可,则nums[k]一定大于0,而nums[j]交换过来的不一定,所以对j不变化;第二个if:nums[j]小于mid,交换i,j,使小于mid的数永远在左边。

3.快速选择算法:

void quickSelect(vector<int> &nums, int begin, int end, int n){
        int t = nums[end - 1];
        int i = begin, j = begin;
        while(j < end){
            if(nums[j] <= t){
                swap(nums[i++], nums[j++]);
            }
            else{
                ++j;
            }
        }
        if(i - 1 > n){
            quickSelect(nums, begin, i - 1, n);
        }
        else if(i <= n){
            quickSelect(nums, i, end, n);
        }
    }

虚地址方法(没搞懂之后学)

class Solution {
public:
    void wiggleSort(vector<int>& nums) {
        int n = nums.size();

        // Find a median.
        auto midptr = nums.begin() + n / 2;
        nth_element(nums.begin(), midptr, nums.end());
        int mid = *midptr;

        // Index-rewiring.
        #define A(i) nums[(1+2*(i)) % (n|1)]

        // 3-way-partition-to-wiggly in O(n) time with O(1) space.
        int i = 0, j = 0, k = n - 1;
        while (j <= k) {
            if (A(j) > mid)
                swap(A(i++), A(j++));
            else if (A(j) < mid)
                swap(A(j), A(k--));
            else
                j++;
        }
    }
};

---------------------------------------------------------------------------------------------------------------------------------

四、

455. 分发饼干

难度简单457

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。

对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

示例 1:

输入: g = [1,2,3], s = [1,1]
输出: 1
解释: 
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。

示例 2:

输入: g = [1,2], s = [1,2,3]
输出: 2
解释: 
你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出2.
class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(g.begin(),g.end());
        sort(s.begin(),s.end());
        int n=0;
        int m=0;
        int count=0;
        while(n<s.size()&&m<g.size())
        {
            if(s[n]>=g[m])
            {
                count++;
                n++;
                m++;
            }
            else if(s[n]<g[m])
            {
                n++;
            }
        }
        return count;
    }
};

---------------------------------------------------------------------------------------------------------------------------------

五、

1827. 最少操作使数组递增

难度简单21

给你一个整数数组 nums (下标从 0 开始)。每一次操作中,你可以选择数组中一个元素,并将它增加 1 。

  • 比方说,如果 nums = [1,2,3] ,你可以选择增加 nums[1] 得到 nums = [1,3,3] 。

请你返回使 nums 严格递增 的 最少 操作次数。

我们称数组 nums 是 严格递增的 ,当它满足对于所有的 0 <= i < nums.length - 1 都有 nums[i] < nums[i+1] 。一个长度为 1 的数组是严格递增的一种特殊情况。

示例 1:

输入:nums = [1,1,1]
输出:3
解释:你可以进行如下操作:
1) 增加 nums[2] ,数组变为 [1,1,2] 。
2) 增加 nums[1] ,数组变为 [1,2,2] 。
3) 增加 nums[2] ,数组变为 [1,2,3] 。

示例 2:

输入:nums = [1,5,2,4,1]
输出:14

示例 3:

输入:nums = [8]
输出:0
class Solution {
public:
    int minOperations(vector<int>& nums) {
        if(nums.size()==1)return 0;
        int key=nums[0];
        int cishu=0;
        for(int i=1;i<nums.size();i++)
        {
            if(nums[i]<key)
            {
                int t=key-nums[i]+1;
                cishu+=t;
                key=key+1;
            }
            else if(nums[i]>key)
            {
                key=nums[i];
            }
            else
            {
                cishu++;
                key++;
            }
        }
        return cishu;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值