【问题标题】:How to merge two sorted arrays into a sorted array? [closed]如何将两个排序数组合并为一个排序数组? [关闭]
【发布时间】:2011-08-22 22:11:10
【问题描述】:

这是在一次采访中问我的,这是我提供的解决方案:

public static int[] merge(int[] a, int[] b) {

    int[] answer = new int[a.length + b.length];
    int i = 0, j = 0, k = 0;
    while (i < a.length && j < b.length)
    {
        if (a[i] < b[j])
        {
            answer[k] = a[i];
            i++;
        }
        else
        {
            answer[k] = b[j];
            j++;
        }
        k++;
    }

    while (i < a.length)
    {
        answer[k] = a[i];
        i++;
        k++;
    }

    while (j < b.length)
    {
        answer[k] = b[j];
        j++;
        k++;
    }

    return answer;
}

有没有更有效的方法来做到这一点?

编辑:更正了长度方法。

【问题讨论】:

  • 对我来说似乎是一个很好的答案。这个问题充其量将具有 O(n) 复杂性,而您的答案实现了这一点。其他任何事情都是微优化。
  • 你做得很好!这本质上是归并排序的一部分:将两个排序的流(来自磁带或磁盘)合并到另一个排序的流中。
  • 你找到工作了吗?
  • 也可以使用三元运算符:while (i &lt; a.length &amp;&amp; j &lt; b.length) answer[k++] = a[i] &lt; b[j] ? a[i++] : b[j++]; Java 语言规范:Conditional Operator ? :
  • 你忘了评论!!!

标签: java algorithm big-o mergesort


【解决方案1】:
public static int[] merge(int[] a, int[] b) {

    int[] answer = new int[a.length + b.length];
    int i = 0, j = 0, k = 0;

    while (i < a.length && j < b.length)  
       answer[k++] = a[i] < b[j] ? a[i++] :  b[j++];

    while (i < a.length)  
        answer[k++] = a[i++];

    while (j < b.length)    
        answer[k++] = b[j++];

    return answer;
}

稍微紧凑一点,但完全一样!

【讨论】:

  • 对于说这导致索引越界异常的人,您使用什么输入?它适用于我的所有情况。
  • 使用 for 循环合并声明循环变量和循环控制的行。谨慎使用双空行 - 在对称的“尾部副本”之间看起来没有必要。
【解决方案2】:
var arr1 = [2,10,20,30,100];
var arr2 = [2,4,5,6,7,8,9];
var j = 0;
var i =0;
var newArray = [];

for(var x=0;x< (arr1.length + arr2.length);x++){
    if(arr1[i] >= arr2[j]){                //check if element arr2 is equal and less than arr1 element
        newArray.push(arr2[j]);
      j++;
    }else if(arr1[i] < arr2[j]){            //check if element arr1 index value  is less than arr2 element
        newArray.push(arr1[i]);
        i++;
    }
    else if(i == arr1.length || j < arr2.length){    // add remaining arr2 element
        newArray.push(arr2[j]);
        j++
    }else{                                                   // add remaining arr1 element
        newArray.push(arr1[i]); 
        i++
    }

}

console.log(newArray);

