力扣网---贪心算法(JAVA实现)----简单(一)


860,柠檬水找零

/**
     * 在柠檬水摊上,每一杯柠檬水的售价为 5 美元。
     *
     * 顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。
     *
     * 每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。
     * 你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。
     *
     * 注意,一开始你手头没有任何零钱。
     *
     * 如果你能给每位顾客正确找零,返回 true ,否则返回 false 。
     *
     * 示例 1:
     *
     * 输入:[5,5,5,10,20]
     * 输出:true
     * 解释:
     * 前 3 位顾客那里,我们按顺序收取 3 张 5 美元的钞票。
     * 第 4 位顾客那里,我们收取一张 10 美元的钞票,并返还 5 美元。
     * 第 5 位顾客那里,我们找还一张 10 美元的钞票和一张 5 美元的钞票。
     * 由于所有客户都得到了正确的找零,所以我们输出 true。
     * 示例 2:
     *
     * 输入:[5,5,10]
     * 输出:true
     * 示例 3:
     *
     * 输入:[10,10]
     * 输出:false
     * 示例 4:
     *
     * 输入:[5,5,10,10,20]
     * 输出:false
     * 解释:
     * 前 2 位顾客那里,我们按顺序收取 2 张 5 美元的钞票。
     * 对于接下来的 2 位顾客,我们收取一张 10 美元的钞票,然后返还 5 美元。
     * 对于最后一位顾客,我们无法退回 15 美元,因为我们现在只有两张 10 美元的钞票。
     * 由于不是每位顾客都得到了正确的找零,所以答案是 false。
     *  
     *
     * 提示:
     *
     * 0 <= bills.length <= 10000
     * bills[i] 不是 5 就是 10 或是 20 
     *
     * 来源:力扣(LeetCode)
     * 链接:https://leetcode-cn.com/problems/lemonade-change
     * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
     * @param args
     */
    public static void main( String[] args )
    {
        int[] bills={5,5,5,10,20};
        System.out.println(lemonadeChange( bills ));

        int[] bills2={5,5,5,5,20,20,5,5,5,5};
        System.out.println(lemonadeChange( bills2 ));
    }

    public static boolean lemonadeChange(int[] bills) {
        int[] money=new int[3]; //保存 5,10,20 钱数量。
        //注意是排队购买
        for( int i = 0; i < bills.length; i++ )
        {
            if(bills[i]==5){
                money[0]++;
            }else if(bills[i]==10){
                money[1]++;
                //判断是否5元够支付
                if(money[0]>0){
                    money[0]--;
                }else {
                    return false;
                }
            }else {
                if(money[1]>0&&money[0]>0){//先考虑使用10元大钞票
                    money[1]--;
                    money[0]--;
                }else if(money[0]>=3){
                    money[0]-=3;
                }else {
                    return false;
                }

            }
        }
        return true;
    }

