欢迎大家加QQ群:623375442,可以方便群里面交流。现在LeetCode的周赛真的越来越恶心的,第三题纯纯数学。希望LeetCode没有办法解决AI的问题的话,索性停办周赛算了。

100576. Maximum Sum With at Most K Elements

给你一个大小为 n x m 的二维矩阵 grid ,以及一个长度为 n 的整数数组 limits ,和一个整数 k 。你的目标是从矩阵 grid 中提取出 至多 k 个元素,并计算这些元素的最大总和,提取时需满足以下限制:

  • 从 grid 的第 i 行提取的元素数量不超过 limits[i] 。

返回最大总和。

测试样例:

输入:grid = [[1,2],[3,4]], limits = [1,2], k = 2

输出:7

解释:

  • 从第 2 行提取至多 2 个元素,取出 4 和 3 。
  • 至多提取 2 个元素时的最大总和 4 + 3 = 7 。

解答:遍历过程中,利用优先队列减少数据。

class Solution {
    public long maxSum(int[][] grid, int[] limits, int k) {
        PriorityQueue<Integer> queue = new PriorityQueue<>();
        for (int i = 0; i < grid.length; ++i) {
            PriorityQueue<Integer> tmp = new PriorityQueue<>();
            for (int n : grid[i]) {
                tmp.add(n);
                if (tmp.size() > limits[i]) {
                    tmp.poll();
                }
            }
            for (int n : tmp) {
                queue.add(n);
                if (queue.size() > k) {
                    queue.poll();
                }
            }
        }
        long res = 0;
        for (int n : queue) {
            res += n;
        }
        return res;
    }
}

100585. Check If Digits Are Equal in String After Operations II

给你一个由数字组成的字符串 s 。重复执行以下操作,直到字符串恰好包含 两个 数字:

  • 从第一个数字开始,对于 s 中的每一对连续数字,计算这两个数字的和 模 10。
  • 用计算得到的新数字依次替换 s 的每一个字符,并保持原本的顺序。

如果 s 最后剩下的两个数字相同,则返回 true 。否则,返回 false。

测试样例:

输入:s = "3902"

输出:true

解答:能知道是杨辉三角,但是这个模10还要扩展欧几里得算法真的不会。。。

class Solution {
    public boolean hasSameDigits(String s) {
        int n = s.length();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = s.charAt(i) - '0';
        }
        long[][] frac = new long[n + 1][3];
        frac[0][0] = 1;
        for (int i = 1; i <= n; i++) {
            int t = i, c2 = 0, c5 = 0;
            while (t % 2 == 0) {
                c2++;
                t /= 2;
            }
            while (t % 5 == 0) {
                c5++;
                t /= 5;
            }
            frac[i][0] = frac[i - 1][0] * t % 10;
            frac[i][1] = frac[i - 1][1] + c2;
            frac[i][2] = frac[i - 1][2] + c5;
        }
        long[] c = new long[n - 1];
        long s1 = 0, s2 = 0;
        int[] re = {0, 1, 0, 7, 0, 0, 0, 3, 0, 9};
        for (int i = 0; i < n - 1; i++) {
            long c2 = frac[n - 2][1] - frac[i][1] - frac[n - i - 2][1];
            long c5 = frac[n - 2][2] - frac[i][2] - frac[n - i - 2][2];
            if (c2 > 0 && c5 > 0) continue;
            c[i] = frac[n - 2][0] * re[(int) frac[i][0]] * re[(int) frac[n - i - 2][0]] * quickMulti(2, c2, 10) * quickMulti(5, c5, 10) % 10;
            s1 += arr[i] * c[i];
            s1 = s1 % 10;
            s2 += arr[i + 1] * c[i];
            s2 = s2 % 10;
        }
        return s1 == s2;
    }

    private long quickMulti(long a, long q, int mod) {
        long res = 1;
        long p = 1;
        long v = a;
        while (p <= q) {
            if ((q & p) != 0) {
                res *= v;
                res %= mod;
            }
            p = (p << 1);
            v = v * v % mod;
        }
        return res;
    }
}

100592. Maximize the Distance Between Points on a Square

给你一个整数 side,表示一个正方形的边长,正方形的四个角分别位于笛卡尔平面的 (0, 0) ,(0, side) ,(side, 0) 和 (side, side) 处。

同时给你一个 正整数 k 和一个二维整数数组 points,其中 points[i] = [xi, yi] 表示一个点在正方形边界上的坐标。

你需要从 points 中选择 k 个元素,使得任意两个点之间的 最小 曼哈顿距离 最大化 。

返回选定的 k 个点之间的 最小 曼哈顿距离的 最大 可能值。

两个点 (xi, yi) 和 (xj, yj) 之间的曼哈顿距离为 |xi - xj| + |yi - yj|。

测试样例:

输入:side = 2, points = [[0,2],[2,0],[2,2],[0,0]], k = 4

输出:2

class Solution {
    public int maxDistance(int side, int[][] points, int k) {
        ArrayList<int[]> arr1 = new ArrayList<>();
        ArrayList<int[]> arr2 = new ArrayList<>();
        ArrayList<int[]> arr3 = new ArrayList<>();
        ArrayList<int[]> arr4 = new ArrayList<>();
        int n = points.length;
        for (int[] p : points) {
            if (p[0] == 0) {
                arr1.add(p);
            } else if (p[1] == side) {
                arr2.add(p);
            } else if (p[0] == side) {
                arr3.add(p);
            } else {
                arr4.add(p);
            }
        }
        arr1.sort((o1, o2) -> Integer.compare(o1[1], o2[1]));
        arr2.sort((o1, o2) -> Integer.compare(o1[0], o2[0]));
        arr3.sort((o1, o2) -> Integer.compare(o2[1], o1[1]));
        arr4.sort((o1, o2) -> Integer.compare(o2[0], o1[0]));
        long s = side;
        ArrayList<Long> arr = new ArrayList<>(n);
        for (int[] v : arr1) arr.add((long) v[1]);
        for (int[] v : arr2) arr.add(v[0] + s);
        for (int[] v : arr3) arr.add(s - v[1] + 2 * s);
        for (int[] v : arr4) arr.add(s - v[0] + 3 * s);
        TreeSet<Long> ts = new TreeSet<>();
        for (long v : arr) {
            ts.add(v);
            ts.add(v + s * 4);
        }
        int l = 0, r = side;
        while (l < r) {
            int m = l + (r - l + 1) / 2;
            boolean flag = false;
            for (Long v : arr) {
                boolean t = true;
                long p = v;
                for (int i = 0; i < k - 1; i++) {
                    Long p1 = ts.ceiling(p + m);
                    if (p1 == null || p1 >= v + s * 4) {
                        t = false;
                        break;
                    } else {
                        p = p1;
                    }
                }
                if (p + m > v + s * 4) t = false;
                if (t) {
                    flag = t;
                    break;
                }
            }
            if (flag) {
                l = m;
            } else {
                r = m - 1;
            }
        }
        return l;
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *