Facebook面试题 Find first k common elements in n sorted arrays

淩亂°似流年 2022-07-13 07:11 220阅读 0赞

Given n sorted arrays, find first k common elements in them.
E.g. the common elements of { {1,3,5,7}, {3,4,5,6}, {3,5,6,8,9}, {2,3,4,5,11,18}} are 3 and 5.

  • Analysis:
    In order to solve this question, we need to consider 2 aspects, which is common elements and sorted arrays. In this sense, a common elements
    of n sorted arrays need to appear exactly n times in the input. And sorted means we can perform special operation like binary search on the
    arrays.Thus there are roughly 2 ideas for it, showed as following:

    1. Choose a pivot array, for each element of it, perform binary search in all other arrays. And keep a counter for each pivot element. A counter
      of n indicates this element is a common element. Suppose the average length of each array is n as well. For each element in the pivot array, we perform (n - 1) binary
      searches in the remaining arrays. Each binary search takes O(logn) time. In total, the time complexity is O(n * (n - 1) * logn) = O(n^2logn).
    2. However, we did some duplicate works in the above algorithm. That is, in the binary search step, we compare the elements in the pivot array
      again and again with all the elements from 0 to n - 1. In order to optimize, we could keep indexes of the farmost position we have traversed
      for each array. Because all the arrays are sorted or monotonically non-decreasing, so positions we have already checked is useless for us. Thus the algorithm
      could be described as following:
    3. Choose a pivot array, in which each element is going to be used for comparing.
    4. Keep an array of length n - 1, in which stores the pointer indexes of each remaining arrays.
    5. For an element of pivot array, compare it with elements from each remaining arrays from the corresponding pointer index.
  1. * if pivot element is greater than current number, increase the index.
  2. * if pivot element is equal to current number, increase the counter.
  3. * if pivot element is less than current number, no match is found. break.
  4. 6. if the counter reaches n, a common element is found.
  5. This algorithm takes `O(n * n)` time and `O(n)` space. Since we have to traverse each number in the 2d array and need to keep a pointer for
  6. each row in it. However, the `O(n)` space can be saved by using the pivot array to store the pointer indexes.
  7. \_\_For the seek of simplicity, we use linear comparision in the second algorithm. However, use binary search in each comparison step from pointer index to the end of the array
  8. could further increase efficiency. We can further slightly improve the efficiency by choose the array with the greatest first number as the pivot
  9. array.\_\_

A Java implementation of the second algorithm is showed as following:

  1. public class Solution {
  2. public int[] firstKCommonElements(int[][] arrays, int k) {
  3. if (arrays == null || arrays.length == 0 || arrays[0] == null || arrays[0].length == 0) {
  4. return new int[]{};
  5. }
  6. int n = arrays.length;
  7. int[] pointers = new int[n];
  8. int[] ret = new int[k];
  9. int index = 0;
  10. for (int i = 0; i < arrays[0].length; i++) {
  11. int pivot = arrays[0][i];
  12. int counter = 1;
  13. for (int j = 1; j < n; j++) {
  14. while (pointers[j] < arrays[j].length && pivot > arrays[j][pointers[j]]) {
  15. pointers[j]++;
  16. }
  17. if (pointers[j] == arrays[j].length || pivot != arrays[j][pointers[j]]) {
  18. break;
  19. }
  20. counter++;
  21. }
  22. if (counter == n) {
  23. ret[index++] = pivot;
  24. }
  25. if (index == k) {
  26. return ret;
  27. }
  28. }
  29. return ret;
  30. }
  31. }

发表评论

表情:
评论列表 (有 0 条评论,220人围观)

还没有评论,来说两句吧...

相关阅读