贪心算法
分发饼干
胃口值必须是最外层循环,因为不管满不满足条件它都需要移动
public int findContentChildren(int[] g, int[] s) {
Arrays.sort(g);
Arrays.sort(s);
int j=s.length-1;
int count=0;
for(int i=g.length-1;i>=0;i--){
if(j>=0 && s[j]>=g[i]){
count++;
j--;
}
}
return count;
}
摆动序列⭐
得到两个值,一个是前一段的差值,一个是后一段的插值,然后进行比较
public int wiggleMaxLength(int[] nums) {
if(nums.length==1){
return 1;
}
int result=1;
//在前面增加一个虚节点和开头节点一样
int prediff=0;
for (int i = 0; i < nums.length-1; i++) {
int curdiff=nums[i+1]-nums[i];
if (prediff<=0 && curdiff >0 || prediff>=0 && curdiff<0){
result++;
prediff=curdiff;
}
}
return result;
}
最大子数组和
局部思想:当和为负数时,直接重新从下一个开始
重点:只要sum<0就一定会重新开始,不论它与最大值的关系
public int maxSubArray(int[] nums) {
int sum=0;
int max=nums[0];
for (int i=0;i<nums.length;i++){
sum=sum+nums[i];
if (sum>max){
max=sum;
}
if (sum < 0) {
sum=0;
}
}
return max;
}
买卖股票的最佳时机
思路:每两天的利润值,大于0则相加
public int maxProfit(int[] prices) {
int result=0;
for(int i=1;i<prices.length;i++){
int temp=prices[i]-prices[i-1];
temp=temp>0?temp:0;
result=result+temp;
}
return result;
}
跳跃游戏
当覆盖范围大于nums.length-1时也是成功。
思路:只看覆盖范围
public boolean canJump(int[] nums) {
int maxRange=0;
for (int i = 0; i<= maxRange; i++) {
int range=i+nums[i];
maxRange=maxRange>range?maxRange:range;
if (maxRange>=nums.length-1){
return true;
}
}
return false;
}
跳跃游戏中返回跳跃的次数
遍历for循环,因为需要判断i==当前覆盖范围最大值时,此时应当count++,把下一步的最大值赋给当前范围。
public int jump(int[] nums) {
if (nums.length==1){
return 0;
}
//当前覆盖的最远距离下标
int maxRange=0;
//下一步覆盖的最远距离下标
int next=0;
int count=0;
for (int i = 0; i <nums.length; i++) {
next=Math.max(next,i+nums[i]);
//下一步仔跳异步就会到达末尾
if (next>=nums.length-1){
count++;
break;
}
if (i==maxRange){
count++;
maxRange=next;
}
}
return count;
}
K次取反后最大化的数组和
先排序 将负数全部取正,如果k不够立即跳出
若k还有剩且是奇数 将数组重新排序,将最小的正数取反
public int largestSumAfterKNegations(int[] nums, int k) {
//对数组进行排序
Arrays.sort(nums);
//将最小的负数加上负号
for (int i = 0; i < nums.length; i++) {
if (nums[i]>=0){
break;
}
nums[i]=-nums[i];
k--;
//如果k为0 直接结束
if (k==0){
break;
}
}
if (k>0 && k%2==1){
Arrays.sort(nums);
nums[0]=-nums[0];
}
int sum=0;
for (int i = 0; i < nums.length; i++) {
sum=sum+nums[i];
}
return sum;
}
加油站
得到每到一个加油站油的剩余情况,如果和为负数,则无解
若和>=0,当前面为负数时,肯定不是起始加油站,从下一个加油站开始重新作为起点,直到找到一个从起始到结束为正数的。
public int canCompleteCircuit(int[] gas, int[] cost) {
int[] res=new int[gas.length];
int curSum=0;
for(int i=0;i<gas.length;i++){
res[i]=gas[i]-cost[i];
curSum+=res[i];
}
if(curSum<0){
return -1;
}
curSum=0;
int th=0;
for(int i=0;i<res.length;i++){
curSum=curSum+res[i];
if(curSum<0){
curSum=0;
th=i+1;
}
}
return th;
}
分发糖果
必须要两次遍历,从前往后遍历,拿右孩子和左孩子比较
再从后往前遍历,拿左孩子和右孩子比较,最终给的糖果数取两次最高的值
public int candy(int[] ratings) {
int[] candy=new int[ratings.length];
Arrays.fill(candy,1);
//从前往后 右孩子比左孩子得分高的情况
for (int i = 1; i < ratings.length; i++) {
if (ratings[i]>ratings[i-1]){
candy[i]=candy[i-1]+1;
}
}
//从后往前 左孩子比右孩子得分高的情况
for (int i = ratings.length-1; i >0; i--) {
if (ratings[i-1]>ratings[i]){
//比较两次结果candy的最大值
candy[i-1]=Math.max(candy[i-1],candy[i]+1);
}
}
int sum=0;
for (int i = 0; i < candy.length; i++) {
sum+=candy[i];
}
return sum;
}


浙公网安备 33010602011771号