【教3妹学编程-算法题】最大和查询
  96AOqGW9dKgh 2023年12月08日 15 0


【教3妹学编程-算法题】最大和查询_升序

3妹:2哥,你有没有看到新闻“18岁父亲为4岁儿子落户现身亲子鉴定”
2哥 : 啥?18岁就当爹啦?
3妹:确切的说是14岁好吧。
2哥 : 哎,想我30了, 还是个单身狗。
3妹:别急啊, 2嫂肯定在某个地方等着你去娶她呢。又不是结婚越早越好。
2哥:是啊, 这孩子14岁当爹,也太早了。
3妹:2哥,你找女朋友有什么条件没有哇?
2哥 : emmm, 以前希望找一个温柔漂亮的, 现在嘛, 女的、活的。毕竟年龄已经很大了, 已经30了…
3妹:才30而已嘛, 女生很多都喜欢找个比自己大一点的~
2哥 : 哎,你们女生最大能接受比自己大多少岁啊?
3妹:emmm, 这么不好说,要看具体女生,一般大个3-5岁都可以吧。 2哥说到最大, 我今天看到一个最大和查询的题目,让我也来考考你吧~

【教3妹学编程-算法题】最大和查询_数组_02

题目:

给你两个长度为 n 、下标从 0 开始的整数数组 nums1 和 nums2 ,另给你一个下标从 1 开始的二维数组 queries ,其中 queries[i] = [xi, yi] 。

对于第 i 个查询,在所有满足 nums1[j] >= xi 且 nums2[j] >= yi 的下标 j (0 <= j < n) 中,找出 nums1[j] + nums2[j] 的 最大值 ,如果不存在满足条件的 j 则返回 -1 。

返回数组 answer ,其中 answer[i] 是第 i 个查询的答案。

示例 1:

输入:nums1 = [4,3,1,2], nums2 = [2,4,9,5], queries = [[4,1],[1,3],[2,5]]
输出:[6,10,7]
解释:
对于第 1 个查询:xi = 4 且 yi = 1 ,可以选择下标 j = 0 ,此时 nums1[j] >= 4 且 nums2[j] >= 1 。nums1[j] + nums2[j] 等于 6 ,可以证明 6 是可以获得的最大值。
对于第 2 个查询:xi = 1 且 yi = 3 ,可以选择下标 j = 2 ,此时 nums1[j] >= 1 且 nums2[j] >= 3 。nums1[j] + nums2[j] 等于 10 ,可以证明 10 是可以获得的最大值。
对于第 3 个查询:xi = 2 且 yi = 5 ,可以选择下标 j = 3 ,此时 nums1[j] >= 2 且 nums2[j] >= 5 。nums1[j] + nums2[j] 等于 7 ,可以证明 7 是可以获得的最大值。
因此,我们返回 [6,10,7] 。
示例 2:

输入:nums1 = [3,2,5], nums2 = [2,3,4], queries = [[4,4],[3,2],[1,1]]
输出:[9,9,9]
解释:对于这个示例,我们可以选择下标 j = 2 ,该下标可以满足每个查询的限制。
示例 3:

输入:nums1 = [2,1], nums2 = [2,3], queries = [[3,3]]
输出:[-1]
解释:示例中的查询 xi = 3 且 yi = 3 。对于每个下标 j ,都只满足 nums1[j] < xi 或者 nums2[j] < yi 。因此,不存在答案。

提示:

nums1.length == nums2.length
n == nums1.length
1 <= n <= 10^5
1 <= nums1[i], nums2[i] <= 10^9
1 <= queries.length <= 10^5
queries[i].length == 2
xi == queries[i][1]
yi == queries[i][2]
1 <= xi, yi <= 10^9

思路:

【教3妹学编程-算法题】最大和查询_Math_03

先按nums1升序,然后一个个检查nums2,如果后面出现nums2比前面大,那说明前面那个数没有用了(两者都比你大,那么和也比你更大) 剔除掉无用数后,我们可以发现第一维是升序,第二维是降序。 对于每一个询问queries,我们可以用二分法找到第一个比x大的下标left(left之后的都比它大) 同理,可以找到比y大的下标right(right之前的都比它大) 接下来我们需要返回的答案就是left和right之间所有下标里和最大的值(线段树维护区间最大值)

java代码:

class Solution {
    public int[] maximumSumQueries(int[] nums1, int[] nums2, int[][] queries) {
        int n = nums1.length;
        int m = queries.length;
        Point[] ps = new Point[m + n];
        for (int i = 0; i < n; i++) {
            ps[i] = new Point(nums1[i], nums2[i], i, 0);
        }
        for (int i = 0; i < m; i++) {
            ps[i + n] = new Point(queries[i][0], queries[i][1], i, 1);
        }
        // p.q=0/1是为了让p.x相同时,nums的数排在前面,从而先update再query
        Arrays.sort(ps, (p1, p2) -> p1.x == p2.x ? (p1.q - p2.q) : (p2.x - p1.x));
        int end = (int)1e9;
        Node root = new Node(0, end, -1);
        int[] ans = new int[m];
        for (Point p : ps) {
            if (p.q == 0) {
                root.update(p.y, p.y, p.x + p.y);   // 单点更新
            } else {
                ans[p.idx] = root.query(p.y, end);  // 区间查询[p.y, end]
            }
        }

        return ans;
    }

    class Point {
        int x;
        int y;
        int idx;
        int q;

        public Point(int x, int y, int idx, int q) {
            this.x = x;
            this.y = y;
            this.idx = idx;
            this.q = q;
        }
    }

    class Node {
        int left;
        int right;
        int val;
        Node leftNode;
        Node rightNode;

        public Node(int l, int r, int v) {
            left = l;
            right = r;
            val = v;
        }

        public Node getLeftNode() {
            if (leftNode == null) {
                leftNode = new Node(left, left + (right - left) / 2, val);
            }
            return leftNode;
        }

        public Node getRightNode() {
            if (rightNode == null) {
                rightNode = new Node(left + (right - left) / 2 + 1, right, val);
            }
            return rightNode;
        }

        public void update(int lo, int hi, int v) {
            if (left > hi || right < lo) {
                return;
            }
            if (left >= lo && right <= hi) {
                val = Math.max(val, v);
                return;
            }
            getLeftNode().update(lo, hi, v);
            getRightNode().update(lo, hi, v);
            val = Math.max(val, leftNode.val);
            val = Math.max(val, rightNode.val);
        }

        public int query(int lo, int hi) {
            if (left > hi || right < lo || val == -1) {
                return -1;
            }
            if (left >= lo && right <= hi) {
                return val;
            }
            return Math.max(getLeftNode().query(lo, hi), getRightNode().query(lo, hi));
        }

    }
}


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月08日 0

暂无评论

推荐阅读
96AOqGW9dKgh
最新推荐 更多

2024-05-17