zoukankan      html  css  js  c++  java
  • 高效合并两个有序数组

    1、用temp数组作为中间变量,保存两个有序子数组的合并结果数组,再复制回原数组。
          空间复杂度O(N),时间复杂度O(m+n),m、n为两个有序子数组的长度

    //将有二个有序数列a[first...mid]和a[mid...last]合并。
    void mergearray(int a[], int first, int mid, int last, int temp[])
    {
    int i = first, j = mid + 1;
    int m = mid, n = last;
    int k = 0;

    while (i <= m && j <= n)
    {
    if (a[i] <= a[j])
    temp[k++] = a[i++];
    else
    temp[k++] = a[j++];
    }

    while (i <= m)
    temp[k++] = a[i++];

    while (j <= n)
    temp[k++] = a[j++];

    for (i = 0; i < k; i++)
    a[first + i] = temp[i];
    }

    2、没有中间变量temp,要求空间复杂度为O(1),通过交换+移位实现
          空间复杂度O(1),时间复杂度最坏为O(N*N)

    void swap(int *a, int *b)
    {
    int tmp;

    tmp = *a;
    *a = *b;
    *b = tmp;
    }

    void func(int a[], int n)
    {
    int i,j;

    if (n<=0)
    {
    return;
    }
    i = 0;
    j = n/2;

    while(j<n && i<j)
    {
    if (a[i]<=a[j])
    {
    i++;
    }
    else
    {
    swap(a[i], a[j]);
    for (int k=j-1;k>i; k--) // 每次发现一个a[i]>a[j]交换后,需要把i+1到j的子数组循环右移一
    { // 位,(i+1)~(j)保持有序,这里可以优化
    swap(a[k], a[k+1]);
    }
    i++;
    j++;
    }
    }

    }

    3、优化第二种方法,交换+循环移位(不用中间变量,通过交换反转实现),第二种方法中,每次移动的单位是一个数,效率低,可以采用块循环移动(单位是连续几个数)进行优化
    空间复杂度O(1),时间复杂度应该比O(m+n)要小!

    void Reverse(int *a , int begin , int end ) //反转
    {
    for(; begin < end; begin++ , end--)
    swap(a[begin] , a[end]);
    }
    void RotateRight(int *a , int begin , int end , int k) //循环右移,a[begin:end]段向右循环移位k位
    {
    int len = end - begin + 1; //数组的长度
    k %= len;
    Reverse(a , begin , end - k);
    Reverse(a , end - k + 1 , end);
    Reverse(a , begin , end);
    }

    // 将有序数组a[begin...mid] 和 a[mid+1...end] 进行合并
    void Merge(int *a , int begin , int end )
    {
    int i , j , k;
    i = begin;
    j = 1 + ((begin + end)>>1); //位运算的优先级比较低,需要加一个括号
    while(i <= end && j <= end && i<j)
    {
    while(i <= end && a[i] < a[j])
    i++;
    k = j; //暂时保存指针j的位置
    while(j <= end && a[j] < a[i]) // 找到连续的j索引列都小于a[i],进行块循环移动
    j++;
    if(j > k)
    RotateRight(a , i , j-1 , j-k); //数组a[i...j-1]循环右移j-k次,a[i..j-1]始终有序
    i += (j-k+1); //第一个指针往后移动,因为循环右移后,数组a[i....i+j-k]是有序的
    }
    }

  • 相关阅读:
    [React] Use the React Context API to Globally Manage State
    [Docker] Push container to Docker hub
    [Docker] Create a Node.js Non-root Image
    时序数据库DolphinDB与Druid的对比测试
    麻省理工学院的牛人解说数学体系,你到哪个层次了?
    Python的7种性能测试工具:timeit、profile、cProfile、line_profiler、memory_profiler、PyCharm图形化性能测试工具、objgraph
    2020年度盘点:顶流坐镇的普林斯顿理科书单请收藏
    万字Matplotlib实操总结,几行代码实现数据绘图
    形意拳-五行拳之劈拳功法奥秘
    Top 10 Python Packages For Finance And Financial Modeling
  • 原文地址:https://www.cnblogs.com/wzf-Learning/p/8109513.html
Copyright © 2011-2022 走看看