leetcode刷题笔记——贪心算法 2021-01-26

题目122.买卖股票的最佳时机

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xxf2IzyD-1611670606460)(C:\Users\HASEE\AppData\Roaming\Typora\typora-user-images\1611647557679.png)]

  • class Solution {
           
        public int maxProfit(int[] prices) {
           
            int ans=0;
            for(int i=0;i<prices.length-1;i++){
           
                ans+=Math.max(0,prices[i+1]-prices[i]);
            }
            return ans;
        }
    }
    
  • 利用数学操作,将问题转化为求相邻两天收益和的最大值问题。

题目392.判断子序列

  • 栈:将原序列入栈跟子序列入栈,比较栈顶元素,若相等则同时弹出,若不想等原序列弹出,若最后两栈同时为空,返回true,否则返回false。

  • 双指针:

  • class Solution {
           
        public boolean isSubsequence(String s, String t) {
           
            int i=0,j=0;
           while(i<s.length()&&j<t.length()){
           
            if(s.charAt(i)==t.charAt(j)){
           
                i++;
                j++;
            }else j++;
           }
           return i==s.length();
        }
    }
    
  • class Solution {
           
        public boolean isSubsequence(String s, String t) {
           
           //动态规划
        int n=s.length(),m=t.length();
        //对字符串t进行预处理
        //首先建立dp表,记录字符第一次出现索引位置
        int[][] f=new int[m+1][26];
        for(int i=0;i<26;i++){
           //第m行初始化
            f[m][i]=m;
        }
        //从后往前循环填充dp数组
        for(int i=m-1;i>=0;i--){
           
            for(int j=0;j<26;j++){
           
                if(t.charAt(i)-'a'==j){
           
                    f[i][j]=i;
                }else{
           
                    f[i][j]=f[i+1][j];
                }
            }
        }
        //判断s字符串中字符在t中位置
        //设置两个指针
        int add=0;
        for(int i=0;i<n;i++){
           
            if(f[add][s.charAt(i)-'a']==m) return false;
            add=f[add][s.charAt(i)-'a']+1;
        }
        return true;
        }
    }
    

题目455.分发饼干

  • 这题查贪心算法时当例题看了

  • 思路是将胃口值和尺寸值数组按顺序排列,分别设置指针,饼干能满足小孩,小孩、饼干都加1,不能满足则饼干加一。

  • class Solution {
           
        public int findContentChildren(int[] g, int[] s) {
           
            //标准贪心算法。9ms,39.3MB
           /* Arrays.sort(g);
            Arrays.sort(s);
            int child=0,cake=0;
            while(child=g[child]) {
                    cake++;
                    child++;
                }else cake++;
            }
            return child;*/
            
             //8ms,39.2MB
            Arrays.sort(g);
            Arrays.sort(s);
            int count=0;
            for(int i=0;i<s.length;i++){
           
                if(s[i]>=g[count]){
           
                    count++;
                    if(count==g.length) break;
                }
            }
            return count;
    
    
        }
    }
    

题目605.种花问题

  • 0的左右都是0才可以种花。

  • 开头和结尾单独讨论,若是0则相邻也是0即可。

  • 统计中间连着3个0的个数即是可以种花的个数

  • class Solution {
           
        public boolean canPlaceFlowers(int[] flowerbed, int n) {
           
            int prev=-1;
            int count=0;
            for(int i=0;i<flowerbed.length;i++){
           
                if(flowerbed[i]==1){
           
                    if(prev<0&&i>=2) count+=(i+1)/2;//左侧无花最多可种多少花计算公式
                    else count+=(i-prev-2)/2;//两侧有花中间最多可种多少花计算公式
                    prev=i;
                }
            }
            if(prev<0) count+=(flowerbed.length+1)/2;//全部无花计算公式
            else count+=(flowerbed.length-prev-1)/2;//右侧无花计算公式
            return count>=n;
        }
    }
    

题目860.柠檬水找零

  • 这个问题大致思路很简单

  • 注意点在于20美元找零方式有两种,10+5或3*5,当这两种方式都可以时我们倾向于按第一种方式找零,因为需要使用5美元的找零场景多余10美元的找零场景,应尽可能保留5美元钞票。

  • 但问题是,存不存在一种情况,你是两种方式交替找零?

  • 其实不然,因为你收到钱的总数是不变的,保留5元还是保留10元,最后总额是一定的,你如果10+5最后没零钱找了,3张5元的也找不开,因为某一时刻你手里零钱数目相等,无非是形式变化,。但如果你先用3*5,到最后可能出两个10元,你找不开,此时如果10元的形式是两张5元的就可以找开。

  • class Solution {
           
        public boolean lemonadeChange(int[] bills) {
           
            int count_5=0,count_10=0,count_20=0;
            for(int i=0;i<bills.length;i++){
           
                if(bills[i]==5) count_5++;
                else if(bills[i]==10){
           
                    count_10++;
                    count_5--;
                    if(count_5<0) return false;
                } else{
           
                        if(count_5<3){
           
                        count_5--;
                        count_10--;}else if(count_10<0){
           
                            count_5=count_5-3;
                        }else{
           
                            count_5--;
                            count_10--;
                        }
                    count_20++;
                    if(count_5<0) return false;
                    else if(count_10<0&&count_5<3)
                    return false;
                }
            }
            return true;
        }
    }
    

题目874.模拟行走机器人

  • 用x表示机器人横坐标,y表示纵坐标,commands数组,

  • -1之前若y+,则x+,x+转为y-,y-转为x-,x-转为y+

  • -2若之前y+则x-,x- y- ,y- x+ ,x+ y+

  • 其他情况则根据之前的方向加x,若加完大于等于障碍物,则到障碍物-1位置,执行转向指令。



你可能感兴趣的:(学习笔记,算法,数据结构,leetcode,字符串,java)