贪心算法
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处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足 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 最低加油次数