zoukankan      html  css  js  c++  java
  • Leetcode OJ: Merge Sorted Array

    Merge Sorted Array

    Given two sorted integer arrays A and B, merge B into A as one sorted array.

    Note:
    You may assume that A has enough space (size that is greater or equal to m + n) to hold additional elements from B. The number of elements initialized in A and B are m andn respectively.

    最简单粗暴的思路:

    1. 开辟数组空间C用以存放中间过程,然后对A、B数组各给一个指针。

    2. 开始遍历比较,哪个小把对应的值push进C,然后对应指针也后移,直到两个数组都遍历完了。

    3. 把C的值都拷贝到A。

    时间复杂度为O(m+n),空间复杂度为O(m+n)。

    代码如下:

     1 class Solution {
     2 public:
     3     void merge(int A[], int m, int B[], int n) {
     4         vector<int> C;
     5         int i = 0, j = 0;
     6         int count = 0;
     7         while (i < m && j < n) {
     8             if (A[i] < B[j]) {
     9                 C.push_back(A[i]);
    10                 ++i;
    11             } else {
    12                 C.push_back(B[j]);
    13                 ++j;
    14             }
    15             count++;
    16         }
    17         while (i < m) {
    18             C.push_back(A[i++]);
    19             count++;
    20         }
    21         while (j < n) {
    22             C.push_back(B[j++]);
    23             count++;
    24         }
    25         
    26         for (int i = 0; i < count; ++i) {
    27             A[i] = C[i];
    28         }
    29     }
    30 };

    减少比较次数的思路(利用二分查找):

    1. 开辟数组空间C用以存放中间过程,然后对A、B数组各给一个指针i, j。

    2. 在A[i]后查找B[j]应该在A中插入的位置i+ansA(一定要注意好下标

    3. 若ansA没越界,判断A[i+ansA]是与B[j]是否相等,若相等重复3,否则跳下一步4。

    4. 把A[i]~A[i+ansA](不包含)值都拷贝到C中。

    5. 若ansA仍没越界,则在B[j]中查找这一值应插入的位置ansB,把B[j]~B[j+ansB](不包含)值都拷贝到C中,j:=j+ansB。

    6. i := i+ansA。如果i,j均没越界,跳到2,否则跳到下一步7。

    7. 把A、B中的剩余部分都拷贝到C

    8. 最后把C的值都拷贝到A

    代码如下:

     1 class Solution {
     2 public:
     3     // 二分查找
     4     int search(int A[], int n, int target) {
     5         int begin = 0, end = n, mid;
     6         while (begin < end) {
     7             mid = begin + ((end - begin) >> 1);
     8             if (A[mid] < target) {
     9                 begin = mid + 1;
    10             } else if (A[mid] > target) {
    11                 end = mid;
    12             } else {
    13                 break;
    14             }
    15         }
    16         if (begin >= end)
    17             return end;
    18         return mid;
    19     }
    20 
    21     void merge(int A[], int m, int B[], int n) {
    22         vector<int> C;
    23         int i = 0, j = 0;
    24         while (i < m && j < n) {
    25             int ansA = search(A + i, m - i, B[j]);
    26             // 判断是否与B[j]相等
    27             while (i + ansA < m && A[i + ansA] == B[j])
    28                 ++ansA;
    29             if (ansA > 0)
    30                 C.insert(C.end(), A + i, A + i + ansA);
    31             if (i + ansA < m) {
    32                 int ansB = search(B + j, n - j, A[i + ansA]);
    33                 if (ansB > 0) {
    34                     C.insert(C.end(), B + j, B + j + ansB);
    35                     j += ansB;
    36                 }
    37             } 
    38             i += ansA;
    39         }
    40         if (i < m) {
    41             C.insert(C.end(), A + i, A + m);
    42         }
    43         if (j < n) {
    44             C.insert(C.end(), B + j, B + n);
    45         }
    46         
    47         copy(C.begin(), C.end(), A);
    48     }
    49 };

    比较次数是O(logm+logn),复制次数还是O(m+n),最终复杂度还是O(m+n),空间复杂度为O(m+n)。

    在时间复杂度上我已经尽力了,于是就想有没有空间复杂度为O(1)的方法呢?

    很自然就会想到利用数组移动,为了减小移动的数量,我们还可以结合以上说到的二分查找。

    过程与以上类似,只是中间过程需要不断改变A的长度,而且要特别的注意下标问题。

     1 class Solution {
     2 public:
     3     int search(int* A, int n, int target) {
     4         int begin = 0, end = n;
     5         int mid;
     6         while (begin < end) {
     7             mid = begin + ((end - begin) >> 1);
     8             if (A[mid] < target) {
     9                 begin = mid + 1;
    10             } else if (A[mid] > target) {
    11                 end = mid;
    12             } else {
    13                 break;
    14             }
    15         }
    16         
    17         if (begin >= end) {
    18             return end;
    19         }
    20         return mid;
    21     }
    22     
    23     
    24     void merge(int A[], int m, int B[], int n) {
    25         vector<int> C;
    26         int i = 0, j = 0;
    27         while (i < m && j < n) {
    28             int ansA = search(A + i, m - i, B[j]);
    29             while (i + ansA < m && A[i + ansA] == B[j])
    30                 ansA++;
    31             if (ansA < m - i) {
    32                 int ansB = search(B + j, n - j, A[i + ansA]);
    33                 if (ansB > 0) { 
    34                     for (int k = m - 1; k >= i + ansA; --k) {
    35                         A[k + ansB] = A[k];
    36                     }
    37                     for (int k = 0; k < ansB; ++k) {
    38                         A[i + ansA + k] = B[j + k];
    39                     }
    40                     j += ansB;
    41                 }
    42                 i += ansA + ansB;
    43                 m += ansB;
    44             } else {
    45                 i += ansA;
    46                 break;
    47             }
    48         }
    49         
    50         while (j < n) {
    51             A[i++] = B[j++];
    52         }
    53     }
    54 };

    时间复杂度为O(m+n),空间复杂度为O(1)。

    不过最终在LeetCode上跑的运行时间,对于这三段代码都是没有明显的区别,有时候简单粗暴的方法还更快一些。所以大家看着玩就好。

     
  • 相关阅读:
    如何在Ubuntu 18.04上安装Memcached
    ubuntu安装mysql添加密码
    Django学习---快速搭建搜索引擎(haystack + whoosh + jieba)
    django3.x 使用haystack 报错:ImportError: cannot import name 'six' from 'django.utils'
    spring boot2之Jackson和ObjectMapper
    python之装饰器强制函数上的类型检查
    python之*args和**kwargs的区别
    Python之@property
    python基础语法之and,or,not
    小案例
  • 原文地址:https://www.cnblogs.com/flowerkzj/p/3616937.html
Copyright © 2011-2022 走看看