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

算法稳定性 -- 假设在数列中存在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. 599. Minimum Index Sum of Two Lists两个餐厅列表的索引和最小

    [抄题]: Suppose Andy and Doris want to choose a restaurant for dinner, and they both have a list of fa ...

  2. java 解析xml(dom4j.jar)

    先导入jar包 <?xml version="1.0" encoding="UTF-8"?> <companys> <compan ...

  3. Luogu 1606 [USACO07FEB]白银莲花池Lilypad Pond

    感觉应当挺简单的,但是弄了好久……菜死了 如果不考虑那些为$1$的点,直接跑个最短路计数就好了,但是我们现在有一些边可以不用付出代价,那么只要在连边的时候先预处理搜一下就好了. 原来的想法是拆点,但是 ...

  4. 【原创】请不要对Boost Format使用Byte作为参数

    曾几何时我们可以肆无忌惮的对sprintf传入BYTE等类型作为参数,只要你指定的为%D即可打印出对应的数字 但是boost format不可以,当你发生类型截断,错误,异常,请尽快查看你传入的类型是 ...

  5. hdu 1905 Pseudoprime numbers

    #include<stdio.h> #include<math.h> #define ll long long ll mod; bool Judge(int x) { ;i&l ...

  6. BZOJ3223 文艺平衡树(splay)

    题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1, ...

  7. WndProc

    主要用在拦截并处理系统消息和自定义消息. form窗体的一个重载方法. protected override void WndProc(ref Message m) { //拦截窗体最小化按钮消息 i ...

  8. AD对象DirectoryEntry本地开发

    DirectoryEntry类如果需要在本地计算机开发需要满足以下条件: 1.本地计算机dns解析必须和AD域控制器的dns保持一致,如图: 2.必须模拟身份验证,才能操作查询AD用户 /// < ...

  9. Linux服务器其中一个磁盘满了怎么办?在不做磁盘扩容的情况下,一个软连接就搞定。

    适用环境要求:Linux系统及服务器.有管理员权限.存在多余空间的磁盘例如下图中"/home"在磁盘sda5中与"/"不属于同一块磁盘: 1.首先转移正在使用的 ...

  10. 20165219 2017-2018-2《Java程序设计》结对编程一 第一周总结

    20165219 2017-2018-2<Java程序设计>结对编程一 第一周总结 结对对象 20165219王彦博 20165232何彦达 需求分析 实现一个程序,要求: 1 支持整数运 ...