贪心算法相关题目——NWU_LK

  1. 柠檬水找零(860)
class Solution {
    public boolean lemonadeChange(int[] bills) {
        Map<Integer,Integer> moneys=new HashMap<>();
        for(int bill:bills){
            if (bill!=5){
                if (!zhaoQian(moneys,bill-5)){
                    return false;
                }
            }
            int x=moneys.getOrDefault(bill,0);
            moneys.put(bill,x+1);
        }
        return true;
    }
    public boolean zhaoQian(Map<Integer,Integer> map,int bill){
        Integer[] money = map.keySet().toArray(new Integer[map.size()]);
        Arrays.sort(money, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        for (Integer i:money){
            int count=map.getOrDefault(i,0);
            while (count>0 && bill>=i){
                map.put(i,map.get(i)-1);
                count--;
                bill-=i;
            }
        }
        if (bill!=0){
            return false;
        }
        return true;
    }
}
  1. 分发饼干(455题)
    在这里插入图片描述
class Solution {
    public int findContentChildren(int[] g, int[] s) {
        Arrays.sort(g);
        Arrays.sort(s);
        int i=0,j=0;
        while (i<s.length&&j<g.length){
            if (s[i]>=g[j]){
                j++;
            }
            i++;
        }
        return j;
    }
}
  1. 摆动序列
    在这里插入图片描述
class Solution {
    public int wiggleMaxLength(int[] nums) {
        if (nums.length<=1){
            return nums.length;
        }
        int prediff =nums[1]-nums[0];
        int count=prediff!=0?2:1;
        for (int i=2;i<nums.length;i++){
            int diff=nums[i]-nums[i-1];
            if ((prediff>=0&&diff<0)||(prediff<=0&&diff>0)){
                count++;
                prediff=diff;
            }
        }
        return count;
    }
}
  1. 删除k位数字(402题)
    在这里插入图片描述
class Solution {
    public String removeKdigits(String num, int k) {
       Stack<Integer> stack=new Stack<>();
        char[] chars=num.toCharArray();
        int count=0;
        for (char c:chars){
            int cha=c-'0';
            while (!stack.isEmpty()&&cha<stack.peek() && count<k){
                stack.pop();
                count++;
            }
            stack.push(cha);
        }
        while (count<k){
            stack.pop();
            count++;
        }
        
        Stack<Integer> stack1=new Stack<>();
        while (!stack.isEmpty()){
            stack1.push(stack.pop());
        }
        
        while (!stack1.isEmpty()&&stack1.peek()==0){
            stack1.pop();
        }
        if (stack1.isEmpty()){
            return String.valueOf(0);
        }
        StringBuilder sb=new StringBuilder();
        while (!stack1.isEmpty()){
            sb.append(stack1.pop());
        }
        return sb.toString();
    }
}
  1. 跳跃游戏
    在这里插入图片描述
class Solution {
    public boolean canJump(int[] nums){
        int k=0;
        for (int i=0;i<nums.length;i++){
            if (k<i){
                return false;
            }
            k=Math.max(i+nums[i],k);
        }
        return true;
    }
}
  1. 跳跃游戏2(45题)
    在这里插入图片描述
class Solution {
    public int jump(int[] nums) {
        int index=0;
        int count=0;
        while (index<nums.length-1){
            int x=nums[index];
            int min=1;
            for (int i=1;i<=x;i++){
                if (index+i>=nums.length-1){
                    return count+1;
                }
                if (i+nums[index+i]>=nums[index+min]+min){
                    min=i;
                }
            }
            index+=min;
            count++;
        }
        return count;
    }
}
  1. 用最少数量的箭引爆气球(452题)
    在这里插入图片描述
class Solution {
    public int findMinArrowShots(int[][] points) {
        int count=0,index=0;
        Arrays.sort(points, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                long lo1=o1[1];
                long lo2=o2[1];
                if (lo1-lo2>0){
                    return 1;
                }else if (lo1-lo2==0){
                    return 0;
                }else {
                    return -1;
                }
            }
        });
        int[] pre=null;
        while (index<points.length){
            if (pre==null || points[index][0]>pre[1]){
                pre=points[index];
                count++;
            }
            index++;
        }