874,模拟行走机器人

 /**
     * 机器人在一个无限大小的网格上行走,从点 (0, 0) 处开始出发,面向北方。该机器人可以接收以下三种类型的命令:
     * <p>
     * -2:向左转 90 度
     * -1:向右转 90 度
     * 1 <= x <= 9:向前移动 x 个单位长度
     * 在网格上有一些格子被视为障碍物。
     * <p>
     * 第 i 个障碍物位于网格点  (obstacles[i][0], obstacles[i][1])
     * <p>
     * 机器人无法走到障碍物上,它将会停留在障碍物的前一个网格方块上,但仍然可以继续该路线的其余部分。
     * <p>
     * 返回从原点到机器人所有经过的路径点(坐标为整数)的最大欧式距离的平方。
     * <p>
     * 示例 1:
     * <p>
     * 输入: commands = [4,-1,3], obstacles = []
     * 输出: 25
     * 解释: 机器人将会到达 (3, 4)
     * 示例 2:
     * <p>
     * 输入: commands = [4,-1,4,-2,4], obstacles = [[2,4]]
     * 输出: 65
     * 解释: 机器人在左转走到 (1, 8) 之前将被困在 (1, 4) 处
     *  
     * <p>
     * 提示:
     * <p>
     * 0 <= commands.length <= 10000
     * 0 <= obstacles.length <= 10000
     * -30000 <= obstacle[i][0] <= 30000
     * -30000 <= obstacle[i][1] <= 30000
     * 答案保证小于 2 ^ 31
     * <p>
     * 来源:力扣(LeetCode)
     * 链接:https://leetcode-cn.com/problems/walking-robot-simulation
     * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
     *
     * @param args
     */
    public static void main( String[] args )
    {
        int[] commands = {4,-1,3};
        int[][]   obstacles = {};
        System.out.println(robotSim( commands,obstacles ));

        int[] commands2 = {4,-1,4,-2,4};
        int[][]   obstacles2 = {{2,4}};
        System.out.println(robotSim( commands2,obstacles2 )); //65

        int[] commands3 = {1,2,-2,5,-1,-2,-1,8,3,-1,9,4,-2,3,2,4,3,9,2,-1,-1,-2,1,3,-2,4,1,4,-1,1,9,-1,-2,5,-1,5,5,-2,6,6,7,7,2,8,9,-1,7,4,6,9,9,9,-1,5,1,3,3,-1,5,9,7,4,8,-1,-2,1,3,2,9,3,-1,-2,8,8,7,5,-2,6,8,4,6,2,7,2,-1,7,-2,3,3,2,-2,6,9,8,1,-2,-1,1,4,7};
        int[][]   obstacles3= {{-57,-58},{-72,91},{-55,35},{-20,29},{51,70},{-61,88},{-62,99},{52,17},{-75,-32},{91,-22},{54,33},{-45,-59},{47,-48},{53,-98},{-91,83},{81,12},{-34,-90},{-79,-82},{-15,-86},{-24,66},{-35,35},{3,31},{87,93},{2,-19},{87,-93},{24,-10},{84,-53},{86,87},{-88,-18},{-51,89},{96,66},{-77,-94},{-39,-1},{89,51},{-23,-72},{27,24},{53,-80},{52,-33},{32,4},{78,-55},{-25,18},{-23,47},{79,-5},{-23,-22},{14,-25},{-11,69},{63,36},{35,-99},{-24,82},{-29,-98},{-50,-70},{72,95},{80,80},{-68,-40},{65,70},{-92,78},{-45,-63},{1,34},{81,50},{14,91},{-77,-54},{13,-88},{24,37},{-12,59},{-48,-62},{57,-22},{-8,85},{48,71},{12,1},{-20,36},{-32,-14},{39,46},{-41,75},{13,-23},{98,10},{-88,64},{50,37},{-95,-32},{46,-91},{10,79},{-11,43},{-94,98},{79,42},{51,71},{4,-30},{2,74},{4,10},{61,98},{57,98},{46,43},{-16,72},{53,-69},{54,-96},{22,0},{-7,92},{-69,80},{68,-73},{-24,-92},{-21,82},{32,-1},{-6,16},{15,-29},{70,-66},{-85,80},{50,-3},{6,13},{-30,-98},{-30,59},{-67,40},{17,72},{79,82},{89,-100},{2,79},{-95,-46},{17,68},{-46,81},{-5,-57},{7,58},{-42,68},{19,-95},{-17,-76},{81,-86},{79,78},{-82,-67},{6,0},{35,-16},{98,83},{-81,100},{-11,46},{-21,-38},{-30,-41},{86,18},{-68,6},{80,75},{-96,-44},{-19,66},{21,84},{-56,-64},{39,-15},{0,45},{-81,-54},{-66,-93},{-4,2},{-42,-67},{-15,-33},{1,-32},{-74,-24},{7,18},{-62,84},{19,61},{39,79},{60,-98},{-76,45},{58,-98},{33,26},{-74,-95},{22,30},{-68,-62},{-59,4},{-62,35},{-78,80},{-82,54},{-42,81},{56,-15},{32,-19},{34,93},{57,-100},{-1,-87},{68,-26},{18,86},{-55,-19},{-68,-99},{-9,47},{24,94},{92,97},{5,67},{97,-71},{63,-57},{-52,-14},{-86,-78},{-17,92},{-61,-83},{-84,-10},{20,13},{-68,-47},{7,28},{66,89},{-41,-17},{-14,-46},{-72,-91},{4,52},{-17,-59},{-85,-46},{-94,-23},{-48,-3},{-64,-37},{2,26},{76,88},{-8,-46},{-19,-68}};
        System.out.println(robotSim( commands3,obstacles3 )); //5140
    }

    public static int[][] dist = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; //上  右  下  左(方便旋转)

    public static int robotSim( int[] commands, int[][] obstacles )
    {
        Set<String> set=new HashSet<>(  );
        for( int i = 0; i < obstacles.length; i++ )
        {
            set.add( obstacles[i][0]+"+"+obstacles[i][1] );
        }
        int[] place = new int[2];//位置坐标
        int dir=0;//方向
        int max=0; //坑,居然不是求最后的值,而是过程中最大值。
        for( int i = 0; i < commands.length; i++ )
        {
            //如果是旋转命令
            if( commands[i] == -2 )
            {
                 dir=dir-1>=0?dir-1:3;
            }else if( commands[i] == -1 )
            {
                dir=dir+1<=3?dir+1:0;
            }else {
                //判断路径上是否有障碍
                int command=commands[i];
                while( command>0 ){
                    if(set.contains( (place[0]+dist[dir][0] )+"+"+(place[1]+dist[dir][1]))){
                        break;
                    }else {
                        place[0]+=dist[dir][0];
                        place[1]+=dist[dir][1];
                        command--;
                    }
                }
            }
            max=Math.max( max, (int)Math.pow( place[0],2 )+(int)Math.pow( place[1],2 ));
            //System.out.println( Arrays.toString( place ) );
        }
        return max;
    }

