小小算法——Day2

71 阅读3分钟

K 次取反后最大化的数组和

这道题也是贪心算法,很简单,维护一个最小堆,每次取反最小值就可以了


class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        int res = 0;
        PriorityQueue<Integer> que = new PriorityQueue<>();
        for(int i = 0;i < nums.length;i ++){
            que.add(nums[i]);
        }
        for(int j = 0;j < k;j ++){
            int out = que.poll();
            que.add(-out);
        }
        while(!que.isEmpty()){
            res += que.poll();
        }
        return  res;
    }
}

加油站

这道题得从两个角度去判断,首先判断gas的总和是否能包括cost,如果不能包括直接返回-1,然后在推导局部最优——当gas - cost能覆盖的时候直接更新start为第一次覆盖的下标,一旦不能覆盖,则从下一个下标重新开始

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        // 首先从全局来看,如果cost总和大于gas,那么一定不能够支持跑一圈,所以首先计算出总cost和总gas进行比较,成功进行下一步
        // 然后按照贪心的思想,只要gas可以覆盖当前cost,就可以进行选择,如果不能的话,从i + 1开始

        //当前收获和前往下一个节点的差距
        int cur = 0;
        // 判断总和是否大于0
        int sum = 0;
        // 开始的位置
        int start = 0;
        for(int i = start;i < cost.length;i ++){
            sum += gas[i] - cost[i];
            cur += gas[i] - cost[i];
            // 当获得的gas小于下一站的花费,直接从下一站重新开始计算
            if(cur < 0){
                start = i + 1;
                cur = 0;
            }
        }
        // 总和小于0直接返回
        if(sum < 0){
            return -1;
        }
        return start;
    }
}

分发糖果

分发糖果需要考虑元素的左右元素的大小,所以需要两次遍历,一次统一右侧元素,一次统一左侧元素

在统一右侧元素时,唯一遵守的就是:只要当前的分比上一个高,就在上一个的基础上加一

在统一左侧元素的时候,与统一右侧元素不同的是,我们要在满足右侧元素的基础上维护左侧元素,所以就取两次结果的最大值

注意事项:注意循环的范围限制和数组的值是前一个还是后一个

class Solution {
    public int candy(int[] ratings) {
        int len = ratings.length;
        // 糖果数量对比
        int[] candyVec = new int[len];
        candyVec[0] = 1;
        // 糖果数组和
        int sum = 0;
        // 循环对比
        for(int i = 1;i < len;i ++){
            candyVec[i] = (ratings[i] > ratings[i - 1]) ? candyVec[i - 1] + 1 : 1;
        }
        // 从后向前
        for(int i = len - 2;i >= 0;i --){
            if(ratings[i] > ratings[i + 1]){
                candyVec[i] = Math.max(candyVec[i],candyVec[i + 1] + 1);
            }
        }
        
        for(int i : candyVec){
            sum += i;
        }
        return sum;

    }
}

柠檬水找零

我们要先做一次数组第一个元素的判断,如果元素大于5,那么就要拜拜了,使用哈希存储目前手里有的钱,其实就是读到数字,然后add,同时找零的那个钱remove掉

class Solution {
    public boolean lemonadeChange(int[] bills) {
        // 如果第一个元素大于5直接寄
        if(bills[0] > 5){
            return false;
        }
        int len = bills.length;
        Map<Integer,Integer> cash = new HashMap<>();
        cash.put(5,0);
        cash.put(10,0);
        for(int i = 0;i < len;i ++){
            cash.put(bills[i],cash.getOrDefault(bills[i],0) + 1);
            int change = bills[i] - 5;
            if(change == 5){
                if (cash.get(5) > 0) {
                    cash.put(5, cash.get(5) - 1);
                } else {
                    return false;
                }
            }else if(change == 15){
                if(cash.get(10) > 0 && cash.get(5) > 0){
                    cash.put(10, cash.get(10) - 1);
                    cash.put(5, cash.get(5) - 1);
                }else if(cash.get(5) >= 3){
                    cash.put(5, cash.get(5) - 3);
                }else{
                    return false;
                }
            }
                
        }

        return true;
    }
}

找出缺失和重复的数字

这是每日一题

一开始思路跑偏了,想着用HashMap解决,后来一想,HashMap是无序的,只能算出那个元素重复了,没办法判断少了哪个元素,所以用了暴力的解决方法,直接把grid拉长有序化,新建一个对比数组count,如果元素存在,则在该下标出+1表示元素出现了一次,当元素是4的时候,就会在count[4]处填写1,出现第二次则再次自增填写2,然后遍历count就可以了,时间复杂度是On2

class Solution {
    public int[] findMissingAndRepeatedValues(int[][] grid) {
        int n = grid.length;
        int[] res = new int[2];
        int[] count = new int[n * n + 1];
        for(int[] row : grid){
            for(int i : row){
                count[i] ++;
            }
        }
        for(int i = 0;i < count.length;i ++){
            if(count[i] == 2){
                res[0] = i;
            }
            if(count[i] == 0){
                res[1] = i;
            }
        }
        return res;
    }
}

emmm,力扣上耗时有点大,可以考虑一下优化