【讨论】:

    【解决方案3】:

    要在 O(m+n) 时间复杂度中对两个排序数组进行匹配,请使用以下方法,仅使用一个循环。 m 和 n 是第一个数组和第二个数组的长度。

    public class MargeSortedArray {
        public static void main(String[] args) {
            int[] array = new int[]{1,3,4,7};
            int[] array2 = new int[]{2,5,6,8,12,45};
            int[] newarry = margeToSortedArray(array, array2);
            //newarray is marged array
        }
    
        // marge two sorted array with o(a+n) time complexity
        public static int[] margeToSortedArray(int[] array, int[] array2) {
            int newarrlen = array.length+array2.length;
            int[] newarr = new int[newarrlen];
    
            int pos1=0,pos2=0;
            int len1=array.length, len2=array2.length;
    
            for(int i =0;i<newarrlen;i++) {     
                if(pos1>=len1) {
                    newarr[i]=array2[pos2];
                    pos2++;
                    continue;
                }
                if(pos2>=len2) {
                    newarr[i]=array[pos1];
                    pos1++;
                    continue;
                }
    
                if(array[pos1]>array2[pos2]) {
                    newarr[i]=array2[pos2];
                    pos2++;
                } else {
                    newarr[i]=array[pos1];
                    pos1++;
                }   
            }
    
            return newarr;
        }
    
    }
    

    【讨论】:

      【解决方案4】:

      GallopSearch 合并:O(log(n)*log(i)) 而不是 O(n)

      我继续在 cmets 中实施了灰胡子建议。主要是因为我需要此代码的高效关键任务版本。

      • 代码使用了一个 GallopSearch,它是 O(log(i)),其中 i 是 与相关索引存在的当前索引的距离。
      • 在驰骋搜索之后,代码使用 binarySearch 确定了正确的范围。由于疾驰将其限制为较小的 range 结果 binarySearch 也是 O(log(i))
      • 疾驰和合并是向后执行的。这似乎不是 关键任务,但它允许就地合并阵列。如果其中之一 你的数组有足够的空间来存储结果值,你可以 只需将其用作合并数组结果数组。在这种情况下,您必须在数组中指定有效范围。
      • 在这种情况下不需要内存分配(在关键操作中节省大量资金)。它只是确保它不会也不能覆盖任何未处理的值(只能向后完成)。事实上,您对输入和结果使用相同的数组。它不会受到任何不良影响。
      • 我一直使用 Integer.compare(),因此可以将其切换为其他用途。
      • 我可能会犯一些错误而没有利用我之前证明过的信息。例如二进制搜索到两个值的范围,其中一个值已经被检查过。可能还有一种更好的方式来说明主循环,如果将它们按顺序组合成两个操作,则不需要翻转 c 值。因为你知道你每次都会做一个然后另一个。有一些修饰的空间。

      这应该是最有效的方法,时间复杂度为 O(log(n)*log(i)) 而不是 O(n)。最坏情况的时间复杂度为 O(n)。如果你的数组是块状的并且有很长的值串在一起,这将使任何其他方法相形见绌,否则它会比它们更好。

      它在合并数组的末尾有两个读取值,在结果数组中写入值。在找出哪个最终值较小之后,它会对该数组进行驰骋搜索。 1, 2, 4, 8, 16, 32 等。当它找到另一个数组的读取值更大的范围时。它在该范围内进行二进制搜索(将范围减半,搜索正确的一半,重复直到单个值)。然后它将这些值复制到写入位置。请记住,副本必然会被移动,以使其无法覆盖任一读取数组中的相同值(这意味着写入数组和读取数组可以相同)。然后它对另一个数组执行相同的操作,该数组现在已知小于另一个数组的新读取值。

      static public int gallopSearch(int current, int[] array, int v) {
          int d = 1;
          int seek = current - d;
          int prevIteration = seek;
          while (seek > 0) {
              if (Integer.compare(array[seek], v) <= 0) {
                  break;
              }
              prevIteration = seek;
              d <<= 1;
              seek = current - d;
              if (seek < 0) {
                  seek = 0;
              }
          }
          if (prevIteration != seek) {
              seek = binarySearch(array, seek, prevIteration, v);
              seek = seek >= 0 ? seek : ~seek;
          }
          return seek;
      }
      
      static public int binarySearch(int[] list, int fromIndex, int toIndex, int v) {
          int low = fromIndex;
          int high = toIndex - 1;
          while (low <= high) {
              int mid = (low + high) >>> 1;
              int midVal = list[mid];
              int cmp = Integer.compare(midVal, v);
              if (cmp < 0) {
                  low = mid + 1;
              } else if (cmp > 0) {
                  high = mid - 1;
              } else {
                  return mid;// key found
              }
          }
          return -(low + 1);// key not found.
      }
      
      static public int[] sortedArrayMerge(int[] a, int[] b) {
          return sortedArrayMerge(null, a, a.length, b, b.length);
      }
      
      static public int[] sortedArrayMerge(int[] results, int[] a, int aRead, int b[], int bRead) {
          int write = aRead + bRead, length, gallopPos;
          if ((results == null) || (results.length < write)) {
              results = new int[write];
          }
          if (aRead > 0 && bRead > 0) {
              int c = Integer.compare(a[aRead - 1], b[bRead - 1]);
              while (aRead > 0 && bRead > 0) {
                  switch (c) {
                      default:
                          gallopPos = gallopSearch(aRead, a, b[bRead-1]);
                          length = (aRead - gallopPos);
                          write -= length;
                          aRead = gallopPos;
                          System.arraycopy(a, gallopPos--, results, write, length);
                          c = -1;
                          break;
                      case -1:
                          gallopPos = gallopSearch(bRead, b, a[aRead-1]);
                          length = (bRead - gallopPos);
                          write -= length;
                          bRead = gallopPos;
                          System.arraycopy(b, gallopPos--, results, write, length);
                          c = 1;
                          break;
                  }
              }
          }
          if (bRead > 0) {
              if (b != results) {
                  System.arraycopy(b, 0, results, 0, bRead);
              }
          } else if (aRead > 0) {
              if (a != results) {
                  System.arraycopy(a, 0, results, 0, aRead);
              }
          }
          return results;
      }
      

      这应该是最有效的方法。


      某些答案具有重复删除功能。这将需要一个 O(n) 算法,因为您必须实际比较每个项目。所以这是一个独立的,事后应用。如果您需要查看所有条目,则无法一路遍历多个条目,但如果您有很多重复条目,则可以遍历它们。

      static public int removeDuplicates(int[] list, int size) {
          int write = 1;
          for (int read = 1; read < size; read++) {
              if (list[read] == list[read - 1]) {
                  continue;
              }
              list[write++] = list[read];
          }
          return write;
      }
      

      更新:以前的答案,不是可怕的代码,但明显不如上述。

      另一个不必要的超优化。它不仅对结束位调用 arraycopy,而且对开始位调用。通过 binarySearch 将 O(log(n)) 中的任何介绍性非重叠处理到数据中。 O(log(n) + n) 是 O(n) 并且在某些情况下效果会非常明显,尤其是在合并数组之间根本没有重叠的情况下。

      private static int binarySearch(int[] array, int low, int high, int v) {
          high = high - 1;
          while (low <= high) {
              int mid = (low + high) >>> 1;
              int midVal = array[mid];
              if (midVal > v)
                  low = mid + 1;
              else if (midVal < v)
                  high = mid - 1;
              else
                  return mid; // key found
          }
          return low;//traditionally, -(low + 1);  // key not found.
      }
      
      private static int[] sortedArrayMerge(int a[], int b[]) {
          int result[] = new int[a.length + b.length];
          int k, i = 0, j = 0;
          if (a[0] > b[0]) {
              k = i = binarySearch(b, 0, b.length, a[0]);
              System.arraycopy(b, 0, result, 0, i);
          } else {
              k = j = binarySearch(a, 0, a.length, b[0]);
              System.arraycopy(a, 0, result, 0, j);
          }
          while (i < a.length && j < b.length) {
              result[k++] = (a[i] < b[j]) ? a[i++] : b[j++];
          }
          if (j < b.length) {
              System.arraycopy(b, j, result, k, (b.length - j));
          } else {
              System.arraycopy(a, i, result, k, (a.length - i));
          }
          return result;
      }
      

      【讨论】:

      • 赞成开始对对称性做一些事情,但为什么要停在那里呢?使用疾驰搜索,让它返回索引 after 相等的键。仅在超过 3 个元素时使用数组复制。请注意,在复制之后,除了 a) 一个输入和输出数组中的起始索引 b) 您知道哪个“下一个”元素更小之外,没有任何变化。
      • 这完全是实现的 Arrays.sort 所做的。最坏的情况是合并排序。我认为他们在需要的地方交换了 2 个元素,但对于超过 2 个元素,它们属于 arraycopy。我不确定您是线性检查下一个元素还是二进制搜索。如果你能跑得更远,那么推测性地检查你是否能跑得更远会有很大的优势。就像前面检查 8 一样,如果你可以复制,你就为自己节省了 7 项不需要查看的操作。
      • @greybeard ... 完成。也倒退了,所以我可以重复使用相同的内存。
      • 幸好你激发了弹道运动。将在白天的时间汇后仔细观察。
      • That is totally what the implemented Arrays.sort does那个:来自您的答案的第一个修订版 - 或 - 来自我 2 月 19 日的评论?) - 在 Sunsoft 的 JDK 8 中找不到:你指的是Arrays.sort的实现吗?
      【解决方案5】:

      这是用 javascript 编写的缩写形式:

      function sort( a1, a2 ) {
      
          var i = 0
              , j = 0
              , l1 = a1.length
              , l2 = a2.length
              , a = [];
      
          while( i < l1 && j < l2 ) {
      
              a1[i] < a2[j] ? (a.push(a1[i]), i++) : (a.push( a2[j]), j++);
          }
      
          i < l1 && ( a = a.concat( a1.splice(i) ));
          j < l2 && ( a = a.concat( a2.splice(j) ));
      
          return a;
      }
      

      【讨论】:

        【解决方案6】:

        我很惊讶没有人提到这个更酷、更高效、更紧凑的实现:

        public static int[] merge(int[] a, int[] b) {
            int[] answer = new int[a.length + b.length];
            int i = a.length - 1, j = b.length - 1, k = answer.length;
        
            while (k > 0)
                answer[--k] =
                        (j < 0 || (i >= 0 && a[i] >= b[j])) ? a[i--] : b[j--];
            return answer;
        }
        

        兴趣点

        1. 请注意,它执行的操作数与任何其他 O(n) 算法相同或更少,但实际上是在单个 while 循环中的单个语句中!
        2. 如果两个数组的大小大致相同,则 O(n) 的常数相同。但是,如果数组真的不平衡,那么带有 System.arraycopy 的版本会胜出,因为在内部它可以使用单个 x86 汇编指令来做到这一点。
        3. 通知a[i] &gt;= b[j] 而不是a[i] &gt; b[j]。这保证了“稳定性”,即当 a 和 b 的元素相等时,我们希望 a 中的元素在 b 之前。

        【讨论】:

        • 这是一个非常好的方法。我在 Swift 语言中的合并排序算法上很难获得良好的基准。转换这个给了我我需要的东西,非常感谢
        • while 循环中 (j
        • @Hengameh 以防j &lt; 0b 已经用完,所以我们继续将剩余的a 元素添加到answer 数组中
        • 太“聪明”,难以在我的脑海中阅读。我更喜欢更易于阅读的代码,尤其是因为您并没有真正通过这段代码获得任何性能改进。
        • 注意的加点,a[i] >= b[j] 而不是 a[i] > b[j]。这保证了“稳定性”
        【解决方案7】:

        您可以使用 2 个线程来填充结果数组,一个从前,一个从后。

        在数字的情况下,这可以在没有任何同步的情况下工作,例如如果每个线程插入一半的值。

        【讨论】:

          【解决方案8】:
          public static int[] mergeSorted(int[] left, int[] right) {
              System.out.println("merging " + Arrays.toString(left) + " and " + Arrays.toString(right));
              int[] merged = new int[left.length + right.length];
              int nextIndexLeft = 0;
              int nextIndexRight = 0;
              for (int i = 0; i < merged.length; i++) {
                  if (nextIndexLeft >= left.length) {
                      System.arraycopy(right, nextIndexRight, merged, i, right.length - nextIndexRight);
                      break;
                  }
                  if (nextIndexRight >= right.length) {
                      System.arraycopy(left, nextIndexLeft, merged, i, left.length - nextIndexLeft);
                      break;
                  }
                  if (left[nextIndexLeft] <= right[nextIndexRight]) {
                      merged[i] = left[nextIndexLeft];
                      nextIndexLeft++;
                      continue;
                  }
                  if (left[nextIndexLeft] > right[nextIndexRight]) {
                      merged[i] = right[nextIndexRight];
                      nextIndexRight++;
                      continue;
                  }
              }
              System.out.println("merged : " + Arrays.toString(merged));
              return merged;
          }
          

          与原始解决方案略有不同

          【讨论】:

            【解决方案9】:

            这是我删除重复项的 java 实现。

            public static int[] mergesort(int[] a, int[] b) {
                int[] c = new int[a.length + b.length];
                int i = 0, j = 0, k = 0, duplicateCount = 0;
            
                while (i < a.length || j < b.length) {
                    if (i < a.length && j < b.length) {
                        if (a[i] == b[j]) {
                            c[k] = a[i];
                            i++;j++;duplicateCount++;
                        } else {
                            c[k] = a[i] < b[j] ? a[i++] : b[j++];
                        }
                    } else if (i < a.length) {
                        c[k] = a[i++];
                    } else if (j < a.length) {
                        c[k] = b[j++];
                    }
                    k++;
                }
            
                return Arrays.copyOf(c, c.length - duplicateCount);
            }
            

            【讨论】:

              【解决方案10】:

              您可以使用三元运算符使代码更紧凑

              public static int[] mergeArrays(int[] a1, int[] a2) {
                  int[] res = new int[a1.length + a2.length];
                  int i = 0, j = 0;
              
                  while (i < a1.length && j < a2.length) {
                      res[i + j] = a1[i] < a2[j] ? a1[i++] : a2[j++];
                  }
              
                  while (i < a1.length) {
                      res[i + j] = a1[i++];
                  }
              
                  while (j < a2.length) {
                      res[i + j] = a2[j++];
                  }
              
                  return res;
              }
              

              【讨论】:

                【解决方案11】:
                public static void main(String[] args) {
                    int[] arr1 = {2,4,6,8,10,999};
                    int[] arr2 = {1,3,5,9,100,1001};
                
                    int[] arr3 = new int[arr1.length + arr2.length];
                
                    int temp = 0;
                
                    for (int i = 0; i < (arr3.length); i++) {
                        if(temp == arr2.length){
                            arr3[i] = arr1[i-temp];
                        }
                        else if (((i-temp)<(arr1.length)) && (arr1[i-temp] < arr2[temp])){
                                arr3[i] = arr1[i-temp];
                        }
                        else{
                            arr3[i] = arr2[temp];
                            temp++;
                        }
                    }
                
                    for (int i : arr3) {
                        System.out.print(i + ", ");
                    }
                }
                

                输出是:

                1、2、3、4、5、6、8、9、10、100、999、1001、

                【讨论】:

                • 将索引命名为arr2 而不是ind2,而是temp 令人困惑。
                【解决方案12】:

                也许使用 System.arraycopy

                public static byte[] merge(byte[] first, byte[] second){
                    int len = first.length + second.length;
                    byte[] full = new byte[len];
                    System.arraycopy(first, 0, full, 0, first.length);
                    System.arraycopy(second, 0, full, first.length, second.length);
                    return full;
                }
                

                【讨论】:

                • 你只是在合并它们;您的结果数组本身未排序,这是一项要求。
                【解决方案13】:

                这个问题与归并排序算法有关,其中两个已排序的子数组合并为一个已排序的子数组。 CLRS 书提供了一个算法示例,并通过在每个数组的末尾添加一个哨兵值(比较并“大于任何其他值”)来清除检查是否已到达终点的需要。

                我是用 Python 编写的,但它也应该可以很好地转换为 Java:

                def func(a, b):
                    class sentinel(object):
                        def __lt__(*_):
                            return False
                
                    ax, bx, c = a[:] + [sentinel()], b[:] + [sentinel()], []
                    i, j = 0, 0
                
                    for k in range(len(a) + len(b)):
                        if ax[i] < bx[j]:
                            c.append(ax[i])
                            i += 1
                        else:
                            c.append(bx[j])
                            j += 1
                
                    return c
                

                【讨论】:

                • 批量复制元素一次(熟练地)使用哨兵......
                【解决方案14】:

                可以通过多种方式增强算法。例如,检查a[m-1]&lt;b[0]b[n-1]&lt;a[0] 是合理的。 在任何一种情况下,都无需进行更多比较。 算法可以将源数组以正确的顺序复制到结果数组中。

                更复杂的增强功能可能包括搜索交错部分并仅为它们运行合并算法。 当合并数组的大小多次不同时,它可以节省很多时间。

                【讨论】:

                • 对于这个增强,最好使用二分搜索检查第一个元素在第二个数组中的位置,然后数组复制该数据开始。然后在其中一项检查为真的情况下,它只会有 arraycopy 一切,然后 arraycopy 三元,你会得到相同的结果。但是,在有一点点重叠的情况下,您只需要在重叠期间执行正确的算法即可,无需其他时间。由于您事先使用一些快速的 O(logn) 命令会遇到 O(n) 问题,因此不会花费任何成本。
                【解决方案15】:

                我最喜欢的编程语言是 JavaScript

                function mergeSortedArrays(a, b){
                    var result = [];
                
                    var sI = 0;
                    var lI = 0;
                    var smallArr;
                    var largeArr;
                    var temp;
                
                    if(typeof b[0] === 'undefined' || a[0]<b[0]){
                        smallArr = a;
                        largeArr = b;
                    } else{
                        smallArr = b;
                        largeArr = a;
                    }
                
                    while(typeof smallArr[sI] !== 'undefined'){
                        result.push(smallArr[sI]);
                        sI++;
                
                        if(smallArr[sI]>largeArr[lI] || typeof smallArr[sI] === 'undefined'){
                            temp = smallArr;
                            smallArr = largeArr;
                            largeArr = temp;
                            temp = sI;
                            sI = lI;
                            lI = temp;
                        }
                    }
                    return result;
                }
                

                【讨论】:

                  【解决方案16】:
                  public static int[] merge(int[] a, int[] b) {
                      int[] mergedArray = new int[(a.length + b.length)];
                      int i = 0, j = 0;
                      int mergedArrayIndex = 0;
                      for (; i < a.length || j < b.length;) {
                          if (i < a.length && j < b.length) {
                              if (a[i] < b[j]) {
                                  mergedArray[mergedArrayIndex] = a[i];
                                  i++;
                              } else {
                                  mergedArray[mergedArrayIndex] = b[j];
                                  j++;
                              }
                          } else if (i < a.length) {
                              mergedArray[mergedArrayIndex] = a[i];
                              i++;
                          } else if (j < b.length) {
                              mergedArray[mergedArrayIndex] = b[j];
                              j++;
                          }
                          mergedArrayIndex++;
                      }
                      return mergedArray;
                  }
                  

                  【讨论】:

                  • 这有什么可取之处?它可以缩小到for (int i, j, k = i = j = 0 ; k &lt; c.length ; ) c[k++] = b.length &lt;= j || i &lt; a.length &amp;&amp; a[i] &lt; b[j] ? a[i++] : b[j++];。它与Andrew's 2014 answer 有何不同?
                  【解决方案17】:
                  var arrCombo = function(arr1, arr2){
                    return arr1.concat(arr2).sort(function(x, y) {
                      return x - y;
                    });
                  };
                  

                  【讨论】:

                  • 这个答案不适用于 Java 编程语言,尽管它对 javascript 来说是一个很好的答案。
                  • 这是工作面试的一部分。在这些情况下,您并不真正希望编写像上面这样的“正常”代码。他们正在寻找“高效”的代码和您了解所涉及算法的演示。
                  【解决方案18】:

                  Apache 集合从版本 4 开始支持 collat​​e 方法;你可以使用collate 方法来做到这一点:

                  org.apache.commons.collections4.CollectionUtils
                  

                  这里引用javadoc:

                  collate(Iterable<? extends O> a, Iterable<? extends O> b, Comparator<? super O> c)
                  

                  将两个排序的集合ab 合并为一个集合, 排序列表使得元素的排序根据 比较器 c 被保留。

                  不要重新发明轮子!文件参考: http://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/CollectionUtils.html

                  【讨论】:

                    【解决方案19】:
                    public int[] merge(int[] a, int[] b) {
                        int[] result = new int[a.length + b.length];
                        int aIndex, bIndex = 0;
                    
                        for (int i = 0; i < result.length; i++) {
                            if (aIndex < a.length && bIndex < b.length) {
                                if (a[aIndex] < b[bIndex]) {
                                    result[i] = a[aIndex];
                                    aIndex++;
                                } else {
                                    result[i] = b[bIndex];
                                    bIndex++;
                                }
                            } else if (aIndex < a.length) {
                                result[i] = a[aIndex];
                                aIndex++;
                            } else {
                                result[i] = b[bIndex];
                                bIndex++;
                            }
                        }
                    
                        return result;
                    }
                    

                    【讨论】:

                    • 一些解释会很好。 :)
                    【解决方案20】:
                    public static int[] merge(int[] listA, int[] listB) {
                            int[] mergedList = new int[ listA.length + listB.length];
                            int i = 0; // Counter for listA
                            int j = 0; // Counter for listB
                            int k = 0; // Counter for mergedList
                            while (true) {
                                if (i >= listA.length && j >= listB.length) {
                                    break;
                                }
                                if (i < listA.length && j < listB.length) { // If both counters are valid.
                                    if (listA[i] <= listB[j]) {
                                        mergedList[k] = listA[i];
                                        k++;
                                        i++;
                                    } else {
                                        mergedList[k] = listB[j];
                                        k++;
                                        j++;
                                    }
                                } else if (i < listA.length && j >= listB.length) { // If only A's counter is valid.
                                    mergedList[k] = listA[i];
                                    k++;
                                    i++;
                                } else if (i <= listA.length && j < listB.length) { // If only B's counter is valid
                                    mergedList[k] = listB[j];
                                    k++;
                                    j++;
                                }
                            }
                            return mergedList;
                        }
                    

                    【讨论】:

                      【解决方案21】:

                      可以用下面的4个语句来完成

                       int a[] = {10, 20, 30};
                       int b[]= {9, 14, 11};
                       int res[]=new int[a.legth+b.length]; 
                       System.arraycopy(a,0, res, 0, a.length); 
                       System.arraycopy(b,0,res,a.length, b.length);
                       Array.sort(res)
                      

                      【讨论】:

                      • 我不明白为什么这个答案得到了反对票。确实效率不高。但有时你所需要的只是尽快完成工作。如果您正在处理非常小的数组,比如少于 100 个元素,我宁愿使用上面的代码,而不是编写不会带来任何重要性能改进的冗长代码。所以,感谢 Sudhir 提供了这个简单的解决方案并感谢 SANN3 对其进行编辑。
                      • 不成文的前提是sort 函数不能将自身用作排序方法。那将是无限回归而不是递归。另一个前提是merge_array是实现排序的函数。因此,这个答案在最可能的情况下是不可用的。
                      • 问的问题没有提到所需的代码仅适用于小数组。因此,除非明确说明其局限性,否则此答案将具有误导性。也看看我下面的答案。编写适用于任何数组大小的高效代码需要相同数量的行:)
                      • @greybeard - 是的。 OP没有具体说明他所说的效率究竟是什么意思。是代码的复杂程度、需要执行多少行的效率,还是内存消耗的效率,还是基于 CPU 周期的效率?在这里,Sudhir 提供了一个更紧凑和“更高效”的解决方案,如果你只有一个微型阵列。请记住,“过早的优化是万恶之源”。
                      • 我在面试中给出了完全相同的答案,我觉得面试官看起来不太高兴!
                      【解决方案22】:

                      这个解决方案也与其他帖子非常相似,只是它使用 System.arrayCopy 复制剩余的数组元素。

                      private static int[] sortedArrayMerge(int a[], int b[]) {
                          int result[] = new int[a.length +b.length];
                          int i =0; int j = 0;int k = 0;
                          while(i<a.length && j <b.length) {
                              if(a[i]<b[j]) {
                                  result[k++] = a[i];
                                  i++;
                              } else {
                                  result[k++] = b[j];
                                  j++;
                              }
                          }
                          System.arraycopy(a, i, result, k, (a.length -i));
                          System.arraycopy(b, j, result, k, (b.length -j));
                          return result;
                      }
                      

                      【讨论】:

                        【解决方案23】:
                        import java.util.Arrays;
                        
                        public class MergeTwoArrays {
                        
                            static int[] arr1=new int[]{1,3,4,5,7,7,9,11,13,15,17,19};
                            static int[] arr2=new int[]{2,4,6,8,10,12,14,14,16,18,20,22};
                        
                            public static void main(String[] args){
                                int FirstArrayLocation =0 ;
                                int SecondArrayLocation=0;
                                int[] mergeArr=new int[arr1.length + arr2.length];
                        
                                for ( int i=0; i<= arr1.length + arr2.length; i++){
                                    if (( FirstArrayLocation < arr1.length ) && (SecondArrayLocation < arr2.length)){
                                        if ( arr1[FirstArrayLocation] <= arr2[SecondArrayLocation]){
                                            mergeArr[i]=arr1[FirstArrayLocation];
                                            FirstArrayLocation++;
                                        }else{
                                            mergeArr[i]=arr2[SecondArrayLocation];
                                            SecondArrayLocation++;
                                        }
                                    }
                                    else if(SecondArrayLocation < arr2.length){
                                            mergeArr[i]=arr2[SecondArrayLocation];
                                            SecondArrayLocation++;
                                    }else if ( FirstArrayLocation < arr1.length ){
                                            mergeArr[i]=arr1[FirstArrayLocation];
                                            FirstArrayLocation++;
                                    }
                                }
                            }
                        }
                        

                        【讨论】:

                          【解决方案24】:

                          这里是更新的功能。它会删除重复项,希望有人会发现这个有用:

                          public static long[] merge2SortedAndRemoveDublicates(long[] a, long[] b) {
                              long[] answer = new long[a.length + b.length];
                              int i = 0, j = 0, k = 0;
                              long tmp;
                              while (i < a.length && j < b.length) {
                                  tmp = a[i] < b[j] ? a[i++] : b[j++];
                                  for ( ; i < a.length && a[i] == tmp; i++);
                                  for ( ; j < b.length && b[j] == tmp; j++);
                                  answer[k++] = tmp;
                              }
                              while (i < a.length) {
                                  tmp = a[i++];
                                  for ( ; i < a.length && a[i] == tmp; i++);
                                  answer[k++] = tmp;
                              }
                              while (j < b.length) {
                                  tmp = b[j++];
                                  for ( ; j < b.length && b[j] == tmp; j++);
                                  answer[k++] = tmp;
                              }
                              return Arrays.copyOf(answer, k);
                          }
                          

                          【讨论】:

                          • +1,谢谢分享。一个问题:为什么选择数组类型和变量'temp'的类型,long?
                          • (我对方法名有疑问。)
                          【解决方案25】:

                          由于问题不假定任何特定语言。这是Python中的解决方案。 假设数组已经排序。

                          方法 1 - 使用 numpy 数组: 导入numpy

                          arr1 = numpy.asarray([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 11, 14, 15, 55])
                          arr2 = numpy.asarray([11, 32, 43, 45, 66, 76, 88])
                          
                          array = numpy.concatenate((arr1,arr2), axis=0)
                          array.sort()
                          

                          方法 2 - 使用列表,假设列表已排序。

                          list_new = list1.extend(list2)
                          list_new.sort()
                          

                          【讨论】:

                          • Since the question doesn't assume any specific language 从 2011/5/11/19:43 开始,标记为 java
                          • 您的解决方案没有利用事实列表已经排序,并且它的运行时间不是 O(n),因为 .sort() 充其量是 O(n log n)
                          【解决方案26】:

                          我认为为较大的排序数组引入跳过列表可以减少比较次数,并且可以加快复制到第三个数组的过程。如果数组太大,这可能会很好。

                          【讨论】:

                            【解决方案27】:
                                public class Merge {
                            
                                // stably merge a[lo .. mid] with a[mid+1 .. hi] using aux[lo .. hi]
                                public static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
                            
                                    // precondition: a[lo .. mid] and a[mid+1 .. hi] are sorted subarrays
                                    assert isSorted(a, lo, mid);
                                    assert isSorted(a, mid+1, hi);
                            
                                    // copy to aux[]
                                    for (int k = lo; k <= hi; k++) {
                                        aux[k] = a[k]; 
                                    }
                            
                                    // merge back to a[]
                                    int i = lo, j = mid+1;
                                    for (int k = lo; k <= hi; k++) {
                                        if      (i > mid)              a[k] = aux[j++];
                                        else if (j > hi)               a[k] = aux[i++];
                                        else if (less(aux[j], aux[i])) a[k] = aux[j++];
                                        else                           a[k] = aux[i++];
                                    }
                            
                                    // postcondition: a[lo .. hi] is sorted
                                    assert isSorted(a, lo, hi);
                                }
                            
                                // mergesort a[lo..hi] using auxiliary array aux[lo..hi]
                                private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) {
                                    if (hi <= lo) return;
                                    int mid = lo + (hi - lo) / 2;
                                    sort(a, aux, lo, mid);
                                    sort(a, aux, mid + 1, hi);
                                    merge(a, aux, lo, mid, hi);
                                }
                            
                                public static void sort(Comparable[] a) {
                                    Comparable[] aux = new Comparable[a.length];
                                    sort(a, aux, 0, a.length-1);
                                    assert isSorted(a);
                                }
                            
                            
                               /***********************************************************************
                                *  Helper sorting functions
                                ***********************************************************************/
                            
                                // is v < w ?
                                private static boolean less(Comparable v, Comparable w) {
                                    return (v.compareTo(w) < 0);
                                }
                            
                                // exchange a[i] and a[j]
                                private static void exch(Object[] a, int i, int j) {
                                    Object swap = a[i];
                                    a[i] = a[j];
                                    a[j] = swap;
                                }
                            
                            
                               /***********************************************************************
                                *  Check if array is sorted - useful for debugging
                                ***********************************************************************/
                                private static boolean isSorted(Comparable[] a) {
                                    return isSorted(a, 0, a.length - 1);
                                }
                            
                                private static boolean isSorted(Comparable[] a, int lo, int hi) {
                                    for (int i = lo + 1; i <= hi; i++)
                                        if (less(a[i], a[i-1])) return false;
                                    return true;
                                }
                            
                            
                               /***********************************************************************
                                *  Index mergesort
                                ***********************************************************************/
                                // stably merge a[lo .. mid] with a[mid+1 .. hi] using aux[lo .. hi]
                                private static void merge(Comparable[] a, int[] index, int[] aux, int lo, int mid, int hi) {
                            
                                    // copy to aux[]
                                    for (int k = lo; k <= hi; k++) {
                                        aux[k] = index[k]; 
                                    }
                            
                                    // merge back to a[]
                                    int i = lo, j = mid+1;
                                    for (int k = lo; k <= hi; k++) {
                                        if      (i > mid)                    index[k] = aux[j++];
                                        else if (j > hi)                     index[k] = aux[i++];
                                        else if (less(a[aux[j]], a[aux[i]])) index[k] = aux[j++];
                                        else                                 index[k] = aux[i++];
                                    }
                                }
                            
                                // return a permutation that gives the elements in a[] in ascending order
                                // do not change the original array a[]
                                public static int[] indexSort(Comparable[] a) {
                                    int N = a.length;
                                    int[] index = new int[N];
                                    for (int i = 0; i < N; i++)
                                        index[i] = i;
                            
                                    int[] aux = new int[N];
                                    sort(a, index, aux, 0, N-1);
                                    return index;
                                }
                            
                                // mergesort a[lo..hi] using auxiliary array aux[lo..hi]
                                private static void sort(Comparable[] a, int[] index, int[] aux, int lo, int hi) {
                                    if (hi <= lo) return;
                                    int mid = lo + (hi - lo) / 2;
                                    sort(a, index, aux, lo, mid);
                                    sort(a, index, aux, mid + 1, hi);
                                    merge(a, index, aux, lo, mid, hi);
                                }
                            
                                // print array to standard output
                                private static void show(Comparable[] a) {
                                    for (int i = 0; i < a.length; i++) {
                                        StdOut.println(a[i]);
                                    }
                                }
                            
                                // Read strings from standard input, sort them, and print.
                                public static void main(String[] args) {
                                    String[] a = StdIn.readStrings();
                                    Merge.sort(a);
                                    show(a);
                                }
                            }
                            

                            【讨论】:

                            • a[mid+1 .. hi] 复制到aux 的目的是什么?
                            【解决方案28】:

                            一个小的改进,但是在主循环之后,您可以使用System.arraycopy 在到达另一个输入数组的末尾时复制其中一个输入数组的尾部。不过,这不会改变您解决方案的 O(n) 性能特征。

                            【讨论】:

                              【解决方案29】:
                              //How to merge two sorted arrays into a sorted array without duplicates?
                              //simple C Coding
                              #include <stdio.h>
                              #include <stdlib.h>
                              #include <string.h>
                              
                              main()
                              {
                                  int InputArray1[] ={1,4,5,7,8,9,12,13,14,17,40};
                                  int InputArray2[] ={4,5,11,14,15,17,18,19,112,122,122,122,122};
                                  int n=10;
                                  int OutputArray[30];
                                  int i=0,j=0,k=0;
                                  //k=OutputArray
                                  while(i<11 && j<13)
                                  {
                                      if(InputArray1[i]<InputArray2[j])
                                      {
                                          if (k == 0 || InputArray1[i]!= OutputArray[k-1])
                                          {
                                              OutputArray[k++] = InputArray1[i];
                                          }
                                          i=i+1;
                                      }
                                      else if(InputArray1[i]>InputArray2[j])
                                      {
                                          if (k == 0 || InputArray2[j]!= OutputArray[k-1])
                                          {
                                              OutputArray[k++] = InputArray2[j];
                                          }
                                          j=j+1;
                                      }
                                      else
                                      {
                                          if (k == 0 || InputArray1[i]!= OutputArray[k-1])
                                          {
                                              OutputArray[k++] = InputArray1[i];
                                          }
                                          i=i+1;
                                          j=j+1;
                                      }
                                  };
                                  while(i<11)
                                  {
                                      if(InputArray1[i]!= OutputArray[k-1])
                                          OutputArray[k++] = InputArray1[i++];
                                      else
                                          i++;
                                  }
                                  while(j<13)
                                  {
                                      if(InputArray2[j]!= OutputArray[k-1])
                                          OutputArray[k++] = InputArray2[j++];
                                      else
                                          j++;
                                  }
                                  for(i=0; i<k; i++)
                                  {
                                      printf("sorted data:%d\n",OutputArray[i]);
                                  };
                              }
                              

                              【讨论】:

                                【解决方案30】:

                                我必须用 javascript 编写它,这里是:

                                function merge(a, b) {
                                    var result = [];
                                    var ai = 0;
                                    var bi = 0;
                                    while (true) {
                                        if ( ai < a.length && bi < b.length) {
                                            if (a[ai] < b[bi]) {
                                                result.push(a[ai]);
                                                ai++;
                                            } else if (a[ai] > b[bi]) {
                                                result.push(b[bi]);
                                                bi++;
                                            } else {
                                                result.push(a[ai]);
                                                result.push(b[bi]);
                                                ai++;
                                                bi++;
                                            }
                                        } else if (ai < a.length) {
                                            result.push.apply(result, a.slice(ai, a.length));
                                            break;
                                        } else if (bi < b.length) {
                                            result.push.apply(result, b.slice(bi, b.length));
                                            break;
                                        } else {
                                            break;
                                        }
                                    }
                                    return result;
                                }
                                

                                【讨论】:

                                  猜你喜欢
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2021-10-11
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多