zoukankan      html  css  js  c++  java
  • 合并两个排序的数组

    需求:有两个非递减排序的数组A1和A2,内存在A1的末尾有足够多的空余空间容纳A2,请实现一个函数,把A2中的所有数字插入A1中,并且所有的数字都是排序的。

    例如数组A1{ 1,5,7,8,9,17,20 }和数组A2{ 0,2,4,6,7,17,18,23,25 },合并后的结果应为{ 0,1,2,3,5,7,7,8,9,17,17,18,20,23,25 }。

    分析:

    思路一

    直接从两个数组头部开始合并。

    1.从A2开始遍历第一个数字;

    2.由于A1中如果数字比A2小的话,A1和A2的数字都不需要变动,因此查找A1中第一个比A2当前数字的小的元素;

    3.如果找到了A1中的最后一个数字都比当前A2的数字小,说明A2当前数字以及后面所有的数字都比A1的最后一个数字大,直接把A2当前的数字以及后面所有的数字都依次放到A1最后一个元素的后面即完成合并;

    4.如果找到了A1中的其中一个数字比A2大,则把A1的这个数字以及后面的所有数字都往后移动1个位置;

    5.把A2的这个数字放到步骤2中找到的A1的元素的位置,完成了A2的第1个数字的合并;

    6.继续开始A2的下一个数字,重复步骤2直到数组A2的最后一个数字都已经被放到A1中。

    从头开始合并发,由于要在遍历数组A2的同时还要查找A1中比A2大的元素,并且还要移动A1的元素,假设待合并的两个数组的数字个数分别为m和n,则时间复杂度为O(m*n)。

    见示例代码mergeArrayFromHead

    思路二

    从两个数组的尾部开始合并。

    1.由于合并后的数组长度是A1的长度加上A2的长度,所以可以获取最终数组的最后一个数字的位置;

    2.同时从数组A1和A2的最后一个数字开始往前遍历;

    3.如果A2的当前数字比A1大,说明A2数组的这个数字排在靠后的位置,所以最终数组的最后一个位置应该填上A2数组的数字,然后A2往前遍历下一个数字;否则,最终数组的最后一个位置应该填上A1数组的数字,然后A1往前遍历下一个数字。

    4.当确定了最终数组的最后一个位置的数字之后,继续确定倒数第二个数字的值,通过步骤3结果比较当前A2和A1的数组的数字。继续步骤3。

    5.当数组A2的最后一个数字都已经被放到最中的数组A1中之后,任务结束。

    从尾开始替换法,由于只需要同时遍历数组A1和A2就完成了处理,假设待合并的两个数组的数字个数分别为m和n,则时间复杂度为O(m+n)。

    见示例代码mergeArrayFromTail

    扩展需求见:https://www.cnblogs.com/huangwenhao/p/11172206.html

    c++示例代码:

      1 #include <iostream>
      2 
      3 using namespace std;
      4 
      5 /************************************************************************/
      6 /* @brif 从头开始合并数组B的数字到数组A中
      7 /* @param arrA 非递减排序的整数数组A
      8 /* @param numA 数组A的数字的数量
      9 /* @param arrB 非递减排序的整数数组B
     10 /* @param numB 数组B的数字的数量
     11 /* @return true表示合并成功 false表示合并失败
     12 /************************************************************************/
     13 bool mergeArrayFromHead(int* arrA, const int numA, const int* arrB, const int numB)
     14 {
     15     if (!arrA || !arrB || numA < 0 || numB < 0)
     16     {
     17         cout << "传参有问题" << endl;
     18         return false;
     19     }
     20 
     21     int newLenA = numA;
     22     int currIndexA = 0;
     23 
     24     for (int i = 0; i < numB; ++i)
     25     {
     26         //查找到下一个比B数字大的数
     27         while (currIndexA < newLenA && arrA[currIndexA] < arrB[i])
     28         {
     29             ++currIndexA;
     30         }
     31         //假如A的最后一个元素都比B当前的数字小,就B和后面所有的数字都放到A最后一个数字的后面,结束循环
     32         if (currIndexA == newLenA)
     33         {
     34             for (int j = i; j < numB; ++j)
     35             {
     36                 arrA[currIndexA] = arrB[j];
     37                 ++currIndexA;
     38             }
     39         }
     40         else
     41         {
     42             //当前A的数字比B的数字大,从当前A的数字开始,所有数字都往后移动1位,把B的数字放在当前A的数字的位置
     43             for (int j = newLenA; j >= currIndexA; --j)
     44             {
     45                 arrA[j + 1] = arrA[j];
     46             }
     47             arrA[currIndexA] = arrB[i];
     48             //移动到下一个
     49             ++currIndexA;
     50             //由于增加了一个数字,数组新长度加1
     51             ++newLenA;
     52         }        
     53     }
     54     return true;
     55 }
     56 
     57 /************************************************************************/
     58 /* @brif 从尾开始合并数组B的数字到数组A中
     59 /* @param arrA 非递减排序的整数数组A
     60 /* @param numA 数组A的数字的数量
     61 /* @param arrB 非递减排序的整数数组B
     62 /* @param numB 数组B的数字的数量
     63 /* @return true表示合并成功 false表示合并失败
     64 /************************************************************************/
     65 bool mergeArrayFromTail(int* arrA, const int numA, const int* arrB, const int numB)
     66 {
     67     if (!arrA || !arrB || numA < 0 || numB < 0)
     68     {
     69         cout << "传参有问题" << endl;
     70         return false;
     71     }
     72 
     73     int currIndex = numA + numB -1;
     74     int currIndexA = numA, currIndexB = numB;
     75     for (int i = currIndexB-1, j = currIndexA-1; i > 0 && j > 0;)
     76     {
     77         //如果B数组的数字比较大或者相等,则把B的数字放在当前位置,否则把A的数字放在当前位置
     78         if (arrA[j] <= arrB[i])
     79         {
     80             arrA[currIndex] = arrB[i];
     81             --i;
     82         }
     83         else
     84         {
     85             arrA[currIndex] = arrA[j];
     86             --j;
     87         }
     88         --currIndex;
     89     }
     90     return true;
     91 }
     92 
     93 int main()
     94 {
     95     int arrA1[100] = { 1,5,7,8,9,17,20 };
     96     int arrB1[100] = { 0,2,4,6,7,17,18,23,25 };
     97 
     98     int arrA2[100] = { 1,5,7,8,9,17,20 };
     99     int arrB2[100] = { 0,2,4,6,7,17,18,23,25 };
    100 
    101     int lenA = 7;
    102     int lenB = 9;
    103 
    104     cout << "原始数组A:" << endl;
    105     for (int i = 0; i < lenA; ++i)
    106     {
    107         cout << arrA1[i] << "	";
    108     }
    109 
    110     cout << endl << endl << "原始数组B:" << endl;
    111     for (int i = 0; i < lenB; ++i)
    112     {
    113         cout << arrB1[i] << "	";
    114     }
    115 
    116     bool success = mergeArrayFromHead(arrA1, lenA, arrB1, lenB);
    117     cout << endl << endl << "从头开始合并法" << endl;
    118     if (!success)
    119     {
    120         cout << "合并失败" << endl;
    121     }
    122     else
    123     {
    124         for (int i = 0; i < lenB + lenA; ++i)
    125         {
    126             cout << arrA1[i] << "	";
    127         }
    128     }
    129 
    130     success = mergeArrayFromTail(arrA2, lenA, arrB2, lenB);
    131     cout << endl << endl << "从尾开始合并法" << endl;
    132     if (!success)
    133     {
    134         cout << "合并失败" << endl;
    135     }
    136     else
    137     {
    138         for (int i = 0; i < lenB + lenA; ++i)
    139         {
    140             cout << arrA2[i] << "	";
    141         }
    142     }
    143 
    144     cout << endl << endl;
    145     return 0;
    146 }

    运行结果

  • 相关阅读:
    set
    皮肤病药物
    C 批量保存图片进 mysql 利用MYSQL_BIND插入longblob
    eclipse行号显示
    dynamic_cast使用
    list添加删除操作
    VS2008 对齐代码
    c++ mysql二进制存取,blob存取
    Select Window关键字——模拟打开了多个页面窗口时,在不同的窗口之间,进行窗口切换
    Click Image关键字——模拟单击某一个图片 其余:Click Button / Click Link
  • 原文地址:https://www.cnblogs.com/huangwenhao/p/11175427.html
Copyright © 2011-2022 走看看