上岸算法 I LeetCode Weekly Contest 244解题报告

No.1判断矩阵经轮转后是否一致

解题思路

模拟矩阵的旋转即可。

代码展示

class Solution {

    public boolean findRotation(int[][] mat, int[][] target) {

        for (int i = 0; i < 4; i++) {

            if (equal(mat, target)) {

                return true;

            }

            mat = rotate(mat);

        }

        return false;

    }

    private int[][] rotate(int[][] mat) {

        int[][] r = new int[mat.length][mat[0].length];

        for (int i = 0, y = 0; i < mat.length; i++, y++) {

            for (int j = 0, x = mat.length - 1; j < mat[0].length; j++, x--) {

                r[i][j] = mat[x][y];

            }

        }

        return r;

    }

    boolean equal(int[][] mat, int[][] target) {

        for (int i = 0; i < mat.length; i++) {

            for (int j = 0; j < mat[0].length; j++) {

                if (mat[i][j] != target[i][j]) {

                    return false;

                }

            }

        }

        return true;

    }

}

No.2 使数组元素相等的减少操作次数

解题思路

简单暴力地,从大到小依次处理每个元素即可。使用 TreeMap 的代码非常简洁,或者可以使用链表,速度更快。

代码展示

class Solution {

    public int reductionOperations(int[] nums) {

        TreeMap count = new TreeMap<>();

        for (var num : nums) {

            count.put(num, count.getOrDefault(num, 0) + 1);

        }

        int result = 0;

        while (count.size() > 1) {

            var largest = count.pollLastEntry();

            var nextLargest = count.lastEntry();

            result += largest.getValue();

            count.put(nextLargest.getKey(), nextLargest.getValue() + largest.getValue());

        }

        return result;

    }

}

No.3 使二进制字符串字符交替的最少反转次数

解题思路

枚举类型 1 操作执行的次数即可。

执行完类型 1 的操作之后,需要执行的类型 2 的操作次数是固定的。

我们只需要知道奇数下标上 0 和 1 的数量、偶数下标上 0 和 1 的数量就可以计算出类型 2 的操作次数。

每执行一次类型 1 的操作,奇数下标上 0 和 1 的数量、偶数下标上 0 和 1 的数量的变化都可以 O(1) 地计算出来。

代码展示

class Solution {

    public int minFlips(String s) {

        char[] str = s.toCharArray();

        // count[0] 表示偶数下标上 0 和 1 的数量

        // count[1] 表示奇数下标上 0 和 1 的数量

        int[][] count = new int[2][2];

        for (int i = 0; i < str.length; i++) {

            count[i % 2][str[i] - '0']++;

        }

        int result = Math.min(count[1][1] + count[0][0], count[1][0] + count[0][1]);

        for (int i = 0; i < str.length - 1; i++) {

            count[0][str[i] - '0']--;

            int tmp = count[1][0];

            count[1][0] = count[0][0];

            count[0][0] = tmp;

            tmp = count[1][1];

            count[1][1] = count[0][1];

            count[0][1] = tmp;

            count[(str.length - 1) % 2][str[i] - '0']++;

            result = Math.min(result, Math.min(count[1][1] + count[0][0], count[1][0] + count[0][1]));

        }

        return result;

    }

}

No.4 装包裹的最小浪费空间

解题思路

二分查找。

对所有的包裹和供应商的盒子都排序,然后依次枚举每个供应商即可。

计算一个供应商的盒子的浪费空间时,从小到大使用每种盒子,每种盒子尽可能多装包裹即可,使用前缀和数组和二分查找可以快速计算结果。

代码展示

class Solution {

    public int minWastedSpace(int[] packages, int[][] boxes) {

        Arrays.sort(packages);

        long[] preSum = new long[packages.length];

        preSum[0] = packages[0];

        for (int i = 1; i < preSum.length; i++) {

            preSum[i] = preSum[i - 1] + packages[i];

        }

        long result = -1;

        for (int[] box : boxes) {

            Arrays.sort(box);

            long t = waste(packages, preSum, box);

            if (t != -1 && (result == -1 || t < result)) {

                result = t;

            }

        }

        return (int) (result % 1000000007L);

    }

    private long waste(int[] packages, long[] preSum, int[] boxes) {

        int start = 0;

        long result = 0;

        for (int box : boxes) {

            if (box < packages[start]) {

                continue;

            }

            int index = binarySearch(packages, box);

            // [start, index] 之间的包裹使用 box 装

            result += (long) box * (index - start + 1) - preSum[index];

            if (start != 0) {

                result += preSum[start - 1];

            }

            start = index + 1;

            if (start >= packages.length) {

                return result;

            }

        }

        return -1;

    }

    private int binarySearch(int[] arr, int target) {

        int l = 0, r = arr.length - 1;

        while (l + 1 < r) {

            int mid = (l + r) / 2;

            if (arr[mid] <= target) {

                l = mid;

            } else {

                r = mid;

            }

        }

        return arr[r] <= target ? r : l;

    }

}

你可能感兴趣的:(上岸算法 I LeetCode Weekly Contest 244解题报告)