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。