• 数据结构之区间,数组,矩阵 总结


    大纲

    . Merge Two / K Sorted Arrays / Intervals 
    . Median of Unsorted / Two Sorted / K Sorted Arrays

    6. 合并排序数组 II

    中文English

    合并两个有序升序的整数数组A和B变成一个新的数组。新数组也要有序。

    Example

    样例 1:

    输入: A=[1], B=[1]
    输出:[1,1]	
    样例解释: 返回合并后的数组。
    

    样例 2:

    输入: A=[1,2,3,4], B=[2,4,5,6]
    输出: [1,2,2,3,4,4,5,6]	
    样例解释: 返回合并后的数组。
    

    Challenge

    你能否优化你的算法,如果其中一个数组很大而另一个数组很小?

    使用两个指针分别对数组从小到大遍历,每次取二者中较小的放在新数组中。
    直到某个指针先到结尾,另一个数组中剩余的数字直接放在新数组后面。

    时间复杂度O(n)

    class Solution:
        """
        @param A: sorted integer array A
        @param B: sorted integer array B
        @return: A new sorted integer array
        """
        def mergeSortedArray(self, A, B):
            i, j = 0, 0
            C = []
            while i < len(A) and j < len(B):
                if A[i] < B[j]:
                    C.append(A[i])
                    i += 1
                else:
                    C.append(B[j])
                    j += 1
            while i < len(A):
                C.append(A[i])
                i += 1
            while j < len(B):
                C.append(B[j])
                j += 1
                
            return C
    

      

    64. 合并排序数组

    中文English

    合并两个排序的整数数组A和B变成一个新的数组。

    Example

    样例 1:

    输入:[1, 2, 3]  3  [4,5]  2
    输出:[1,2,3,4,5]
    解释:
    经过合并新的数组为[1,2,3,4,5]
    

    样例 2:

    输入:[1,2,5] 3 [3,4] 2
    输出:[1,2,3,4,5]
    解释:
    经过合并新的数组为[1,2,3,4,5]
    

    Notice

    你可以假设A具有足够的空间(A数组的大小大于或等于m+n)去添加B中的元素。

    分析:涉及两个有序数组合并,设置i和j双指针,分别从两个数组的尾部想头部移动,并判断A[i]和B[j]的大小关系,从而保证最终数组有序,同时每次index从尾部向头部移动。---双指针

    class Solution:
        """
        @param: A: sorted integer array A which has m elements, but size of A is m+n
        @param: m: An integer
        @param: B: sorted integer array B which has n elements
        @param: n: An integer
        @return: nothing
        """
        def mergeSortedArray(self, A, m, B, n):
            # write your code here
            pos = m + n - 1 
            i = m - 1  
            j = n - 1
            while  i >= 0 and j >= 0 :
                if A[i]>B[j] :
                    A[pos]=A[i]
                    pos-=1
                    i-=1
                else :
                    A[pos]=B[j]
                    pos-=1
                    j-=1
                    
            while i >= 0 :
                A[pos] = A[i]
                pos-=1
                i-=1
            while j >= 0:
                A[pos] = B[j]
                pos-=1
                j-=1
    

      

    839. 合并两个排序的间隔列表

    中文English

    合并两个已排序的区间列表,并将其作为一个新的有序区间列表返回。新的区间列表应该通过拼接两个列表的区间并按升序排序。

    Example

    样例1

    输入: [(1,2),(3,4)] and list2 = [(2,3),(5,6)]
    输出: [(1,4),(5,6)]
    解释:
    (1,2),(2,3),(3,4) --> (1,4)
    (5,6) --> (5,6)
    

    样例2

    输入: [(1,2),(3,4)] 和 list2 = [(4,5),(6,7)]
    输出: [(1,2),(3,5),(6,7)]
    解释:
    (1,2) --> (1,2)
    (3,4),(4,5) --> (3,5)
    (6,7) --> (6,7)
    

    Notice

    同一个列表中的区间一定不会重叠。
    不同列表中的区间可能会重叠。

    用一个 last 来记录最后一个还没有被放到 merge results 里的 Interval,用于和新加入的 interval 比较看看能不能合并到一起。
    """
    Definition of Interval.
    class Interval(object):
        def __init__(self, start, end):
            self.start = start
            self.end = end
    """
    
    class Solution:
        """
        @param list1: one of the given list
        @param list2: another list
        @return: the new sorted list of interval
        """
        def mergeTwoInterval(self, list1, list2):
            i, j = 0, 0
            intervals = []
            while i < len(list1) and j < len(list2):
                if list1[i].start < list2[j].start:
                    self.push_back(intervals, list1[i])
                    i += 1
                else:
                    self.push_back(intervals, list2[j])
                    j += 1
            while i < len(list1):
                self.push_back(intervals, list1[i])
                i += 1
            while j < len(list2):
                self.push_back(intervals, list2[j])
                j += 1
            
            return intervals
            
        def push_back(self, intervals, interval):
            if not intervals:
                intervals.append(interval)
                return
            
            last_interval = intervals[-1]
            if last_interval.end < interval.start:
                intervals.append(interval)
                return
            
            intervals[-1].end = max(intervals[-1].end, interval.end)
    

      

    486. 合并k个排序数组

    中文English

    将 k 个有序数组合并为一个大的有序数组。

    Example

    样例 1:

    输入:
      [
        [1, 3, 5, 7],
        [2, 4, 6],
        [0, 8, 9, 10, 11]
      ]
    输出: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
    

    样例 2:

    输入: 
      [
        [1,2,3],
        [1,2]
      ]
    输出: [1,1,2,2,3]
    

    Challenge

    在 O(N log k) 的时间复杂度内完成:

    • N 是所有数组包含的整数总数量。
    • k 是数组的个数。

    可以用堆做到 O(N log k) 的时间复杂度.

    初始将所有数组的首个元素入堆, 并记录入堆的元素是属于哪个数组的.

    每次取出堆顶元素, 并放入该元素所在数组的下一个元素.

    import heapq
    
    
    class Solution:
        """
        @param arrays: k sorted integer arrays
        @return: a sorted array
        """
        def mergekSortedArrays(self, arrays):
            result = []
            heap = []
            for index, array in enumerate(arrays):
                if len(array) == 0:
                    continue
                heapq.heappush(heap, (array[0], index, 0))
                 
            while len(heap):
                val, x, y = heap[0]
                heapq.heappop(heap)
                result.append(val)
                if y + 1 < len(arrays[x]):
                    heapq.heappush(heap, (arrays[x][y + 1], x, y + 1))
                
            return result
    

      

    自顶向下的分治法

     
    class Solution:
        """
        @param arrays: k sorted integer arrays
        @return: a sorted array
        """
        def mergekSortedArrays(self, arrays):
            return self.merge_range_arrays(arrays, 0, len(arrays) - 1)
            
        def merge_range_arrays(self, arrays, start, end):
            if start == end:
                return arrays[start]
            
            mid = (start + end) // 2
            left = self.merge_range_arrays(arrays, start, mid)
            right = self.merge_range_arrays(arrays, mid + 1, end)
            return self.merge_two_arrays(left, right)
            
        def merge_two_arrays(self, arr1, arr2):
            i, j = 0, 0
            array = []
            while i < len(arr1) and j < len(arr2):
                if arr1[i] < arr2[j]:
                    array.append(arr1[i])
                    i += 1
                else:
                    array.append(arr2[j])
                    j += 1
            while i < len(arr1):
                array.append(arr1[i])
                i += 1
            while j < len(arr2):
                array.append(arr2[j])
                j += 1
            return array
    

      

    547. 两数组的交集

    中文English

    给出两个数组,写出一个方法求出它们的交集

    Example

    例1:

    输入: nums1 = [1, 2, 2, 1], nums2 = [2, 2], 
    输出: [2].
    

    例2:

    输入: nums1 = [1, 2], nums2 = [2], 
    输出: [2].
    

    Challenge

    可以用三种不同的方法实现吗?

    Notice

    • 结果中的每个元素必须是唯一的。
    • 结果需要为升序。

    三种解法-----------倒排索引!!!

    // version 1: sort & merge
    public class Solution {
        /**
         * @param nums1 an integer array
         * @param nums2 an integer array
         * @return an integer array
         */
        public int[] intersection(int[] nums1, int[] nums2) {
            Arrays.sort(nums1);
            Arrays.sort(nums2);
            
            int i = 0, j = 0;
            int[] temp = new int[nums1.length];
            int index = 0;
            while (i < nums1.length && j < nums2.length) {
                if (nums1[i] == nums2[j]) {
                    if (index == 0 || temp[index - 1] != nums1[i]) {
                        temp[index++] = nums1[i];
                    }
                    i++;
                    j++;
                } else if (nums1[i] < nums2[j]) {
                    i++;
                } else {
                    j++;
                }
            }
            
            int[] result = new int[index];
            for (int k = 0; k < index; k++) {
                result[k] = temp[k];
            }
            
            return result;
        }
    }
    
    // version 2: hash map
    public class Solution {
        /**
         * @param nums1 an integer array
         * @param nums2 an integer array
         * @return an integer array
         */
        public int[] intersection(int[] nums1, int[] nums2) {
            if (nums1 == null || nums2 == null) {
                return null;
            }
            
            HashSet<Integer> hash = new HashSet<>();
            for (int i = 0; i < nums1.length; i++) {
                hash.add(nums1[i]);
            }
            
            HashSet<Integer> resultHash = new HashSet<>();
            for (int i = 0; i < nums2.length; i++) {
                if (hash.contains(nums2[i]) && !resultHash.contains(nums2[i])) {
                    resultHash.add(nums2[i]);
                }
            }
            
            int size = resultHash.size();
            int[] result = new int[size];
            int index = 0;
            for (Integer num : resultHash) {
                result[index++] = num;
            }
            
            return result;
        }
    }
    
    // version 3: sort & binary search
    public class Solution {
        /**
         * @param nums1 an integer array
         * @param nums2 an integer array
         * @return an integer array
         */
        public int[] intersection(int[] nums1, int[] nums2) {
            if (nums1 == null || nums2 == null) {
                return null;
            }
            
            HashSet<Integer> set = new HashSet<>();
            
            Arrays.sort(nums1);
            for (int i = 0; i < nums2.length; i++) {
                if (set.contains(nums2[i])) {
                    continue;
                }
                if (binarySearch(nums1, nums2[i])) {
                    set.add(nums2[i]);
                }
            }
            
            int[] result = new int[set.size()];
            int index = 0;
            for (Integer num : set) {
                result[index++] = num;
            }
            
            return result;
        }
        
        private boolean binarySearch(int[] nums, int target) {
            if (nums == null || nums.length == 0) {
                return false;
            }
            
            int start = 0, end = nums.length - 1;
            while (start + 1 < end) {
                int mid = (end - start) / 2 + start;
                if (nums[mid] == target) {
                    return true;
                }
                if (nums[mid] < target) {
                    start = mid;
                } else {
                    end = mid;
                }
            }
            
            if (nums[start] == target) {
                return true;
            }
            if (nums[end] == target) {
                return true;
            }
            
            return false;
        }
    }
    

      

     

    793. 多个数组的交集

    中文English

    给出多个数组,求它们的交集。输出他们交集的大小。

    Example

    样例 1:

    	输入:  [[1,2,3],[3,4,5],[3,9,10]]
    	输出:  1
    	
    	解释:
    	只有3出现在三个数组中。
    

    样例 2:

    	输入: [[1,2,3,4],[1,2,5,6,7][9,10,1,5,2,3]]
    	输出:  2
    	
    	解释:
    	交集是[1,2].
    

    基于 Priority Queue 的版本。
    假设每个数组长度为 n, 一共 k 个数组。
    时间复杂度为 O(knlogn + nklogk)
    其中 knlogn 是 k 个数组进行分别排序的时间复杂度
    nklogk 是 总共 nk 个数从 PriorityQueue 中进出,每次进出 logk。

    相比使用 HashMap 的算法的时间复杂度 O(nk) 这个方法并没有什么时间上的优势。
    但是这个方法的空间复杂度很低,只有 O(k),即多少个数组就花费多少的额外空间。

    在面试中也是很有可能会被要求不用 HashMap 或者实现一个比 O(n) 更低的空间复杂度的算法。因此这个程序的方法也是需要掌握的。

    public class Solution {
        class Pair {
            public int row, col;
            
            public Pair(int row, int col) {
                this.row = row;
                this.col = col;
            }
        }
        
        /**
         * @param arrs: the arrays
         * @return: the number of the intersection of the arrays
         */
        public int intersectionOfArrays(int[][] arrs) {
            Comparator<Pair> comparator = new Comparator<Pair>() {
              public int compare(Pair x, Pair y) {
                return arrs[x.row][x.col] - arrs[y.row][y.col];
              }
            };
            
            Queue<Pair> queue = new PriorityQueue<>(arrs.length, comparator);
            
            for (int i = 0; i < arrs.length; i++) {
                if (arrs[i].length == 0) {
                    return 0;
                }
                
                Arrays.sort(arrs[i]);
                queue.offer(new Pair(i, 0));
            }
            
            int lastValue = 0, count = 0;
            int intersection = 0;
            while (!queue.isEmpty()) {
                Pair pair = queue.poll();
                if (arrs[pair.row][pair.col] != lastValue || count == 0) {
                    if (count == arrs.length) {
                      intersection++;
                    }
                    lastValue = arrs[pair.row][pair.col];
                    count = 1;
                } else {
                    count++;
                }
                
                pair.col++;
                if (pair.col < arrs[pair.row].length) {
                  queue.offer(pair);
                }
            }
            
            // kickoff the last number
            if (count == arrs.length) {
                intersection++;
            }
            
            return intersection;
        }
    }
    

      

  • 相关阅读:
    LoadRunne遇到的一些问题FAQ(持续更新...)
    LoadRunner11下载、安装与破解
    LoadRunner之录制你的第一个脚本
    appium+Linux环境安装配置
    appium-FAQ(持续更新...)
    appium启动运行log分析
    利用Unity3D与Oculus实现机器情绪安抚师的一种方案
    利用Unity3D实现多平台增强现实网络游戏的一种方案
    Ubuntu16.04安装NVIDIA驱动时的一些坑与解决方案
    你的计算机也可以看懂世界——十分钟跑起卷积神经网络(Windows+CPU)
  • 原文地址:https://www.cnblogs.com/bonelee/p/11926181.html
Copyright © 2020-2023  润新知