上岸算法 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<Pair> 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<int[], Integer> 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<int[], Integer> 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值