贪心算法

Leetcode 455 分发饼干

需求因子:饼干

1.对饼干和孩子排序,方便比较

2.当一个孩子能被多个饼干满足时,要挑选哪个饼干

3.一个饼干能满足多个孩子时,要选哪个孩子 

思路:对两个数组排序,用最小号的饼干分配给最小胃口的孩子

class Solution {
    public int findContentChildren(int[] g, int[] s) {
        Arrays.sort(g);
        Arrays.sort(s);
        int index = 0;
        int sum = 0;
        for(int i=0;i<s.length;i++)
        {
            if(index<g.length)
            {
                if(s[i]>=g[index]) 
                {
                    index++;
                    sum++;
                }
            } 
        }

        return sum;
    }
}

Leetcode 376 摇摆序列

https://leetcode-cn.com/problems/wiggle-subsequence

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。

例如, [1,7,4,9,2,5] 是一个摆动序列,因为差值 (6,-3,5,-7,3) 是正负交替出现的。相反, [1,4,7,2,5] 和 [1,7,4,5,5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。

给定一个整数序列,返回作为摆动序列的最长子序列的长度。 通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。

思路:分析过程,递增过程中选择最大的元素,递减过程中选择最小的元素

扫描过程中三个状态的转换:

 

 

使用switch case

(java类常量: public static final int )

(switch case中能够使用到变量:int short char String)

class Solution {
    public static final int begin = 0;
    public static final int up = 1;
    public static final int down = 2;

    public int wiggleMaxLength(int[] nums) {
        if(nums.length==0) return 0;

        int sum = 0;

        int state = begin;
        for(int i=0;i<nums.length-1;i++)
        {
            switch(state)
            {
                case begin:
                    if(nums[i]<nums[i+1]) 
                    {
                        //System.out.print("A"+nums[i]+" ");
                        sum++;
                        state = up;
                    }
                    else if(nums[i]>nums[i+1]) 
                    {
                        //System.out.print("B"+nums[i]+" ");
                        sum++;
                        state = down;
                    }
                    break;
                
                case up:
                    if(nums[i]>nums[i+1])
                    {
                        //System.out.print("C"+nums[i]+" ");
                        state = down;
                        sum++;
                    }
                    break;
                case down:
                    if(nums[i]<nums[i+1])
                    {
                        //System.out.print("D"+nums[i]+" ");
                        state = up;
                        sum++;
                    }
                    break;
            }  
        }
        sum++;
        return sum;
    }
}

Leetcode 402 移除k个数字

https://leetcode-cn.com/problems/remove-k-digits

给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。

 

示例 1 :

输入: num = "1432219", k = 3

输出: "1219"

解释: 移除掉三个数字 4, 3, 2 形成一个新的最小的数字 1219

思路1 使用StringBuilder,删k轮,每次删一个高位大数或最后一个数。

String → StringBuilder : StringBuilder s = new StringBuilder(str);

StringBuilder → String : String str = s.toString();

StringBuilder的方法:

class Solution {
    public String removeKdigits(String num, int k) {
        if( k>= num.length()||num.length()==0) return "0";
        StringBuilder s = new StringBuilder(num);
        boolean flag = false;
        for(int i=0;i<k;i++)
        {
            flag = false;
            for(int j=0;j<s.length()-1;j++)
            {
                if(s.charAt(j)>s.charAt(j+1))
                {
                    s.delete(j,j+1);
                    flag = true;
                    break;
                }
            }
            if(!flag) s.delete(s.length()-1,s.length());
        }

        while(s.charAt(0)=='0' && s.length()>1)
        {
            s.delete(0,1);
        }
        return s.toString();
    }
}

思路2: 栈+贪心算法

思路有点难想到。星星 星星 星星

1.char 封装类是 Charater

2.使用stringbuilder.append(字符串/字符)追加

3.String对象有charAt(index)方法返回字符

class Solution {
    public String removeKdigits(String num, int k) {
        if(num.length()==0 || k >= num.length()) return "0";

        Stack<Character> stack = new Stack<>();
        stack.push(num.charAt(0));for(int i=1;i<num.length();i++)
        {
            char now = num.charAt(i);
            while(!stack.isEmpty()&&k>0&&now<stack.peek())
            {
                stack.pop(); 
                k--;
            }
            
            stack.push(now);
            
        }
        while(k>0)
        {
            stack.pop();
            k--;
        }
        Stack<Character> s = new Stack<>();
        while(!stack.isEmpty())
        {
            s.push(stack.pop());
        }
        StringBuilder sb = new StringBuilder();
        boolean fz = true;
        while(!s.isEmpty())
        {
            if(sb.length()==0&&s.peek()=='0') s.pop();
            else sb.append(s.pop());
        }

        if(sb.length()==0) return "0";
        return sb.toString();
        

    }
}

Leetcode 55 跳跃游戏 

给定一个非负整数数组,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个位置。

思路:关键是判断最优的跳跃路径,跳到的下一个位置能跳到的最远位置要最远

 

class Solution {
    public boolean canJump(int[] nums) {

        if(nums.length<=1) return true;
        int max = 0; 
        for(int i=0;i<nums.length;)
        {
            int temp = i;
            int maxnow = max;
            for(int k=0;k<=nums[i];k++)
            {
                if(i+k+nums[i+k]>max) 
                {
                    max = k+i+nums[i+k];
                    if(max>=nums.length-1) return true;
                    temp = i+k;
                }
            }
            i=temp;
            if(maxnow==max&&max<nums.length-1) return false;
        }
        return false;

    }
}

 

Leetcode 452 射气球 

在二维空间中有许多球形的气球。对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标。由于它是水平的,所以y坐标并不重要,因此只要知道开始和结束的x坐标就足够了。开始坐标总是小于结束坐标。

一支弓箭可以沿着x轴从不同点完全垂直地射出。在坐标x处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstartxend, 且满足  xstart ≤ x ≤ xend,则该气球会被引爆。

 

思路1:

1.将气球的右端点进行排序!!从尾部开射

2.判断一个弓箭手最多能射几个气球,尽可能多射

3. Arrays的自定义排序算法

 

class Solution {
    public int findMinArrowShots(int[][] points) {
        if(points.length<1) return 0;
        Arrays.sort(points, new Comparator<int[]>() {
            public int compare(int[] a,int[] b) {
                return a[1]-b[1];
            }
        });
        
        int sum = 0;
        for(int i=0;i<points.length;)
        {
            sum++;
            int k=i+1;
            if(k>points.length-1) break;
            while(points[i][1]>= points[k][0])
            {
                k++;
                if(k>points.length-1) break;
            }
            i=k;
        }
        return sum;
    }
}

思路2:

1.将气球的左端点进行排序!!从头部开射

2.判断一个弓箭手最多能射几个气球,尽可能多射

class Solution {
    public int findMinArrowShots(int[][] points) {
        if(points.length<1) return 0;
        Arrays.sort(points, new Comparator<int[]>() {
            public int compare(int[] a,int[] b) {
                return a[0]-b[0];
            }
        });
        
        int sum = 0;
        int end = 0;
        for(int i=0;i<points.length;)
        {
            sum++;
            int k=i+1;
            end = points[i][1];
            if(k>points.length-1) break;
            while(points[k][0]<=end)
            {
                if(points[k][1]<end) end = points[k][1];
                k++;
                if(k>points.length-1) break;
            }
            i=k;
        }
        return sum;
    }
}

Leetcode 871 最低加油次数

 

posted on 2020-04-16 16:48  洛小侠  阅读(158)  评论(0编辑  收藏  举报

导航