贪心算法
摆动序列
题目链接: https://leetcode.cn/problems/wiggle-subsequence/
思路:其实就是看差值序列 正负和负正的组合有多少个,pre可以取0,这样才可以启动
class Solution {
public int wiggleMaxLength(int[] nums) {
int pre = 0;
int cur = 0;
int count = 0;
for(int i =1;i<nums.length;i++){
cur = nums[i] - nums[i-1];
if((pre>=0&&cur<0)||(pre<=0&&cur>0)){
count++;
pre = cur;
}
}
return count+1;
}
}
加油站
题目链接:https://leetcode.cn/problems/gas-station/
思路1:计算中途最小的,如果全程大于等于0,则从0开始,否则从后开始遍历,填平最小的的加油站则是起点
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int min = 0;
int count = 0;
for(int i = 0;i<gas.length;i++){
count += gas[i] - cost[i];
min = Math.min(min,count);
}
if(count< 0 ) return -1;
if(min>=0) return 0;
for(int i = gas.length-1;i>=0;i--){
min += gas[i] - cost[i];
if(min>=0) return i;
}
return -1;
}
}
思路2(copy代码随想录):每个加油站的剩余量rest[i]为gas[i] - cost[i]。
i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置,因为这个区间选择任何一个位置作为起点,到i这里都会断油,那么起始位置从i+1算起,再从0计算curSum。
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int count = 0;
int index = 0;
int total = 0;
for(int i = 0;i<gas.length;i++){
count += gas[i] - cost[i];
total += gas[i] - cost[i];
if(count<0){
index = i+1;
count = 0;
}
}
return index==gas.length||total<0?-1:index;
}
}
分发糖果
题目链接:https://leetcode.cn/problems/candy/
思路:2次遍历,从左往右,从右往左
class Solution {
public int candy(int[] ratings) {
int[] left = new int[ratings.length];
left[0] = 1;
for(int i=1;i<ratings.length;i++){
if(ratings[i]>ratings[i-1]){
left[i] = left[i-1]+1;
}else{
left[i] = 1;
}
}
int[] right = new int[ratings.length];
right[ratings.length-1] = 1;
for(int i=ratings.length-2;i>=0;i--){
if(ratings[i]>ratings[i+1]){
right[i] = right[i+1]+1;
}else{
right[i] = 1;
}
}
int sum = 0;
for(int i = 0;i<ratings.length;i++){
sum += Math.max(left[i],right[i]);
}
return sum;
}
}
用最少数量的箭引爆气球
题目链接:https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/
class Solution {
public int findMinArrowShots(int[][] points) {
Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));
int count = 1;
int right = points[0][1];
for (int i = 1;i< points.length;i++){
System.out.println(points[i][0]);
System.out.println(right);
if (points[i][0]>right){
right = points[i][1];
count++;
}else {
right = Math.min(right,points[i][1]);
}
}
return count;
}
}
按右端点排序
class Solution {
public int findMinArrowShots(int[][] points) {
Arrays.sort(points, (a, b) -> Integer.compare(a[1], b[1]));
int count = 1;
int right = points[0][1];
for (int i = 1;i< points.length;i++){
if (points[i][0]>right){
right = points[i][1];
count++;
}
}
return count;
}
}
监控二叉树
题目链接:https://leetcode.cn/problems/binary-tree-cameras/
思路:后序遍历+0,1,2三个状态指示,最后需要判断一下根节点的状态
class Solution {
int count = 0;
public int minCameraCover(TreeNode root) {
int index = search(root);
return index==0?count+1:count;
}
public int search(TreeNode node){
if (node==null){
return 2;
}
int left = search(node.left);
int right = search(node.right);
if (left==0 || right==0){
count++;
return 1;
}
if (left == 2 && right ==2){
return 0;
}
return 2;
}
}
单调递增的数字
题目链接:https://leetcode.cn/problems/monotone-increasing-digits/
思路:从倒数第二位开始遍历,如不得不降低那么记录一下当前位置,后面的都是9
class Solution {
public int monotoneIncreasingDigits(int n) {
String s = n+"";
char[] c =s.toCharArray();
int index = c.length;
for (int i = c.length-2;i>=0;i--){
if (c[i]>c[i+1]){
c[i]--;
index = i+1;
}
}
for (;index<c.length;index++){
c[index] = '9';
}
s = String.valueOf(c);
return Integer.valueOf(s);
}
}