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

No.1重新格式化电话号码

解题思路

预处理两种特殊符号之后的字符串根据长度 len 分一下三种情况

len % 3 == 0: 直接拼接

len % 3 == 1: 保留最后四位特殊拼接

len % 3 == 2: 保留最后两位特殊拼接

代码展示

class Solution {

    public String reformatNumber(String number) {

        if (number == null || number.length() == 0) {

            return "";

        }

        int n = number.length();

        StringBuilder tempString = new StringBuilder();

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

            char c = number.charAt(i);

            if (c == '-' || c == ' ') {

                continue;

            }

            tempString.append(c);

        }

        int tmpSize = tempString.length();

        StringBuilder resString = new StringBuilder();

        if (tmpSize % 3 == 0) {

            for (int i = 0; i < tmpSize; i += 3) {

                resString.append(tempString.charAt(i))

                        .append(tempString.charAt(i + 1))

                        .append(tempString.charAt(i + 2));

                if (i != tmpSize - 3) {

                    resString.append('-');

                }

            }

            return resString.toString();

        }

        else if (tmpSize % 3 == 1) {

            int tmpL = tmpSize - 4;

            for (int i = 0; i < tmpL; i += 3) {

                resString.append(tempString.charAt(i))

                        .append(tempString.charAt(i + 1))

                        .append(tempString.charAt(i + 2))

                        .append('-');

            }

            resString.append(tempString.charAt(tmpL))

                    .append(tempString.charAt(tmpL + 1))

                    .append('-')

                    .append(tempString.charAt(tmpL + 2))

                    .append(tempString.charAt(tmpL + 3));

            return resString.toString();

        }

        else {

            int tmpL = tmpSize - 2;

            for (int i = 0; i < tmpL; i += 3) {

                resString.append(tempString.charAt(i))

                        .append(tempString.charAt(i + 1))

                        .append(tempString.charAt(i + 2))

                        .append('-');

            }

            resString.append(tempString.charAt(tmpL))

                    .append(tempString.charAt(tmpL + 1));

            return resString.toString();

        }

    }

}

No.2 删除子数组的最大得分

解题思路

同向双指针经典应用

left 指针枚举起点

right指针不断的扩大sunArray的范围

当不满足条件时,移动left指针使得满足条件

代码展示

public int maximumUniqueSubarray(int[] nums) {

        if (nums == null || nums.length == 0) {

            return 0;

        }

        int n = nums.length;

        int res = 0;

        int tmpSum = 0;

        // two point

        // 枚举左端点left,右端点right,记录left ~ right 之间重复字符个数

        int left = 0, right = 0;

        int []counts = new int[10001];

        while (left < n && right < n) {

            int num = nums[right];

            counts[num] += 1;

            tmpSum += num;

            // subArray 存在重复数字,从left开始移除,直到满足条件

            while (left < n && counts[num] > 1) {

                tmpSum -= nums[left];

                counts[nums[left]] -= 1;

                left++;

            }

            res = Math.max(res, tmpSum);

            right++;

        }

        return res;

    }

No.3跳跃游戏 VI

解题思路

动态规划加优先队列

数据结构Pair,当前位置的结果值value,当前位置的index

优先队列的堆首是已经到达过位置结果值最大的

判断队首的位置能否调达至当前位置i

代码展示

class Solution {

    static class Pair {

        int value;

        int index;

        Pair(int value, int index) {

            this.value = value;

            this.index = index;

        }

    }

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

        if (nums == null || nums.length == 0) {

            return 0;

        }

        int n = nums.length;

        // 单调队列【优先队列】

        PriorityQueue queue = new PriorityQueue<>((o1, o2) -> o2.value - o1.value);

        queue.offer(new Pair(nums[0], 0));

        int res = nums[0];

        for (int i = 1; i < n; i++) {

            // 选择一个可到达的目的地中最大的那个跳跃,不满足则出队列

            while (!queue.isEmpty() && i - queue.peek().index > k) {

                queue.poll();

            }

            if (!queue.isEmpty()) {

                res = queue.peek().value + nums[i];

            }

            queue.offer(new Pair(res, i));

        }

        return res;

    }

}

No.4 检查边长度限制的路径是否存在

解题思路

查询按照距离限制排序,记录在TreeMap,query => index

边集合根据边权重排序

针对每一个查询

只构建边权重小于limit的边

判断查询的点是否连通

代码展示

// 并查集模板

static class UnionFind {

    int[] father;

    UnionFind(int n) {

        father = new int[n];

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

            father[i] = i;

        }

    }

    public int find(int x) {

        if (x == father[x]) {

            return x;

        }

        return father[x] = find(father[x]);

    }

    public void union(int a, int b) {

        int fatherA = find(a);

        int fatherB = find(b);

        if (fatherA != fatherB) {

            father[fatherA] = fatherB;

        }

    }

}

public boolean[] distanceLimitedPathsExist(int n, int[][] edgeList, int[][] queries) {

    // key:query[start, end, limit] value: index

    // 按照距离远近排序,距离从小到大

    TreeMap map = new TreeMap<>((o1, o2) -> o1[2] != o2[2] ? o1[2] - o2[2] : 1);

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

        map.put(queries[i], i);

    }

    // 图的边集合也根据边的权重排序

    Arrays.sort(edgeList, Comparator.comparingInt(o -> o[2]));

    boolean[] res = new boolean[queries.length];

    UnionFind unionFind = new UnionFind(n);

    int index = 0;

    while (!map.isEmpty()) {

        Map.Entry curr = map.pollFirstEntry();

        int[] query = curr.getKey();

        int currIn = curr.getValue();

        // 只连接比limit更小的那些边

        while (index < edgeList.length && edgeList[index][2] < query[2]) {

            unionFind.union(edgeList[index][0], edgeList[index][1]);

            index++;

        }

        // 查询两端点是否连通

        res[currIn] = (unionFind.find(query[0]) == unionFind.find(query[1]));

    }

    return res;

}

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