Leetcode 244周赛-赛后补题题解【西兰花选手】

Problem A-判断矩阵经轮转后是否一致

题意: 以 90 度顺时针轮转矩阵 mat 中的元素 若干次,如果mat矩阵与target一致,返回true,否则返回false

思路: 直接模拟就可以了,做这题的时候还费劲写了一个原地算法,y神说了没必要,直接开一个二维数组即可。

代码:

Java中不能直接判断两个二维数组的内容是否相同,恶心!

class Solution {
    public boolean findRotation(int[][] mat, int[][] target) {
        int n = mat.length, num = 3;
        boolean flag = false;
        for (int i = 0; i < n; i++){
            for (int j = 0; j < n; j++){
                if (mat[i][j] != target[i][j]) {
                    flag = true; break;
                }
            }
            if (flag)break;
        }
        if (!flag)return true;

        while(num-- > 0) {
            for(int i=0; i<n/2; i++) {
                 for(int j=i; j<n-i-1; j++) {
                     int t = mat[i][j];
                     mat[i][j] = mat[n-j-1][i];
                     mat[n-j-1][i] = mat[n-i-1][n-j-1];
                     mat[n-i-1][n-j-1] = mat[j][n-i-1];
                     mat[j][n-i-1] = t;
                 }
            }
            
            flag = false;
            for (int i = 0; i < n; i++){
                for (int j = 0; j < n; j++){
                    if (mat[i][j] != target[i][j]) {
                        flag = true; break;
                    }
                }
                if (flag)break;
            }
            if (!flag)return  true;
        }
        return false;
    }
}

Problem B-使数组元素相等的减少操作次数

思路: 每个元素a需要经历t个阶段最后变成相等最小值,t就是数组中比元素a小的元素种类和。所以先把数组排序,然后统计(元素前边比他小的元素种类即可)

代码:

class Solution {
    public int reductionOperations(int[] nums) {
        int len = nums.length;
        Arrays.sort(nums);
        int pre[] = new int[len + 1];
        int count = 0;
        pre[0] = 0;
        for (int i = 1; i < len; i++) {
            if ((nums[i] - nums[i-1]) != 0) {
                pre[i] = pre[i - 1] + 1;
            } else {
                pre[i] = pre[i - 1];
            }
        }
        // 下边的累加可以放在第一个for循环中
        int res = 0;
        for (int i = 1; i < len; i++) {
            res += pre[i];
        }
        return res;
    }
}

Problem C-使二进制字符串字符交替的最少反转次数

思路: 两种类型的操作,让统计第二种类型操作的最少次数。第一种类型操作的特殊性,让我想到将两个原串拼接在一起,然后滑动窗口,取第二种操作的最少次数。最终字符串有两种:“0101010101…”或"1010101010…",比较两串不同元素个数即可。

代码:

class Solution {
    public int minFlips(String s) {
        int len = s.length(), t = 2, res = Integer.MAX_VALUE;
        String time = s + s;
        
        t = 2;
        while (t-- > 0) {
            int count = 0, j = t;
            for (int k = 0; k < len; j ^= 1, k++) {
                count += (time.charAt(k) ==  (j +'0')) ? 0:1;
            }
            res = Math.min(res, count);

            for (int k = len, p = t; k < len*2; j ^= 1, p ^= 1, k++) {
                count -= (time.charAt(k - len) ==  (p +'0')) ? 0:1;
                count += (time.charAt(k) ==  (j +'0')) ? 0:1;
                res = Math.min(res, count);
            }
        }
        return res;
    }
}

Problem D-装包裹的最小浪费空间

思路: 遍历supplier,让box二分package,计算出该supplier所需要的总容积,最后取最小的容积,减去packages的总和。如果遍历package,让package二分box,会超时。

代码:

class Solution {
    final long mod = (long)(1e9 + 7);
    final long inf = (long)1e18;

    public int minWastedSpace(int[] packages, int[][] boxes) {
        int supplierNum = boxes.length, packagesNum = packages.length;

        long res = inf, sum = 0;
        // 包裹总和
        for (int i = 0; i < packagesNum; i++) {
            sum += packages[i];
        }
		
        Arrays.sort(packages);

        for (int i = 0; i < supplierNum; i++) {
            int len = boxes[i].length, left = -1, right = packagesNum - 1, last = -1;
            long count = -sum;

            Arrays.sort(boxes[i], 0, len);
            if (packages[packagesNum - 1] > boxes[i][len - 1]) continue;
			// 统计box总的容积
            for (int j = 0; j < len; j ++) {
                left = upperBound(packages, left, right, boxes[i][j]);

                if (left == last) continue;
                count += ((long)(left - last) * boxes[i][j]);
                last = left;
            }
            res = Math.min(res, count);
        }
        if (res == inf) return -1;
        return (int)(res % mod);
    }

    public int upperBound(int[] a, int left, int right, int key) {
        int mid;
        while (left < right) {
            mid = (left + right + 1) >> 1;
            if (a[mid] > key) {
                right = mid - 1;
            } else {
                left = mid;
            }
        }
        return left;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Honyelchak

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值