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

No.1盒子中小球的最大数量
解题思路

计算一个整数的每个数字之和:不断 % 10 取出最后一位并 / 10 抹掉最后一位。

代码展示

class Solution {
    public int countBalls(int lowLimit, int highLimit) {
        int[] count = new int[46];
        for (int i = lowLimit; i <= highLimit; i++) {
            int box = 0;
            for (int j = i; j > 0; j /= 10) {
                box += j % 10;
            }
            count[box]++;
        }
        return Arrays.stream(count).max().getAsInt();
    }
}

No.2 从相邻元素对还原数组
解题思路

根据相邻的边建图,得到的图一定是链状的,找到相邻节点只有一个节点的点作为起点然后进行遍历即可。

代码展示

class Solution {
    public int[] restoreArray(int[][] adjacentPairs) {
        // 建图
        Map<Integer, List<Integer>> adjacent = new HashMap<>();
        for (var a : adjacentPairs) {
            adjacent.put(a[0], adjacent.getOrDefault(a[0], new ArrayList<>()));
            adjacent.put(a[1], adjacent.getOrDefault(a[1], new ArrayList<>()));
            adjacent.get(a[0]).add(a[1]);
            adjacent.get(a[1]).add(a[0]);
        }
        // 找到起点
        int start = 0;
        for (var a : adjacentPairs) {
            if (adjacent.get(a[0]).size() == 1) {
                start = a[0];
                break;
            }
            if (adjacent.get(a[1]).size() == 1) {
                start = a[1];
                break;
            }
        }
        // 遍历这个链状的图
        Set<Integer> vis = new HashSet<>();
        int[] res = new int[adjacentPairs.length + 1];
        for (int i = 0; i < res.length; i++) {
            res[i] = start;
            vis.add(start);
            for (int j : adjacent.get(start)) {
                if (!vis.contains(j)) {
                    start = j;
                    break;
                }
            }
        }
        return res;
    }
}

No.3 你能在你最喜欢的那天吃到你最喜欢的糖果吗
解题思路

前缀和 + 二分查找。利用二分查找得出这一天能够吃到的糖果类型的最小值和最大值,判断想吃的类型是否在这个范围内即可。

代码展示

class Solution {
    public boolean[] canEat(int[] candiesCount, int[][] queries) {
        int n = candiesCount.length;
        long sum = 0;
        long[] prefixSum = new long[n];
        for (int i = 0; i < n; i++) {
            sum += candiesCount[i];
            prefixSum[i] = sum;
        }

        boolean[] res = new boolean[queries.length];
        for (int i = 0; i < queries.length; i++) {
            int left = binarySearch(queries[i][1] + 1, prefixSum);
            int right = binarySearch(((long) queries[i][2]) * (queries[i][1] + 1), prefixSum);
            res[i] = queries[i][0] >= left && queries[i][0] <= right;
        }

        return res;
    }

    private int binarySearch(long val, long[] prefixSum) {
        int left = 0, right = prefixSum.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (prefixSum[mid] >= val) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }
}

No.4 回文串分割 IV
解题思路

数据范围较小,可以直接 dp + 暴力枚举。

代码展示

class Solution {
    public boolean checkPartitioning(String s) {
        int n = s.length();
        // dp[i][j] 表示 [i, j] 的子串是否回文的
        boolean[][] dp = new boolean[n][n];
        for (int i = n - 1; i >= 0; i--) {
            for (int j = i; j < n; j++) {
                dp[i][j] = i == j || (s.charAt(i) == s.charAt(j) && (i + 1 == j || dp[i + 1][j - 1]));
            }
        }

        // 枚举两个分割点
        for (int i = 0; i < n; i++) {
            if (dp[0][i]) {
                for (int j = i + 1; j < n - 1; j++) {
                    if (dp[i + 1][j] && dp[j + 1][n - 1])
                        return true;
                }
            }
        }
        return false;
    }
}

你可能感兴趣的:(求职)