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

No.1最大升序子数组和

解题思路

注意该题目的子数组是连续的。因此枚举起始位置即可。

代码展示

class Solution {

    public int maxAscendingSum(int[] nums) {

        int res = nums[0];

        for (int start = 0; start < nums.length; start++) {

            int sum = nums[start];

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

                if (nums[i] > nums[i - 1]) {

                    sum += nums[i];

                } else {

                    break;

                }

            }

            res = Math.max(res, sum);

        }

        return res;

    }

}

No.2 积压订单中的订单总数

解题思路

使用 PriorityQueue 或者 TreeMap 维护两类挤压订单即可。

代码展示

class Solution {

    public int getNumberOfBacklogOrders(int[][] orders) {

        TreeMap toSell = new TreeMap();

        TreeMap toBuy = new TreeMap();

        for (var order : orders) {

            if (order[2] == 0) {

                // buy

                while (order[1] > 0) {

                    var entry = toSell.firstEntry();

                    if (entry == null || entry.getKey() > order[0]) {

                        break;

                    }

                    int cnt = Math.min(entry.getValue(), order[1]);

                    order[1] -= cnt;

                    if (cnt == entry.getValue()) {

                        toSell.remove(entry.getKey());

                    } else {

                        toSell.put(entry.getKey(), entry.getValue() - cnt);

                    }

                    // break;

                }

                if (order[1] > 0) {

                    toBuy.put(order[0], order[1] + toBuy.getOrDefault(order[0], 0));

                }

            } else {

                // sell

                while (order[1] > 0) {

                    var entry = toBuy.lastEntry();

                    if (entry == null || entry.getKey() < order[0]) {

                        break;

                    }

                    int cnt = Math.min(entry.getValue(), order[1]);

                    order[1] -= cnt;

                    if (cnt == entry.getValue()) {

                        toBuy.remove(entry.getKey());

                    } else {

                        toBuy.put(entry.getKey(), entry.getValue() - cnt);

                    }

                    // break;

                }

                if (order[1] > 0) {

                    toSell.put(order[0], order[1] + toSell.getOrDefault(order[0], 0));

                }

            }

        }

        int res = 0;

        for (var entry : toSell.entrySet()) {

            res = (res + entry.getValue()) % 1000000007;

        }

        for (var entry : toBuy.entrySet()) {

            res = (res + entry.getValue()) % 1000000007;

        }

        return res;

    }

}

No.3 有界数组中指定下标处的最大值

解题思路

二分答案。当指定下标处的值确定后,贪心地令其他元素尽可能小即可,所以就是等差数列求和。

代码展示

class Solution {

    public int maxValue(int n, int index, int maxSum) {

        long l = 0, r = maxSum;

        while (l + 1 < r) {

            long mid = (l + r) / 2;

            if (check(mid, index, maxSum, n)) {

                l = mid;

            } else {

                r = mid;

            }

        }

        return (int) (check(r, index, maxSum, n) ? r : l);

    }

    long sum(long start, long count) {

        if (count <= 0) {

            return 0;

        }

        if (start < count) {

            return (start + 1) * start / 2 + (count - start);

        }

        return (start + start - count + 1) * count / 2;

    }

    boolean check(long value, long index, long maxSum, long n) {

        long left = index;

        long right = n - index - 1;

        return sum(value - 1, left) + sum(value - 1, right) + value <= maxSum;

    }

}

No.4 统计异或值在范围内的数对有多少

解题思路

求 [low, high] 区间内的等同于求 [low, inf) 再减去 (high, inf)。

因此问题转换成求异或值大于给定数值的数对数量。使用字典树即可。

代码展示

class Solution {

    public int countPairs(int[] nums, int low, int high) {

        return (int) (solve(nums, low - 1) - solve(nums, high));

    }

    static class TrieTree {

        TrieTree[] next = new TrieTree[2];

        int count = 1;

    }

    long solve(int[] nums, int m) {

        TrieTree trieTree = buildTrieTree(nums);

        long result = 0;

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

            result += queryTrieTree(trieTree, nums[i], m, 31);

        }

        return result / 2;

    }

    long queryTrieTree(TrieTree trieTree, int a, int m, int index) {

        if (trieTree == null)

            return 0;

        TrieTree current = trieTree;

        for (int i = index; i >= 0; i--) {

            int aDigit = (a >> i) & 1;

            int mDigit = (m >> i) & 1;

            if (aDigit == 1 && mDigit == 1) {

                if (current.next[0] == null)

                    return 0;

                current = current.next[0];

            } else if (aDigit == 0 && mDigit == 1) {

                if (current.next[1] == null)

                    return 0;

                current = current.next[1];

            } else if (aDigit == 1 && mDigit == 0) {

                long p = queryTrieTree(current.next[1], a, m, i - 1);

                long q = current.next[0] == null ? 0 : current.next[0].count;

                return p + q;

            } else if (aDigit == 0 && mDigit == 0) {

                long p = queryTrieTree(current.next[0], a, m, i - 1);

                long q = current.next[1] == null ? 0 : current.next[1].count;

                return p + q;

            }

        }

        return 0;

    }

    TrieTree buildTrieTree(int[] a) {

        TrieTree trieTree = new TrieTree();

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

            TrieTree current = trieTree;

            for (int j = 31; j >= 0; j--) {

                int digit = (a[i] >> j) & 1;

                if (current.next[digit] == null) {

                    current.next[digit] = new TrieTree();

                } else {

                    current.next[digit].count++;

                }

                current = current.next[digit];

            }

        }

        return trieTree;

    }

}

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