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

算法稳定性 -- 假设在数列中存在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. javascript-文档结构遍历

    1.document.all document.all[0] //文档中第一个元素 document.all["navbar"] //id或name为"navbar&qu ...

  2. SpringBoot23 分模块开发

    1 开发环境说明 JDK:1.8 MAVEN:3.5 IDEA:2017.2.5 SpringBoot:2.0.3.RELEASE 2 创建SpringBoot项目 2.1 项目信息 2.2 添加项目 ...

  3. CentOS 安装mongodb3.0 二进制包

    1.下载mongodb因为64位系统CentOS,所以下载64位的安装包: wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0 ...

  4. Oracle——创建和管理表

    一.常见的数据库对象 对象 描述 表 基本的数据存储集合,由行和列组成 视图 从表中抽出的逻辑上相关的数据集合 序列 提供有规律的数值 索引 提高查询的效率 同以词 给对象起别名 二.Oracle 数 ...

  5. Request[]与Request.Params[] 差别

    Request[]与Request.Params[] ,这二个属性都可以让我们方便地根据一个KEY去[同时搜索]QueryString.Form.Cookies 或 ServerVariables这4 ...

  6. UIPopoverController 简单用法(全代码)

     AppDelegate.m - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDic ...

  7. UVa 11149 Power of Matrix (矩阵快速幂,倍增法或构造矩阵)

    题意:求A + A^2 + A^3 + ... + A^m. 析:主要是两种方式,第一种是倍增法,把A + A^2 + A^3 + ... + A^m,拆成两部分,一部分是(E + A^(m/2))( ...

  8. Java 数据结构之双链表

    package Linked; public class Mylinked { private Node first;//链表的第一个节点 private Node last;//链表的最后一个节点 ...

  9. 【Android学习】Android工程资源命名禁忌

    在制作一个继续按钮时,将button的id设置为continue,发现报了错误,error: invalid symbol: 'continue' 一开始还以为是编码问题,后来百度之后才知道安卓And ...

  10. BZOJ3223 文艺平衡树(splay)

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