2021-01-24 第 225 场周赛

2021-01-24 第 225 场周赛

1736. 替换隐藏数字得到的最晚时间

思路:只需要枚举时间,然后看是否匹配,匹配的时间里面取最大的就可以了。

class Solution {
    public boolean check(char[] a, char[] b) {
        for(int i = 0;i < a.length;i++) {
            if(a[i] == '?' || a[i] == ':')   continue;
            else if(a[i] != b[i]){
                return false;
            }
        }
        return true;
    }

    public String maximumTime(String time) {
        char[] s = time.toCharArray();
        int n = s.length;
        String res = "";

        for(int h = 0;h <= 23;h++) {
            for(int m = 0;m < 60;m++) {
                String hour = h >= 10 ? "" + h : "0" + h;
                String minute = m >= 10 ? "" + m : "0" + m;
                String curTime = hour + ":" + minute;
                if(check(time.toCharArray(), curTime.toCharArray())) {
                    res = curTime;
                }
            }
        }

        return res;
    }
}

1737. 满足三条件之一需改变的最少字符数

思路:这道题一开始的时候WA了一次,以为是简单的枚举三种情况就好了,其实并不是。需要的是枚举以下情况:

  • a以字母α最大, b 以字母β最小,α < β,此时需要修改的个数
  • a以字母α最小, b 以字母β最大,α > β,此时需要修改的个数
  • a 和 b 都只含有字母α时,需要修改的次数

a以字母α最大需要修改的个数,可以通过前缀和的方式求出。同理, b 以字母β最小需要修改的个数,也可以通过前缀和的方式求出。所以这题就可以做出来了。

class Solution {
    public int cal(int[] cntA, int[] sumA, int[] cntB, int[] sumB) {
        int res = (int) (1e6);
        for(int i = 0;i < 25;i++) {
            int changeA = sumA[25] - sumA[i];
            for(int j = i+1;j <= 25;j++) {
                int changeB = sumB[j-1];
                res = Math.min(res, changeA + changeB);
            }
        }
        return res;
    }
    
    public int minCharacters(String _a, String _b) {
        char[] a = _a.toCharArray(), b = _b.toCharArray();
        int A = a.length, B = b.length, res = (int) (1e6);
        int[] cntA = new int[26], cntB = new int[26];
        int[] sumA = new int[26], sumB = new int[26];
        for(char ch : a)    cntA[ch-'a']++;
        for(char ch : b)    cntB[ch-'a']++;
        for(int i = 0;i < 26;i++) {
            sumA[i] = cntA[i];  sumB[i] = cntB[i];
            if(i > 0) {
                sumA[i] += sumA[i-1];
                sumB[i] += sumB[i-1];
            }
        }
        
        res = Math.min(res, cal(cntA, sumA, cntB, sumB));
        res = Math.min(res, cal(cntB, sumB, cntA, sumA));
        
        for(int i = 0;i < 26;i++) {
            res = Math.min(res, A + B - cntA[i] - cntB[i]);
        }

        return res;
    }
}

1738. 找出第 K 大的异或坐标值

在这里插入图片描述

思路:就是个二维前缀和的模板,来计算二维前缀异或值。然后把它们放到一个list里面,取出第k大的值即可。

class Solution {
    public int kthLargestValue(int[][] matrix, int k) {
        int rows = matrix.length, cols = matrix[0].length;
        int[][] a = new int[rows][cols];
        List<Integer> list = new ArrayList<>();

        for(int i = 0;i < rows;i++) {
            int v = 0;
            for(int j = 0;j < cols;j++) {
                v = v ^ matrix[i][j];
                if(i > 0) {
                    a[i][j] = v ^ a[i-1][j];
                } else {
                    a[i][j] = v;
                }
                list.add(a[i][j]);
            }
        }
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        return list.get(k-1);
    }
}

1739. 放置盒子

有一个立方体房间,其长度、宽度和高度都等于 n 个单位。请你在房间里放置 n 个盒子,每个盒子都是一个单位边长的立方体。放置规则如下:

  • 你可以把盒子放在地板上的任何地方。
  • 如果盒子 x 需要放置在盒子 y 的顶部,那么盒子 y 竖直的四个侧面都 必须 与另一个盒子或墙相邻。

给你一个整数 n ,返回接触地面的盒子的 最少 可能数量。

在这里插入图片描述

思路:其实就是一道数学题,当时比赛过程中觉得太麻烦没仔细推。赛后看题解发现规律其实也还蛮简单的

底下盒子数总盒子数盒子总量增加
000
111
221
342
451
572
6103
7111

底下的盒子每增加一个,可以放置的总盒子增加数呈现规律性:1,1,2,1,2,3,1,2,3,4……

那么这样代码写起来就简单了。。。

class Solution {
    public int minimumBoxes(int n) {
        int sum = 0, bottom = 0;
        for(int height = 1; sum < n;height++) {
            // i表示盒子总量增加数
            for(int i = 1;i <= height && sum < n;i++) {
                bottom++;
                sum += i;
            }
        }

        return bottom;
    }
}

更快速的方法,我们可以先不停的加盒子数,直到总数超过给定n的大小,再开始移除。移除的时候,如果当前高度是height,每想要减小一个底下盒子数,需要拿掉的盒子数为:height,height-1,height-2……

class Solution {
    public int minimumBoxes(int n) {
        int sum = 0, bottom = 0,height = 1;
        for(height = 0; sum < n;) {
            height++;
            bottom = height * (height + 1) / 2;
            sum += bottom;
        }

        for(int i = height;i > 0 && sum >= n;i--) {
            sum -= i;
            bottom--;
        }

        // 这时候盒子总数已经比n小,所以上次操作是不能进行的,需要加回来
        return bottom+1;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值