九日集训第六日(贪心)

一、前言

九日集训第六日

二、题目

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

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

1.a)题目分析:

  首先将数组排序,由贪心思想可知,当 ( n u m s [ w ] , n u m s [ x ] ) (nums[w], nums[x]) (nums[w],nums[x])取最大值且 ( n u m s [ y ] , n u m s [ z ] ) (nums[y], nums[z]) (nums[y],nums[z]) 取最小值时,返回值为成绩差的最大值。

1.b)代码:
class Solution {
    public int maxProductDifference(int[] nums) {
        int w,x,y,z=0;
        int n =nums.length;
        int ans =0;
        Arrays.sort(nums);
        w=n-1;
        x=n-2;
        y=1;
        z=0;
       ans=(nums[w] * nums[x])-(nums[y] * nums[z]);
       return ans;
    }
}

2)976. 三角形的最大周长

  给定由一些正数(代表长度)组成的数组 n u m s nums nums ,返回 由其中三个长度组成的、面积不为零的三角形的最大周长 。如果不能形成任何面积不为零的三角形,返回 0 0 0

2.a)题目分析:

  跟昨天题目相似,在此不在赘述。

2.b)代码:
class Solution {
    public int largestPerimeter(int[] nums) {
        int n =nums.length;
        Arrays.sort(nums);
        int ans=0;
        for(int i=n-1;i>=2;--i){
            if(nums[i]<nums[i-1]+nums[i-2]){
                ans=nums[i]+nums[i-1]+nums[i-2];
                return ans;         
            }
        }
     return 0;   
    }
}

3)561. 数组拆分 I

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

3.a)题目分析:

  首先将数组排序,由于要返回这些对的最大值,从贪心思想可得,当对数返回的最小值的下标是排序后的数组中的偶数时,返回最大值。

3.b)代码:
class Solution {
    public int arrayPairSum(int[] nums) {
        int n= nums.length;
        int ans=0;
        Arrays.sort(nums);
        for(int i =0;i<n;i+=2){
            ans+=nums[i];
        }
        return ans;
    }
}

4)881. 救生艇

  给定数组 p e o p l e people people p e o p l e [ i ] people[i] people[i]表示第 i i i 个人的体重 ,船的数量不限,每艘船可以承载的最大重量为 l i m i t limit limit。每艘船最多可同时载两人,但条件是这些人的重量之和最多为 l i m i t limit limit。返回 承载所有人所需的最小船数 。

4.a)题目分析:

  跟昨天题目相似,在此不在赘述。

4.b)代码:
class Solution {
    public int numRescueBoats(int[] people, int limit) {
        int i ;
        int l=0,r=people.length-1;
        int ans =0;
        Arrays.sort(people);
        while(l<=r){
            if(l==r){
                ++ans;
                break;
            }
            else if(people[l]+people[r]>limit){
                ++ans;
                r--;
            }
            else{
                ++ans;
                ++l;
                --r;
            }
        }
        return ans;
    }
}

5)324. 摆动排序 II

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

5.a)题目分析:

  本题为无返回值的排序,所以可以将数组拷贝出来,再拷贝出来的数组中进行排序,然后将排序后的数组重新插入原数组。

5.b)代码:
class Solution {
    public void wiggleSort(int[] nums) {
        int l,r;
        int n =nums.length;
        int ret[]=new int [n];
        for(int i=0;i<n;i++){
            ret[i]=nums[i];
        }
        Arrays.sort(ret);
        r=n-1;
        for(int i=1;i<n;i+=2){
            nums[i]=ret[r--];
        }
        for(int i=0;i<n;i+=2){
            nums[i]=ret[r--];
        }
    }
}

6)455. 分发饼干

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

6.a)题目分析:

   可以先将两个数组排序,然后遍历数组,将两个数组进行对比,如果满足 s [ j ] > = g [ i ] s[j] >= g[i] s[j]>=g[i],则都向后移动一位,如果不满足,则 g [ ] g[ ] g[]向后移动一位。

6.b)代码:
class Solution {
    public int findContentChildren(int[] g, int[] s) {
        Arrays.sort(g);
        Arrays.sort(s);
        int i =g.length-1;
        int j =s.length-1;
        int ans =0;
        while(i>=0&&j>=0){
            if(s[j]>=g[i]){
                --i;
                --j;
                ans++;
            }
            else
                --i;
        }
        return ans;
    }
}

7)1827. 最少操作使数组递增

  给你一个整数数组 n u m s nums nums (下标从 0 0 0 开始)。每一次操作中,你可以选择数组中一个元素,并将它增加 1 1 1 。比方说,如果 n u m s = [ 1 , 2 , 3 ] nums = [1,2,3] nums=[1,2,3] ,你可以选择增加 n u m s [ 1 ] nums[1] nums[1] 得到 n u m s = [ 1 , 3 , 3 ] nums = [1,3,3] nums=[1,3,3] 。请你返回使 n u m s nums nums 严格递增 的 最少 操作次数。
  我们称数组 n u m s nums nums 是 严格递增的 ,当它满足对于所有的 0 < = i < n u m s . l e n g t h − 1 0 <= i < nums.length - 1 0<=i<nums.length1 都有 n u m s [ i ] < n u m s [ i + 1 ] nums[i] < nums[i+1] nums[i]<nums[i+1] 。一个长度为 1 1 1 的数组是严格递增的一种特殊情况。

7.a)题目分析:

   遍历数组,如果满足 n u m s [ i ] < n u m s [ i + 1 ] nums[i] < nums[i+1] nums[i]<nums[i+1]则向下移动一位,如果不满足,则将 n u m s [ i + 1 ] nums[i+1] nums[i+1]加上 a n s ans ans 1 1 1

7.b)代码:
class Solution {
    public int minOperations(int[] nums) {
        int n =nums.length;
        int ans =0;
        int temp =nums[0]+1;
        for(int i =1;i<n;i++){
            if(temp<nums[i]){
                temp=nums[i]+1;
            }
            else{
                ans+=temp-nums[i];
                temp++;
            }
        }
        return ans;
    }
}

8)945. 使数组唯一的最小增量

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

8.a)题目分析:

  本题与上题类似。

8.b)代码:
class Solution {
    public int minIncrementForUnique(int[] nums) {
        Arrays.sort(nums);
        int ans = 0, taken = 0;

        for (int i = 1; i < nums.length; ++i) {
            if (nums[i - 1] == nums[i]) {
                taken++;
                ans -= nums[i];
            } else {
                int give = Math.min(taken, nums[i] - nums[i - 1] - 1);
                ans += give * (give + 1) / 2 + give * nums[i - 1];
                taken -= give;
            }
        }

        if (nums.length > 0) {
            ans += taken * (taken + 1) / 2 + taken * nums[nums.length - 1];
        }

        return ans;
    }
}

9)611. 有效三角形的个数

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

9.a)题目分析:

   通过枚举 i 、 j 、 k i、j、k ijk三个游标来代表三角形的三个边。

9.b)代码:
class Solution {
    public int triangleNumber(int[] nums) {
        int i ,j ,k;
        int ans =0;
        Arrays.sort(nums);
        for(i=0;i<nums.length;i++){
            j=i+1;
            k=j+1;
            while(j<nums.length){
                while(k<nums.length){
                    if(nums[i]+nums[j]<=nums[k]){
                        break;
                    }
                    ++k;
                }
                ans+=k-j-1;
                ++j;
                if(k==j){
                    k++;
                }
            }
        }
        return ans;
    }
}

三、做题记录

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枏念

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值