归并排序:先将数组一分为二,将左边部分排序(同样将其一分为二),再将右边部分排序,最后逐层归并。(分治策略)(稳定排序)。

算法稳定性 -- 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的!

先排序的时间复杂度为log(n);

后归并的时间复杂度为n;

总的时间复杂度nlog(n)。

 

1)自顶向下归并排序的代码:需要一个和待排序数组相同的空间,故将arr[]拷贝一份给aux[]

//将arr[l...mid]和 arr[mid+1...r]两部分进行归并
template<typename T>
void merge(T arr[], int l, int mid, int r){
//需要一个临时的和arr同样大小的空间
T aux[r-l+];
for(int i=l;i<=r;i++)
//将arr复制给aus,aus下标从0开始,而arr下标从l开始
aux[i-l] = arr[i];
//初始化,i指向左半部分的起始索引位置l;j指向右半部分起始索引位置mid+1
int i = l, j = mid+;
for(int k=l;k<=r;k++){
//逐步比较左部分的第i个元素和右部分的第j个元素的大小
//首先判断下标i和j的合法性
if(i>mid){
//左边已经遍历完,但右边还有
arr[k] = aux[j-l];
j++
}
else if(j>r){
//右边已经遍历完,将左边的元素给arr
arr[k] = aux[i-l];
i++;
}
else if(aux[i-l]<aux[j-l]){
arr[k] = aux[i-l];
i++;
}
else{
arr[k] = aux[j-l];
j++;
}
}
} //递归使用归并排序,对arr[l...r]的范围进行排序
template<typename T>
void mergeSort(T arr[], int l, int r){
if(l>=r)
return;
int mid = (l+r)/;
mergeSort(arr, l, mid);
mergeSort(arr, mid+,r);
//优化:只有当 mid>mid+1 时才需要对左右两边进行排序
//因为左边或右边本身是有序的,如果 mid<=mid+1 则不需要对其归并排序了
if(arr[mid] > arr[mid+])
merge(arr,l,mid,r);
}

当数组中的元素足够少时,可以将递归出口改为插入排序,虽然插入排序的时间复杂度是O(n),但是可以提高效率。

2)自底向上归并排序:

template<typename T>      //泛型
void mergeSortBU(T arr[], int n){
//自底向上归并
//对merge的元素个数进行遍历:1,2,4,8以此类推
for(int sz= ; sz<=n ; sz+=sz ){
for(int i=; i+sz<n; i+=sz+sz)
//对arr[i...i+sz-1]和arr[i+sz...i+2*sz-1]进行归并
merge(arr, i, i+sz-, min(i+sz+sz-, n-));
}
}

注意:nums1和nums2 是有序的,m代表nums1元素的个数。

这里的解题思想是归并排序的merge()函数的思想,先开辟一个与nums1相同大小和值的空间aux,再将其与nums2逐一对比,用小的来替换nums1的值。

class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) { if (m <= && n <= ) return;
//int aux[m];
vector<int> aux(m);
for(int i=;i<m;i++){
//将nums1的值拷贝给aux
aux[i] = nums1[i];
} int i=,j=;
for(int k=;k<nums1.size();k++){
if(i>m-){
//aux数组超界
nums1[k] = nums2[j];
j++;
}
else if(j>n-){
nums1[k] = aux[i];
i++;
}
else if(nums2[j]<aux[i]){
nums1[k] = nums2[j];
j++;
}
else{
nums1[k] = aux[i];
i++;
} }
}
};

解法二:从两个数组的末尾开始比较大小,从下标为m+n-1开始存放,将大的存放在nums1的末尾。如果最后剩下的是nums1,则不需要移动;若是nums2中的元素则需要放在nums1的相应位置。

class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) { if (m <= && n <= ) return; int count = m+n-;
--m, --n; //m和n是长度,所以要减1变成下标
while(m>= && n>=){
if(nums1[m] >nums2[n])
nums1[count--] = nums1[m--];
else
nums1[count--] = nums2[n--];
}
while(n>=){
//当m已经全部遍历完,n还剩下
nums1[count--] = nums2[n--];
}
}
};

