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

No.1设计Goal解析器

解题思路

详情见下方代码注解。

代码展示

class Solution {

    public String interpret(String command) {

        command = command.replaceAll("\\(\\)", "o");

        command = command.replaceAll("\\(al\\)", "al");

        return command;

    }

}

No.2 K和数对的最大数目

解题思路

使用 Map 统计每个数值的出现次数, 然后匹配即可. 为了避免重复, Map 中储存大于 k/2 的, 而之后枚举的是小于 k/2 的.

代码展示

class Solution {

    public int maxOperations(int[] nums, int k) {

        Map count = new HashMap<>();

        int halfk = 0;

        for (int num : nums) {

            if (num * 2 > k) {

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

            } else if (num * 2 == k) {

                halfk++;

            }

        }

        Arrays.sort(nums);

        int res = halfk / 2;

        for (int num : nums) {

            if (num * 2 > k) {

                break;

            }

            if (count.getOrDefault(k - num, 0) > 0) {

                res++;

                count.put(k - num, count.get(k - num) - 1);

            }

        }

        return res;

    }

}

No.3 连接连续二进制数字

解题思路

从 n 到 1 逐个拼接计算加和即可. 往一个数字 i 的二进制前拼接一个 0 不影响大小, 拼接一个 1 相当于加上一个 2 的幂.

代码展示

class Solution {

    final int mod = 1000000007;

    public int concatenatedBinary(int n) {

        int res = 0;

        int pow2 = 1;

        for (int i = n; i >= 1; i--) {

            for (int j = i; j > 0; j >>= 1) {

                if ((j & 1) == 1) {

                    res = (res + pow2) % mod;

                }

                pow2 = (pow2 << 1) % mod;

            }

        }

        return res;

    }

}

No.4最小不兼容性

解题思路

解决该题目的通用方法就是深度优先搜索. 分别枚举每个数字要放到哪个组中.

但是需要加一些优化, 否则会超时.

代码展示

class Solution {

    int res, k, cnt;

    int[] idx, latest, first, nums;

    public int minimumIncompatibility(int[] nums, int k) {

        if (nums.length == k) {

            return 0;

        }

        // 判断无解

        int[] numCnt = new int[17];

        for (int num : nums) {

            if ((++numCnt[num]) > k) {

                return -1;

            }

        }

        Arrays.sort(nums);

        this.k = k;

        this.nums = nums;

        cnt = nums.length / k;

        res = Integer.MAX_VALUE;

        idx = new int[k];

        latest = new int[k];

        first = new int[k];

        dfs(0, 0);

        return res;

    }

    private void dfs(int used, int sum) {

        if (used == nums.length) {

            res = Math.min(res, sum);

            return;

        }

        // 优化点

        if (sum >= res) {

            return;

        }

        // 枚举 nums[used] 放到哪一组中

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

            if (idx[i] < cnt && (idx[i] == 0 || latest[i] != nums[used])) {

                int newSum = sum;

                if (idx[i] == 0) {

                    first[i] = nums[used];

                } else {

                    newSum -= latest[i] - first[i];

                    newSum += nums[used] - first[i];

                }

                idx[i]++;

                int bak = latest[i];

                latest[i] = nums[used];

                dfs(used + 1, newSum);

                idx[i]--;

                latest[i] = bak;

                // 优化点: 第一个数值, 没有必要继续枚举

                if (idx[i] == 0) {

                    break;

                }

            }

        }

    }

}

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