Files
Learn-Algorithms/9 Algorithms Job Interview/5.1 数列-排序.md
T
2021-11-27 02:15:19 +08:00

4.0 KiB
Raw Blame History

5.1 数列-排序

使用归并排序对一个 int 类型的数组排序

比如 [1, 6, 2, 2, 2, 3]

void sort(int * a, int length)

用递归的方法判断整数组a[N]是不是升序排列

递归 isAscend(n-1) && a[N-1]< a[N]

求一个数组的最长递减子序列

比如{9,4,3,2,5,4,3,2}的最长递减子序列为{9,5,4,3,2}

动态规划

扑克牌的顺子

从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。 2-10为数字本身,A为1,J为11,Q为12,K为13,而大小王可以看成任意数字。

对这5个数(大小王看做0) 1)排序,如快排 2)统计0的个数 3)统计相邻元素空缺总数

//5个是不是顺子
isShunZi(int *a,int length) 

分割数组

一个int数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。 能否只用一个额外数组和少量其它空间实现。

快速排序

调整数组顺序使奇数位于偶数前面

题目:输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分, 所有偶数位于数组的后半部分。要求时间复杂度为O(n)。

思路:两边向中间扫描,如果第一个指针是偶数,第二个指针是奇数,就交换;如果第一个是偶数,第二个也偶数,第二个指针向前移;反之,第一个指针向后移

void reorder(int *data, int length);

奇偶分离

给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数。 要求:空间复杂度O(1),时间复杂度为O(n) 如 [4,5,2,7,5] => [5,7,5,4,2], 空间复杂度O(1),得使用 交换排序

插入排序思想 快速排序思想

1-1000放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现一次. 每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间, 能否设计一个算法实现?

分析:难点在于 不用辅助空间。

思路一: sum(数组元素的总和)-sum(1~1000) 得到的差即为重复元素,N较大时注意总和溢出 思路二: 异或操作(位运算)

重新排列使负数排在正数前面

一个未排序整数数组,有正负数,重新排列使负数排在正数前面,并且要求不改变原来的正负数之间相对顺序

比如: input: 1,7,-5,9,-12,15 ans: -5,-12,1,7,9,15 要求时间复杂度O(N),空间O(1)。(此题一直没看到令我满意的答案,一般达不到题目所要求的:时间复杂度O(N),空间O(1),且保证原来正负数之间的相对位置不变)。

updated:设置一个起始点j, 一个翻转点k,一个终止点L 从右侧起 起始点在第一个出现的负数, 翻转点在起始点后第一个出现的正数,终止点在翻转点后出现的第一个负数(或结束) 如果无翻转点, 则不操作 如果有翻转点, 则待终止点出现后, 做翻转, 即ab => ba 这样的操作 翻转后, 负数串一定在左侧, 然后从负数串的右侧开始记录起始点, 继续往下找下一个翻转点

例子中的就是

1, 7, -5, 9, -12, 15
第一次翻转: 1, 7, -5, -12,9, 15 => 1, -12, -5, 7, 9, 15 第二次翻转: -5, -12, 1, 7, 9, 15

N维翻转空间占用为O(1)复杂度是2N;在有一个负数的情况下, 复杂度最大是2N, ;在有i个负数的情况下, 复杂度最大是2N+2i, 但是不会超过2N+N实际的复杂度在O(3N)以内 
但从最终时间复杂度分析,此方法是否真能达到O(N)的时间复杂度,还待后续考证。感谢John_Lv,MikovChain。2012.02.25。

1, 7, -5, -6, 9, -12, 15(后续:此种情况未能处理) 1 7 -5 -6 -12 9 15 1 -12 -5 -6 7 9 15 -6 -12 -5 1 7 9 15

更多请参考此文,程序员编程艺术第二十七章:重新排列数组(不改变相对顺序&时间O(N)&空间O(1),半年未被KO)http://blog.csdn.net/v_july_v/article/details/7329314。