944,删列造序


      /**
     * 给定由 N 个小写字母字符串组成的数组 A,其中每个字符串长度相等。
     *
     * 你需要选出一组要删掉的列 D,对 A 执行删除操作,使 A 中剩余的每一列
     * 都是 非降序 排列的,然后请你返回 D.length 的最小可能值。
     *
     * 删除 操作的定义是:选出一组要删掉的列,删去 A 中对应列中的所有字符,
     * 形式上,第 n 列为 [A[0][n], A[1][n], ..., A[A.length-1][n]])。(可以参见 删除操作范例)
     *
     *  
     *
     * 示例 1:
     * 输入:["cba", "daf", "ghi"]
     * 输出:1
     * 解释:
     * 当选择 D = {1},删除后 A 的列为:["c","d","g"]["a","f","i"],均为非降序排列。
     * 若选择 D = {},那么 A 的列 ["b","a","h"] 就不是非降序排列了。
     * 示例 2:
     *
     * 输入:["a", "b"]
     * 输出:0
     * 解释:D = {}
     * 示例 3:
     *
     * 输入:["zyx", "wvu", "tsr"]
     * 输出:3
     * 解释:D = {0, 1, 2}
     *  
     *
     * 提示:
     *
     * 1 <= A.length <= 100
     * 1 <= A[i].length <= 1000
     *  
     *
     * 删除操作范例:
     *
     * 比如,有 A = ["abcdef", "uvwxyz"],
     *
     *
     *
     * 要删掉的列为 {0, 2, 3},删除后 A 为["bef", "vyz"], A 的列分别为["b","v"], ["e","y"], ["f","z"]。
     * 来源:力扣(LeetCode)
     * 链接:https://leetcode-cn.com/problems/delete-columns-to-make-sorted
     * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
     * @param args
     *
     *
     * 用例子来说的话,设数列bai{an}
     * 若符合a(n+1)>an,则du数列的递zhi增的,也是升序的
     * 若符合a(n+1)<an,则数列的递减的,也是降序的
     * 若符合a(n+1)≤an,则数列是非升序的
     * 若符合a(n+1)≥an,则数列是非降序的
     */
  public static void main( String[] args )
    {
        String[] A={"cba", "daf", "ghi"};
        System.out.println(minDeletionSize( A ));

        String[] A1={"a", "b"};
        System.out.println(minDeletionSize( A1 ));

        String[] A2={"zyx", "wvu", "tsr"};
        System.out.println(minDeletionSize( A2 ));

        String[] A3={"rrjk","furt","guzm"};
        System.out.println(minDeletionSize( A3 )); //2

    }
    
    public static int minDeletionSize(String[] A) {
        int count=0;
        for( int i = 0; i <A[0].length() ; i++ )
        {
            char pre=A[0].charAt( i );
            for( int j = 1; j <A.length ; j++ )
            {
                if(A[j].charAt( i )>=pre){ //满足条件
                    pre=A[j].charAt( i );
                }else {
                    count++;
                    break;
                }
            }
        }
        return count;
    }

