2021-02-28 第 230 场周赛

2021-02-28 第 230 场周赛

1773. 统计匹配检索规则的物品数量

在这里插入图片描述

思路:签到题

class Solution {
    public int keyToIndex(String ruleKey) {
        if("type".equals(ruleKey)) {
            return 0;
        } else if("color".equals(ruleKey)) {
            return 1;
        } else {
            return 2;
        }
    }


    public int countMatches(List<List<String>> items, String ruleKey, String ruleValue) {
        int res = 0;
        int index = keyToIndex(ruleKey);
        for(List<String> item : items) {
            String value = item.get(index);
            if(value.equals(ruleValue)) {
                res++;
            }
        }
        return res;
    }
}

1774. 最接近目标价格的甜点成本

在这里插入图片描述
在这里插入图片描述

思路:这道题的数据量比较小,一看就可以暴力来做。遍历每种基料,然后使用三进制状态压缩来枚举每种配料的使用。

class Solution {

    // 数字转化为三进制
    public String getTernaryNum(int num) {
        StringBuffer sb = new StringBuffer();
        while(num > 0) {
            sb.append(num % 3);
            num /= 3;
        }
        return sb.toString();
    }

    public int closestCost(int[] baseCosts, int[] toppingCosts, int target) {
        int res = Integer.MAX_VALUE, mx = Integer.MAX_VALUE;
        int m = toppingCosts.length;
        for(int baseCost : baseCosts) {
            for(int i = 0;i < Math.pow(3,m);i++) {
                int toppingCost = 0;
                String ternaryNumber = getTernaryNum(i);
               // System.out.println("" + i + " " + ternaryNumber);
                for(int j = 0;j < ternaryNumber.length();j++) {
                    char cnt = ternaryNumber.charAt(j);
                    if(cnt != '0') {
                        toppingCost += ((cnt - '0') * toppingCosts[j]);
                    }
                }
                int tot = baseCost + toppingCost;


                if(Math.abs(tot - target) < mx || (Math.abs(tot - target) == mx && tot < res)) {
                    res = tot;
                    mx = Math.abs(tot - target);
                }
            }
        }
        return res;
    }
}

1775. 通过最少操作次数使数组的和相等

在这里插入图片描述

思路:参考零神的题解,思路真的太妙了
在这里插入图片描述

class Solution {
    public int minOperations(int[] nums1, int[] nums2) {
        int sum1 = 0, sum2 = 0, res = 0;
        for(int num : nums1)    sum1 += num;
        for(int num : nums2)    sum2 += num;
        if(sum1 > sum2)     return minOperations(nums2, nums1);

        int[] cnt = new int[6];
        for(int num : nums1) {
            cnt[6-num]++;
        }
        for(int num : nums2) {
            cnt[num-1]++;
        }

        int diff = sum2 - sum1;
        for(int i = 5;i > 0 && diff > 0;i--) {
            while(diff > 0 && cnt[i] > 0) {
                diff -= i;
                cnt[i]--;
                res++;
            }
        }

        return diff > 0 ? -1 : res;
    }
}

里面的计算可以加速

class Solution {
    public int minOperations(int[] nums1, int[] nums2) {
        int sum1 = 0, sum2 = 0, res = 0;
        for(int num : nums1)    sum1 += num;
        for(int num : nums2)    sum2 += num;
        if(sum1 > sum2)     return minOperations(nums2, nums1);

        int[] cnt = new int[6];
        for(int num : nums1) {
            cnt[6-num]++;
        }
        for(int num : nums2) {
            cnt[num-1]++;
        }

        int diff = sum2 - sum1;
        for(int i = 5;i > 0 && diff > 0;i--) {
            if(diff >= cnt[i] * i) {
                diff -= (cnt[i] * i);
                res += cnt[i];
                cnt[i] = 0;
            } else {
                int tmp = diff / i;
                res += tmp;
                if(diff % i != 0)   res++;
                diff = 0;
            }
        }

        return diff > 0 ? -1 : res;
    }
}

1776. 车队 II

在这里插入图片描述

思路:参考oldyan大佬的题解,比较重要的思路是:如果answer[i]为正数,那么一定是cars[i]和某个cars[j]发生了碰撞,其中j>ispeed[j]<speed[i]。相撞之后,会形成车队,进行融合,车队的速度就是车队中最慢的车辆的速度。那么很明显,此处应该是cars[j]的速度较慢,所以后面的车撞上前面的车,最后的车队速度一定是前面的车的速度,所以可以理解为cars[i]消失了,cars[j]状态不变。

因此,我们只需要关注一辆车的右边,不需要关注它的左边,它的左边对它没有任何影响。可以考虑从右往左遍历。

import java.util.Stack;

class Solution {
    public double[] getCollisionTimes(int[][] cars) {
        int n = cars.length;
        double[] res = new double[n];   res[n-1] = -1.0;
        Stack<Integer> stack = new Stack<>();
        stack.push(n-1);

        for(int i = n-2;i >= 0;i--) {
            int[] curCar = cars[i];
            while(stack.size() > 0) {
                int topIndex = stack.peek();
                // 前面一辆车的速度很快,追不上,可以等它消失后,再去追前面的车
                if(curCar[1] <= cars[topIndex][1]) {
                    stack.pop();
                } else {
                    // 前面一辆车的速度比当前这辆车要慢,可以追上

                    // 如果前面的车不会消失(融入车队)
                    if(res[topIndex] < 0) break;

                    // 如果前面的车会消失,那么需要计算能否在消失之前追上它
                    double maxDis = res[topIndex] * (curCar[1] - cars[topIndex][1]); //消失前能行驶的最长距离

                    if(maxDis >= (cars[topIndex][0]-curCar[0])) {
                        //能追上
                        break;
                    } else {
                        //消失前没法追上,只能让它消失,去找前面的车
                        stack.pop();
                    }
                }
            }

            if(stack.size() == 0) {
                res[i] = -1;
            } else {
                double t = (1.0 * (cars[stack.peek()][0]-curCar[0])) / (1.0*(curCar[1] - cars[stack.peek()][1]));
                res[i] = t;
            }

            stack.push(i);
        }

        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值