数组al[0,mid-1] 和 al[mid,num-1],都分别有序。将其merge成有序数组al[0,num-1],要求空间复杂度O(1)

思路:一般的归并是需要O(n)的空间,而这里要求空间复杂度为O(1),也就是只能使用常熟级别的临时变量。而原地操作无非就是移动,关键是怎么移动。在编程珠玑中有一个旋转算法(旋转后k个元素到前面),可以在这里起到关键性作用。见http://www.cnblogs.com/ivorfeng/archive/2013/05/12/3074822.html

因为数组al[0,mid-1] 和 al[mid,num-1],都分别有序,我们要做的是将较小的元素(可能是连续的一片)插入到合理的位置中;不妨假设left 和right是两个有序数组中的下标,a[left] < a[right],首先要在左半部分找到第一个比a[right]大的下标newleft,接着在右半部分找到比a[newleft]小的下表newright,并记录right到newright所移动的步数move

如上图所示,最后就是将红色框中的元素进行右旋转move(这里为3)个元素。

代码如下:

 //翻转数组
template <typename T>
void Reverse(T *a, int size)
{
T tmp;
for(int i = ; i < size/; ++i)
{
tmp = a[i];
a[i] = a[size - i - ];
a[size - i - ] = tmp;
} }
//旋转
template <typename T>
void Rotate(T*a, int size, int pos)
{
Reverse(a, pos);
Reverse(a + pos, size - pos);
Reverse(a, size); }
template<typename T>
void InplaceMerge(T *a, int size, int mid)
{
int fir = ;
int sec = mid;
int Move = ;
while (fir < sec && sec < size)
{
while (fir < sec && a[fir] < a[sec])
{
++fir;
}
Move = ;
while ( sec < size && a[sec] < a[fir])
{
++sec;
++Move;
}
Rotate(a + fir, sec - fir, sec - fir - Move);
fir += Move;
}
}

这样空间复杂度主要是Reverse中用到,为O(1).

In place Merge(原地归并)的更多相关文章

  1. [leetcode]56. Merge Intervals归并区间

    Given a collection of intervals, merge all overlapping intervals. Example 1: Input: [[1,3],[2,6],[8, ...

  2. 【原创】Algorithms:原地归并排序

    第一次归并: a[0] a[1] a[2] a[3] a[4] a[5] a[6] 23 8 19 33 15 6 27 ↑             ↑ i     j 最开始i指向a[0],j指向a ...

  3. 归并排序Java实现

    package practice; import edu.princeton.cs.algs4.*; /* * 归并排序 * 时间复杂度O(NlgN) N为数组长度 * 归并排序在小数组上表现并不好可 ...

  4. 算法(第四版)C# 习题题解——2.2

    写在前面 整个项目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csharp 查找更为方便的版本见:http ...

  5. C#版 - LeetCode 148. Sort List 解题报告(归并排序小结)

    leetcode 148. Sort List 提交网址: https://leetcode.com/problems/sort-list/  Total Accepted: 68702 Total ...

  6. 各种排序算法的总结、比较与Java实现

    1 快速排序(QuickSort) 快速排序是一个就地排序,分而治之,大规模递归的算法.从本质上来说,它是归并排序的就地版本.快速排序可以由下面四步组成. (1) 如果不多于1个数据,直接返回.(2) ...

  7. 选择排序、快速排序、归并排序、堆排序、快速排序实现及Sort()函数使用

    1.问题来源 在刷题是遇到字符串相关问题中使用 strcmp()函数. 在函数比较过程中有使用 排序函数 Sort(beg,end,comp),其中comp这一项理解不是很彻底. #include & ...

  8. 数据结构和算法(Golang实现)(23)排序算法-归并排序

    归并排序 归并排序是一种分治策略的排序算法.它是一种比较特殊的排序算法,通过递归地先使每个子序列有序,再将两个有序的序列进行合并成一个有序的序列. 归并排序首先由著名的现代计算机之父John_von_ ...

  9. 《算法 (第4版)》【PDF】下载

    <算法 (第4版)>[PDF]下载链接: https://u253469.ctfile.com/fs/253469-231196349 (第4版)>[PDF]"  TITL ...

随机推荐

  1. 1024: [SCOI2009]生日快乐 - BZOJ

    Description windy的生日到了,为了庆祝生日,他的朋友们帮他买了一个边长分别为 X 和 Y 的矩形蛋糕.现在包括windy,一共有 N 个人来分这块大蛋糕,要求每个人必须获得相同面积的蛋 ...

  2. java 取小数点后两位 不四舍五入,怎么做

    java 取小数点后两位 不四舍五入,怎么做 正常版: //正常版: import java.text.DecimalFormat; import java.math.RoundingMode; De ...

  3. 数据生成器Bogus的使用以及基于声明的扩展

    引言 最近在整理代码,发现以前写的一个数据填充器写了一半没实现,而偏偏这段时间就要用到类似的功能,所以正好实现下. 目标 这个工具的目标是能够在项目初期快速搭建一个"数据提供器", ...

  4. vim查看函数原型以及关闭窗口

    问题描述:         vim中查看函数原型,以及关闭vim窗口 问题解决:      (1)查看函数原型            使用Shift+K可以查看用户手册      (2)自定义函数   ...

  5. "Principles of Reactive Programming" 之<Actors are Distributed> (2)

    Actor Path 我们知道actor是有层级的(hierarchical),第.每个actor在它的父actor的名字空间下都有一个名字.这样就构成了一个树状的结构,就像是文件系统.每个actor ...

  6. 不定长内存池之apr_pool

    内存池可有效降低动态申请内存的次数,减少与内核态的交互,提升系统性能,减少内存碎片,增加内存空间使用率,避免内存泄漏的可能性,这么多的优点,没有理由不在系统中使用该技术. 内存池分类: 1.      ...

  7. Windows下如何使用BOOST C++库 .

    Windows下如何使用BOOST C++库 我采用的是VC8.0和boost_1_35_0.自己重新编译boost当然可以,但是我使用了 http://www.boostpro.com/produc ...

  8. Object-C中emoji与json的问题

    遇到一个问题,要储存iOS键盘输出的emoji表情到MySQL,我知道用blob+utf8是可以存的.但是现在我的这张表已经太大了,不可能去改类型.所以就想把emoji表情匹配出来,替换掉,再存.但是 ...

  9. hdu 1525 Euclid's Game 博弈论

    思路:两个数a和b,总会出现的一个局面是b,a%b,这是必然的,如果a>=b&&a<2*b,那么只有一种情况,直接到b,a%b.否则有多种情况. 对于a/b==1这种局面, ...

  10. ???????????? no permissions

    1.一手鞋地址 google http://developer.android.com/tools/device.html 我处理的方法如下: 我的问题: android的版卡 在Ubuntu12.0 ...