1005,K 次取反后最大化的数组和

问题描述:
给定一个整数数组 A,我们只能用以下方法修改该数组:我们选择某个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次。(我们可以多次选择同一个索引 i。)

以这种方式修改数组后,返回数组可能的最大和。

示例 1:

输入:A = [4,2,3], K = 1
输出:5
解释:选择索引 (1,) ,然后 A 变为 [4,-2,3]

示例 2:

输入:A = [3,-1,0,2], K = 3
输出:6
解释:选择索引 (1, 2, 2) ,然后 A 变为 [3,1,0,2]

测试代码及答案:

    public static void main( String[] args )
    {
          int[] A={4,2,3};
         System.out.println(largestSumAfterKNegations( A,1 ));

        int[] A2={3,-1,0,2};
        System.out.println(largestSumAfterKNegations( A2,3 ));

        int[] A3={2,-3,-1,5,-4};
        System.out.println(largestSumAfterKNegations( A3,2 ));


        int[] A4={-2,9,9,8,4};
        System.out.println(largestSumAfterKNegations( A4,5 ));

    }

    //贪心思路:
    //1,排序
    //2,首先把负数按优先级转换为正数。
    //3,去反复翻转同一个全局最小值。
    //4, 注意0存在。有0就一直翻转0
    //5,在出现正数时.前一位和当前位存在全局最小值。
    public static int largestSumAfterKNegations( int[] A, int K ) {
        Arrays.sort( A );
        //System.out.println(Arrays.toString( A ));
        int index = 0;
        int sum = 0;
        int mix;
        for( int i = 0; i < K; i++ ){
            if( A[index] < 0 ){
                A[index] = -A[index];
            }
            else if( A[index] > 0 ){
                //直接用全局最小值计算最后翻转结果
                mix = Math.min( A[index], index >0 ? A[index - 1] : 10001 );

                //由于目前数组全为正数,计算最后翻转是否得到负数,是则先减去两倍最小负数。
                sum -= (K - i) % 2 == 1 ? 2 * mix : 0;
                break;
            }else { //0 直接停止
                break;
            }
            if( index < A.length - 1 ){
                index++;
            }
        }

        for( int i = 0; i < A.length; i++ ){
            sum += A[i];
        }
        return sum;
    }

1046,最后一块石头的重量

问题描述:
有一堆石头,每块石头的重量都是正整数。

每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:

如果 x == y,那么两块石头都会被完全粉碎;
如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。
最后,最多只会剩下一块石头。返回此石头的重量。如果没有石头剩下,就返回 0。

示例:

输入:[2,7,4,1,8,1]
输出:1
解释:
先选出 7 和 8,得到 1,所以数组转换为 [2,4,1,1,1],
再选出 2 和 4,得到 2,所以数组转换为 [2,1,1,1],
接着是 2 和 1,得到 1,所以数组转换为 [1,1,1],
最后选出 1 和 1,得到 0,最终数组转换为 [1],这就是最后剩下那块石头的重量。

提示:

1 <= stones.length <= 30
1 <= stones[i] <= 1000

问题解答:

 public static int lastStoneWeight(int[] stones) {

        //先用list来做,先排序
        Arrays.sort( stones );
        ArrayList<Integer> list=new ArrayList<>(  );
        for( int i = 0; i < stones.length; i++ )
        {
            list.add( stones[i] );
        }
        while( list.size()>1 ){
            int len=list.size();
            int last=list.get( len-1 )-list.get( len-2 );
            list.remove(  list.size()-1);
            list.remove(  list.size()-1);
            if(last!=0){
               list.add( last );
               Collections.sort( list );
            }
        }

        return list.size()>0?list.get( 0 ):0;
    }

