[学习报告]《LeetCode零基础指南》(第六讲) 贪心


解题报告

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

题目链接:1913. 两个数对之间的最大乘积差

题目描述

两个数对 (a, b) 和 (c, d) 之间的 乘积差 定义为 (a * b) - (c * d) 。
例如,(5, 6) 和 (2, 7) 之间的乘积差是 (5 * 6) - (2 * 7) = 16 。
给你一个整数数组 nums ,选出四个 不同的 下标 w、x、y 和 z ,使数对 (nums[w], nums[x]) 和 (nums[y], nums[z]) 之间的 乘积差 取到 最大值
返回以这种方式取得的乘积差中的 最大值

解题思路

数组升序排序,取数组末尾两个下标和开头两个下标。

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

(贴通过的截图)

数组拆分 I

题目链接:561. 数组拆分 I

题目描述

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

解题思路

升序排序,偶数项即为每一对的最小值。

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

(贴通过的截图)

摆动排序 II

题目链接:324. 摆动排序 II

题目描述

给你一个整数数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]… 的顺序。
你可以假设所有输入数组都可以得到满足题目要求的结果。

解题思路

( 1 ) (1) (1) 升序排序数组。
( 2 ) (2) (2) 创建一个临时 vector 容器,初始值为 0。
( 3 ) (3) (3) 将数组值倒序插入奇数位置。
( 4 ) (4) (4) 将数组值倒序插入偶数位置。
( 5 ) (5) (5) 因为没有返回值,所以交换 nums 和 temp。

class Solution {
public:
    void wiggleSort(vector<int>& nums) {
        int r = nums.size() - 1;
        sort(nums.begin(), nums.end());                  //(1)
        vector<int> temp(nums.size(), 0);                //(2)
        for(int i = 1; i < nums.size(); i += 2 ){        //(3)
            temp[i] = nums[r -- ];
        }
        for(int i = 0; i < nums.size(); i += 2){         //(4)  
            temp[i] = nums[r -- ];
        }
        nums.swap(temp);                                 //(5)
    }
};

(贴通过的截图)

分发饼干

题目链接:455. 分发饼干

题目描述

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

解题思路

( 1 ) (1) (1) 双指针,gr 指向 g 数组的最右端,sr 指向 s 数组的最右端。
( 2 ) (2) (2) 两个数组升序排序。
( 3 ) (3) (3) 满足 s[j] >= g[i],gr 和 sr 都向右移一位。
( 4 ) (4) (4) 不满足,gr 右移一位。
( 5 ) (5) (5) 饼干或胃口值枚举完,返回 ans。

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        int gr = g.size() - 1, sr = s.size() - 1;                   //(1)
        int ans = 0;
        sort(g.begin(), g.end());                                   //(2) 
        sort(s.begin(), s.end());
        while(gr >= 0 && sr >= 0){
            if(s[sr] >= g[gr]){                                     //(3)
                ans ++ ;
                gr -- ;
                sr -- ;
            }else{                                                  //(4)
                gr -- ;
            }
        }
        return ans;                                                 //(5)
    }
};

(贴通过的截图)

最少操作使数组递增

题目链接:1827. 最少操作使数组递增

题目描述

给你一个整数数组 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 的数组是严格递增的一种特殊情况。

解题思路

若当前枚举到的数比前一个数小,计算能实现严格递增的最小增值,当前的数 和 ans 都加上这个增值。

class Solution {
public:
    int minOperations(vector<int>& nums) {
        int ans = 0, x = 0;
        for(int i = 1; i < nums.size(); i ++ ){
            if(nums[i] <= nums[i - 1]){
                x = nums[i - 1] - nums[i] + 1;       
                nums[i] += x;
                ans += x;
            }
        }
        return ans;
    }
};

(贴通过的截图)

使数组唯一的最小增量

题目链接:945. 使数组唯一的最小增量

题目描述

给你一个整数数组 nums 。每次 move 操作将会选择任意一个满足 0 <= i < nums.length 的下标 i,并将 nums[i] 递增 1。
返回使 nums 中的每个值都变成唯一的所需要的最少操作次数。

解题思路

要使每个数都唯一,可以将数组升序排序,如果前一个数大于当前的数,则当前的数增加到比前一个数大 1,操作与上一题一样。

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

(贴通过的截图)

有效三角形的个数

题目链接:611. 有效三角形的个数

题目描述

给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。

解题思路

排序 + 双指针
( 1 ) (1) (1) 数组升序排序。
( 2 ) (2) (2) 枚举一条边作为三角形最大的边。
( 3 ) (3) (3) 定义两个指针,j 从 i 的前一位开始向左走,k 从 0 开始向右走。
( 4 ) (4) (4) 当 k 与 j 没有相等且 nums[k] + nums[j] <= nums[i],说明当前 k 指向的边不足以和 j,i 指向的边组成三角形,则 k 向右走取更大的值,直到满足组成三角形的条件。
( 5 ) (5) (5) 当某个 k 满足条件,因为数组升序排序,则 k 一直向右直到 j - 1 指向的边都会满足条件。
( 6 ) (6) (6) j 向左移一位,继续(4)(5)。

class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        int len = nums.size();
        sort(nums.begin(), nums.end());                                 //(1)
        int ans = 0;
        for(int i = 2; i < len; i ++ ){                                 //(2)(6)
            for(int j = i - 1, k = 0; k < j; j -- ){                    //(3)  
                while(k < j && nums[k] + nums[j] <= nums[i]) k ++ ;     //(4)
                ans += j - k;                                           //(5)
            }
        }
        return ans;
    }
};

(贴通过的截图)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值