贪心算法总结及其leetcode题目N道

1 我为什么要写这个总结

1.1 字节笔试题

小明在玩一场通关游戏,初始血量为1,关卡有怪兽或者有血包(正数就是血包可回血数,负数说明是怪兽的伤害值),当捡到血包时会加血量,碰到怪兽时会掉血,现在指定初始血量为x,关卡是一个数组,小明必须按照数组的顺序玩游戏,当碰到一个怪兽时,他可以选择将这个怪兽扔到数组末尾,小明可以无限次地将怪兽移到数组末尾,问小明最少移动几次就能存活,如果无论怎么移动都不能存活则返回-1, 假设关卡是这样的[-200,-300,400],则返回-1,假如是这样的[200,100,-250,-60,-70,100],则返回1,只需要把-250挪到尾部,

思路:当发现自己血量不足时,就从当前已经遍历过的所有关卡中,选择耗费血量最多的那个关卡并且放到最后一关,如果即使这样挪开了耗血量最大的一关自身血量还是为负,则直接返回-1,说明无法通关

2 总结

2.1 什么是局部最优?

贪心关注的是局部最优,这里当前最优(指当前遍历的所有元素中的最优解)也是局部最优的一种,而一般的最有解又涉及到数据的最值,而且随着元素的不断向右扩展,可能这个最优值是不断变化的,所以一般可以使用堆来动态维护它的最值

3 题目

3.1 leetcode1046. 最后一块石头的重量

3.2 leetcode 1642. 可以到达的最远建筑

leetcode 1642. 可以到达的最远建筑

标准答案:

	//每次先放梯子,当梯子数量不足时,将当前使用过的梯子中,替代阶梯数最少的梯子找出来用对应砖头替换,替换出来的梯子拿到当前使用
 public int furthestBuilding(int[] heights, int bricks, int ladders) {
        int n=heights.length;
        //int[]:
        PriorityQueue<Integer>pq=new PriorityQueue<>((o1,o2)->(o1-o2));
        int i;
        int sum=0;//表示当前需要的砖块数量
        for(i=1;i<n;i++){
            int diff=heights[i]-heights[i-1];
            if(diff>0){
                pq.offer(diff);
                if(pq.size()>ladders){
                    sum+=pq.poll();
                }
                if(sum>bricks){
                    return i-1;
                }
            }
        }
        return n-1;
    }
    ```
    我的答案:(有几个特别长的case过不了)
    
```java
public int furthestBuilding2(int[] heights, int bricks, int ladders) {
        int n=heights.length;
        PriorityQueue<Integer>pq=new PriorityQueue<>((o1,o2)->(o1-o2));
        int i;
        for(i=1;i<n;){
            int diff=heights[i-1]-heights[i];
            // System.out.println("i:"+i+",diff:"+diff+",heights[i-1]:"+heights[i-1]+",heights[i]:"+heights[i]);
            if(diff<0){
              int diffAbs=-diff;
                if(ladders>0){
                    ladders--;
                    pq.add(diffAbs);
                }else if(bricks>=diffAbs){
                    bricks-=diffAbs;
                }else{
                    int newd=Integer.MAX_VALUE;
                    if(!pq.isEmpty()){
                      newd=pq.peek();
                    }
                    if(bricks>=newd){
                        pq.poll();
                        bricks-=newd;
                        ladders++;
                        i=i-1;
                    }else{
                        break;
                    }
                }
            }
            i++;
        }
        return i-1;
    }

这里还有一个二分查找的方法:
每太整明白:

3.3 871题最低加油次数和

3.4 630课程表III

你可能感兴趣的:(贪心算法,leetcode,算法)