        return count;
    }
}
  1. 最低加油次数(871题)
    在这里插入图片描述
class Solution {
    public int minRefuelStops(int target, int startFuel, int[][] stations) {
        PriorityQueue<Integer> queue=new PriorityQueue<>((o1,o2)->o2-o1);
        int count=0;
        //max表示当前能够到达的最远距离
        int max=startFuel;
        if (max>target){
            return 0;
        }
        for (int[] station : stations) {
            int location=station[0];
            int capacity=station[1];
            //到不了该加油站则选择最大堆中油最多的一桶加油
            while (max<location){
                if (queue.isEmpty()){
                    return -1;
                }else {
                    max+=queue.poll();
                    count++;
                }
            }
            //将该加油站的油放入最大堆,供油不足时加油
            queue.offer(capacity);
        }
        //如果当前油量不足以到达终点则继续选择最大堆中的油加油
        while (max<target){
            if (queue.isEmpty()){
                return -1;
            }else {
                max+=queue.poll();
                count++;
            }
        }
        return count;
    }
}
  1. 非递增顺序的最小子序列(1403题)
    在这里插入图片描述
class Solution {
    public List<Integer> minSubsequence(int[] nums) {
        List<Integer> res= new ArrayList<>();
        Arrays.sort(nums);
        int sum=0;
        for(int num:nums){
            sum+=num;
        }
        int subSum=0;
        for (int i=nums.length-1;i>=0;i--){
            if (subSum<=sum/2){
                res.add(nums[i]);
                subSum+=nums[i];
            }
        }
        return res;
    }
}
  1. 最长快乐字符串(1405题)
    在这里插入图片描述
class Solution {
    public String longestDiverseString(int a, int b, int c) {
       StringBuilder sb=new StringBuilder();
        Map<Character,Integer> map=new HashMap<>();
        map.put('a',a);map.put('b',b);map.put('c',c);
        while (true){
            a=map.get('a');b=map.get('b');c=map.get('c');
            if (a>=b && a>=c){
                if (sb.length()<=1||!sb.substring(sb.length()-2).equals("aa")){
                    if (a==0) break;sb.append('a');map.put('a',a-1);
                }else{
                    if (b>=c){
                        if (b==0) break;
                        sb.append('b');map.put('b',b-1);
                    }else {
                        sb.append('c');map.put('c',c-1);
                    }
                }
            }
            else if (b>=a && b>=c){
                if (sb.length()<=1|| !sb.substring(sb.length()-2).equals("bb")){
                    sb.append('b');map.put('b',b-1);
                }else {
                    if (a>=c){
                        if (a==0) break;
                        sb.append('a');map.put('a',a-1);
                    }else {
                        sb.append('c');map.put('c',c-1);
                    }
                }
            }
            else{
                if (sb.length()<=1|| !sb.substring(sb.length()-2).equals("cc")){
                    sb.append('c');map.put('c',c-1);
                }else {
                    if (a>=b){
                        if (a==0) break;
                        sb.append('a');map.put('a',a-1);
                    }else {
                        sb.append('b');map.put('b',b-1);
                    }
                }
            }
        }
        return sb.toString();
    }
}
  1. 单调递增数字(738)
    在这里插入图片描述
class Solution {
    public int monotoneIncreasingDigits(int N) {
        char[] chars = String.valueOf(N).toCharArray();
        for (int i=chars.length-1;i>0;i--){
            if (chars[i]<chars[i-1]){
                chars[i-1]-=1;
                for (int j=i;j<chars.length;j++){
                    chars[j]='9';
                }
            }
        }
        return Integer.parseInt(new String(chars));
    }
}
  1. 最长递增子数列(300题)
    在这里插入图片描述
    求长度:
class Solution {
    public int lengthOfLIS(int[] arr) {
        if (arr.length==0){
            return 0;
        }
        int[] dp=new int[arr.length+1];
        int len=1;
        dp[len]=arr[0];
        for (int i=1;i<arr.length;i++){
            if (arr[i]>dp[len]){
                dp[++len]=arr[i];
            }else {
                int l=1,r=len,pos=0;
                while (l<=r){
                    int mid=l+(r-l)/2;
                    if (dp[mid]<arr[i]){
                        l=mid+1;
                        pos=mid;
                    }else {
                        r=mid-1;
                    }
                }
                dp[pos+1]=arr[i];
            }
        }
        return len;
    }
}

求数列:

public class Solution {
    public int[] LIS (int[] arr) {
        int[] dp=new int[arr.length+1];
        int[] tag=new int[arr.length];
        int len=1;tag[0]=1;
        dp[len]=arr[0];
        for (int i=1;i<arr.length;i++){
            if (arr[i]>dp[len]){
                dp[++len]=arr[i];
                tag[i]=len;
            }else {
                int l=1,r=len,pos=0;
                while (l<=r){
                    int mid=l+(r-l)/2;
                    if (dp[mid]<arr[i]){
                        l=mid+1;
                        pos=mid;
                    }else {
                        r=mid-1;
                    }
                }
                dp[pos+1]=arr[i];
                tag[i]=pos+1;
            }
        }
        int[] res = new int[len];
        for (int i = arr.length - 1; i >= 0; i--) {
            if (tag[i] == len) {
                res[--len] = arr[i];
            }
        }
        return res;
    }
}
课程表③

来源:Leetcode.630题

思想:尽量选择结束时间早的课程。首先对课程的结束时间进行排序,循环判断排序后的数组中的每一门课程,循环到某一门课程时判断前面课程花费的时间总和加上当前课程需要花费的时间是否小于等于当前课程的结束时间,如果满足的话则将其直接加入,不满足的话则判断当前课程是否可以替代前面花费时间比较长的课程,目的是尽量保证已学过的课程花费的时间较短,从而给后面的课程空余更多的时间。

class Solution {
    public int scheduleCourse(int[][] courses) {
        Arrays.sort(courses, (a, b) -> a[1] - b[1]);

        PriorityQueue<Integer> queue = new PriorityQueue<Integer>((a, b) -> b - a);
        // 优先队列中所有课程的总时间
        int total = 0;

        for (int[] course : courses) {
            int ti = course[0], di = course[1];
            if (total + ti <= di) {
                total += ti;
                queue.offer(ti);
            } else if (!queue.isEmpty() && queue.peek() > ti) {
                total -= queue.poll() - ti;
                queue.offer(ti);
            }
        }

        return queue.size();
    }
}
吃苹果的最大数目

来源:Leetcode.1705题

思想:按照贪心的思想,吃掉过期时间最早的果子。按照[过期时间,果子数量]的方式将其保存在优先队列(堆)里,按照过期时间排序,因此堆顶永远都是过期时间最早的果子。

public int eatenApples(int[] apples, int[] days) {
        int ans = 0;
        PriorityQueue<int[]> queue = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
        int n = apples.length;
        int i = 0;
        //遍历每天的果子数组
        while (i < n) {
        	//丢弃过期的果子
            while (!queue.isEmpty() && queue.peek()[0] <= i) {
                queue.poll();
            }
            int delayDay = i + days[i];
            int count = apples[i];
            if (count > 0) {
                queue.offer(new int[]{delayDay, count});
            }
            //将堆顶数目-1,如果为0则移除堆顶
            if (!queue.isEmpty()) {
                int[] arr = queue.peek();
                arr[1]--;
                if (arr[1] == 0) {
                    queue.poll();
                }
                ans++;
            }
            i++;
        }
        //如果堆中还有果子
        while (!queue.isEmpty()) {
        	//移除过期的
            while (!queue.isEmpty() && queue.peek()[0] <= i) {
                queue.poll();
            }
            if (queue.isEmpty()) {
                break;
            }
            //判断堆顶的果子可以吃几天
            int[] arr = queue.poll();
            int curr = Math.min(arr[0] - i, arr[1]);
            ans += curr;
            i += curr;
        }
        return ans;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值