4.0 KiB
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。