leetcode 88 Merge Sorted Array 归并排序的更多相关文章

  1. Leetcode#88. Merge Sorted Array(合并两个有序数组)

    题目描述 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组. 说明: 初始化 nums1 和 nums2 的元素数量分别为 m ...

  2. [LeetCode] 88. Merge Sorted Array 混合插入有序数组

    Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note: T ...

  3. LeetCode 88. Merge Sorted Array(合并有序数组)

    Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note:Yo ...

  4. leetCode 88.Merge Sorted Array (合并排序数组) 解题思路和方法

    Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note: Y ...

  5. [LeetCode] 88. Merge Sorted Array 合并有序数组

    Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note: T ...

  6. LeetCode 88 Merge Sorted Array

    Problem: Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array ...

  7. Leetcode 88. Merge Sorted Array(easy)

    Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note:Yo ...

  8. [leetcode]88. Merge Sorted Array归并有序数组

    Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note: T ...

  9. Leetcode 88 Merge Sorted Array STL

    合并有序数组 时间复杂度O(m+n) 该算法来自各种算法与数据结构书,写得已经烂得不能再烂了,这个应该是最短的代码了吧,不知如何归类 class Solution { public: void mer ...

随机推荐

  1. IWebBrowser和IE浏览器的行为不一样

    原本一直以为IWebBrowser2的行为和IE浏览器的行为应该是一样的,但是最近发现事实不是如此. IE8以后的浏览器都带有兼容模式,而IWebBrowser2默认情况下是在兼容模式下运行的,可以参 ...

  2. box-shadow 内阴影

    1.盒子阴影样式单词:box-shadow 2.语法 代表边框间距靠左0 靠上0 和1px阴影范围 阴影颜色为黑色(#000),有inset 代表框内阴影 ,不带inset 代表框外阴影. 注意:bo ...

  3. os.chdir("/deepmatching") OSError: [Errno 2] No such file or directory: '/deepmatching'

    #os.chdir("/deepmatching")os.chdir(os.path.dirname(os.path.abspath("deepmatching1&quo ...

  4. opennebula image单个实例响应数据格式

    { ", ", ", "TEMPLATE": { "DEV_PREFIX": "hd", " }, ...

  5. 如何获取.properties配置文件

    如何获取.properties配置文件 分析思路: 先使用流和文件关联,即读取文件 再读取文件内容,一行一行读取 字符分割“=”  键值对 然后把键值对放到集合中去 但是Properties类里面有方 ...

  6. 何为软件的Alpha、Beta、RC和GA发布版本?

    简介 一个软件或者一个功能在发布时,通常会有Beta版这么一说.我很熟悉,差不多知道是什么意思,但没去深究,感觉上就是一个可以用但不保证功能稳定的版本. 直到昨天我看到了 MariaDB 数据库发布标 ...

  7. RPLiDAR 激光雷达探测地面高程

    LiDAR,又称激光探测与测量,全程Light Detection And Ranging,这种技术使用激光测量地物(如森林和建筑物)的高程.它的原理十分类似于使用声波来测绘海底地形的声呐技术,或使用 ...

  8. Ext JS v2.3.0 Ext.grid.ColumnModel renderer Record 获取列值

    场景:设置某一列的值,但是需要获取其他列的值 {"header": '<s:property value="name" />', "wid ...

  9. C# Socket通信改进记录

    1. Socket 使用原始Socket,Send和Recv方法 进行发送和消息获取.(另起后台线程 不停获取和发送) public void RecvMsg() { //receive messag ...

  10. 用firebug 进行表单自定义提交

    在一些限制网页功能的场合,例如,防止复制内容,防止重复提交,限制操作的时间段/用户等,网页上一些按钮是灰化的(禁用的),这通常是通过设置元素的 disable属性来实现的.但在后台并没有做相应的功能限 ...