zoukankan      html  css  js  c++  java
  • 373. Find K Pairs with Smallest Sums

    You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k.

    Define a pair (u,v) which consists of one element from the first array and one element from the second array.

    Find the k pairs (u1,v1),(u2,v2) ...(uk,vk) with the smallest sums.

    Example 1:

    Input: nums1 = [1,7,11], nums2 = [2,4,6], k = 3
    Output: [[1,2],[1,4],[1,6]] 
    Explanation: The first 3 pairs are returned from the sequence: 
                 [1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]

    Example 2:

    Input: nums1 = [1,1,2], nums2 = [1,2,3], k = 2
    Output: [1,1],[1,1]
    Explanation: The first 2 pairs are returned from the sequence: 
                 [1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3]

    Example 3:

    Input: nums1 = [1,2], nums2 = [3], k = 3
    Output: [1,3],[2,3]
    Explanation: All possible pairs are returned from the sequence: [1,3],[2,3]

    改进:参考 https://leetcode.com/problems/find-k-pairs-with-smallest-sums/discuss/84551/simple-Java-O(KlogK)-solution-with-explanation

    因为两个数组都是有序的,往min heap中添加元素的理想顺序应该是:首先只考虑两个数组的前k个元素,对应nums1中的某个元素,下一个理想顺序的组合应该是 nums1中的这个元素 + 从堆中poll出来的对应的nums2元素的下一个元素。堆中存index比较方便,先把(i, 0)放入堆中,i对应nums1的index,0是nums2的index;poll出来一个最小值之后,保存结果,检查index是否越界,然后把下一个candidate放入堆中

    basic idea: use minHeap to keep track on next minimum pair sum, and we only need to maintain K possible candidates in the data structure.

    for every numbers in nums1, its best candidate(yields min sum) always starts from nums2[0] since arrays are all sorted; and for a specific number in nums1, its next candidate sould be [this specific number] + nums2[current_associated_index + 1], unless out of boundary

    时间:O(KlogK),空间:O(K)

    class Solution {
        public List<int[]> kSmallestPairs(int[] nums1, int[] nums2, int k) {
            List<int[]> res = new ArrayList<>();
            if(nums1.length == 0 || nums2.length == 0 || k == 0) return res;
            PriorityQueue<int[]> minHeap = new PriorityQueue<>((a, b) -> (nums1[a[0]] + nums2[a[1]]) - (nums1[b[0]] + nums2[b[1]])); 
            // for(int i = 0; i < nums1.length && i < k; i++) {
            //     minHeap.offer(new int[] {i, 0});
            // }
            // while(k-- > 0 && !minHeap.isEmpty()) {
            //     int[] tmp = minHeap.poll();
            //     res.add(new int[] {nums1[tmp[0]], nums2[tmp[1]]});
            //     if(tmp[1] == nums2.length - 1)
            //         continue;
            //     minHeap.offer(new int[] {tmp[0], tmp[1] + 1});
            // }
            // return res;
            for(int i = 0; i < nums2.length && i < k; i++) {
                minHeap.offer(new int[] {0, i});
            }
            while(k-- > 0 && !minHeap.isEmpty()) {
                int[] tmp = minHeap.poll();
                res.add(new int[] {nums1[tmp[0]], nums2[tmp[1]]});
                if(tmp[0] == nums1.length - 1)
                    continue;
                minHeap.offer(new int[] {tmp[0]+ 1, tmp[1]});
            }
            return res;
        }
    }

    之前的方法用了min heap,但类似于brute force,能过但是太慢了,O(K^2 logK)

    class Solution {
        public List<int[]> kSmallestPairs(int[] nums1, int[] nums2, int k) {
            List<int[]> res = new ArrayList<>();
            if(nums1 == null || nums2 == null) return res;
            PriorityQueue<int[]> minHeap = new PriorityQueue<>((a, b) -> (b[0] + b[1]) - (a[0] + a[1]));
            int m = Math.min(nums1.length, k), n = Math.min(nums2.length, k);
            for(int i = 0; i < m; i++) {
                for(int j = 0; j < n; j++) {
                    minHeap.offer(new int[] {nums1[i], nums2[j]});
                    if(minHeap.size() > k)
                        minHeap.poll();
                }
            }
            while(!minHeap.isEmpty()) {
                res.add(0, minHeap.poll());
            }
            return res;
        }
    }

    or

    class Solution {
        public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
            List<List<Integer>> res = new ArrayList<>();
            if(nums1.length == 0 || nums2.length == 0 || k == 0) {
                return res;
            }
            PriorityQueue<int[]> minHeap = new PriorityQueue<>((a, b) -> (nums1[a[0]] + nums2[a[1]]) - (nums1[b[0]] + nums2[b[1]]));
            boolean[][] visited = new boolean[nums1.length][nums2.length];
            minHeap.offer(new int[] {0, 0});
            visited[0][0] = true;
            
            for(int i = 0; i < k && !minHeap.isEmpty(); i++) {
                int[] cur = minHeap.poll();
                int r = cur[0], c = cur[1];
                
                List<Integer> tmp = new ArrayList<>();
                tmp.add(nums1[r]);
                tmp.add(nums2[c]);
                res.add(tmp);
                
                if(r + 1 < nums1.length && !visited[r + 1][c]) {
                    minHeap.offer(new int[] {r + 1, c});
                    visited[r + 1][c] = true;
                }
                if(c + 1 < nums2.length && !visited[r][c + 1]) {
                    minHeap.offer(new int[] {r, c + 1});
                    visited[r][c + 1] = true;
                }
            }
            
            return res;
        }
    }
  • 相关阅读:
    Python学习【第五篇】:面向对象及相关
    Python之路【第四篇】:模块
    Python之路【第三篇】:python基础(二)
    Python之路【第二篇】:Python基础(一)
    Python之路【第一篇】:Python简介和入门
    Open-source Tutorial
    Algorithms
    Mathematics Base
    Mathematics Base
    Open-source Tutorial
  • 原文地址:https://www.cnblogs.com/fatttcat/p/9992881.html
Copyright © 2011-2022 走看看