1403,非递增顺序的最小子序列

 /**
     * 给你一个数组 nums,请你从中抽取一个子序列,满足该子序列的元素之和 严格 大于未包含在该子序列中的各元素之和。
     *
     * 如果存在多个解决方案,只需返回 长度最小 的子序列。如果仍然有多个解决方案,则返回 元素之和最大 的子序列。
     *
     * 与子数组不同的地方在于,「数组的子序列」不强调元素在原数组中的连续性,也就是说,
     * 它可以通过从数组中分离一些(也可能不分离)元素得到。
     *
     * 注意,题目数据保证满足所有约束条件的解决方案是 唯一 的。同时,返回的答案应当按 非递增顺序 排列。
     *
     *  
     *
     * 示例 1:
     *
     * 输入:nums = [4,3,10,9,8]
     * 输出:[10,9]
     * 解释:子序列 [10,9][10,8] 是最小的、满足元素之和大于其他各元素之和的子序列。但是 [10,9] 的元素之和最大。 
     * 示例 2:
     *
     * 输入:nums = [4,4,7,6,7]
     * 输出:[7,7,6]
     * 解释:子序列 [7,7] 的和为 14 ,不严格大于剩下的其他元素之和(14 = 4 + 4 + 6)。
     * 因此,[7,6,7] 是满足题意的最小子序列。注意,元素按非递增顺序返回。
     * 示例 3:
     *
     * 输入:nums = [6]
     * 输出:[6]
     *  
     *
     * 提示:
     *
     * 1 <= nums.length <= 500
     * 1 <= nums[i] <= 100
     *
     * 来源:力扣(LeetCode)
     * 链接:https://leetcode-cn.com/problems/minimum-subsequence-in-non-increasing-order
     * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
     */

    public static void main( String[] args )
    {
        int[] nums={4,3,10,9,8};
        System.out.println(minSubsequence( nums ));
    }


    public static List<Integer> minSubsequence(int[] nums) {
        Arrays.sort( nums );
        int sum=0;
        for( int i = 0; i <nums.length ; i++ )
        {
             sum+=nums[i];
        }
        ArrayList<Integer> list=new ArrayList<>(  );
        int sum2=0;
        for( int i = nums.length-1; i >=0; i-- )
        {
            list.add( nums[i] );
            sum2+=nums[i];
            if( sum2>sum/2 ){
                break;
            }
        }

        return list;
    }

1518,换酒问题

问题描述:

小区便利店正在促销,用 numExchange 个空酒瓶可以兑换一瓶新酒。你购入了 numBottles 瓶酒。

如果喝掉了酒瓶中的酒,那么酒瓶就会变成空的。

请你计算 最多 能喝到多少瓶酒。

示例 1:

在这里插入图片描述

输入:numBottles = 9, numExchange = 3
输出:13
解释:你可以用 3 个空酒瓶兑换 1 瓶酒。
所以最多能喝到 9 + 3 + 1 = 13 瓶酒。

示例 2:

在这里插入图片描述

输入:numBottles = 15, numExchange = 4
输出:19
解释:你可以用 4 个空酒瓶兑换 1 瓶酒。
所以最多能喝到 15 + 3 + 1 = 19 瓶酒。

示例 3:

输入:numBottles = 5, numExchange = 5
输出:6

示例 4:

输入:numBottles = 2, numExchange = 3
输出:2

测试案例与解答:

    public static void main( String[] args )
    {

        System.out.println(numWaterBottles( 9,3 ));
        System.out.println(numWaterBottles( 15,4 ));
        System.out.println(numWaterBottles( 5,5 ));
    }

    public static int numWaterBottles(int numBottles, int numExchange) {
        int sum=numBottles;
        while( numBottles>=numExchange ){
            int add=numBottles/numExchange; //新换的酒
            sum+=add;
            numBottles=numBottles-add*numExchange+add;
        }
        return sum;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值