一:全排列问题
题目:输入一个字符串,打印出该字符串中字符的所有排列。
例如输入字符串abc,则输出由字符a、b、c 所能排列出来的所有字符串:abc、acb、bac、bca、cab 和cba。
1:递归算法
从集合中依次选出每一个元素,作为排列的第一个元素,然后对剩余的元素进行全排列,如此递归处理,从而得到所有元素的全排列。
代码:
void Permutation(char * pStr, char * pBegin)
{
if(!pStr || !pBegin)
return;
char *pCh = NULL;
if(*pBegin == '\0')
{
printf("%s\n", pStr);
}
else
{
for(pCh = pBegin; *pCh != '\0'; ++ pCh)
{
char temp = *pCh;
*pCh = *pBegin;
*pBegin = temp;
Permutation(pStr,pBegin + 1);
temp = *pCh;
*pCh = *pBegin;
*pBegin = temp;
}
}
}
2:非递归算法
基本思想是:
a:对原始队列进行排序,找到所有排列中最小的一个排列Pmin。
b:找到刚刚好比Pmin大比其它都小的排列P(min+1)。
c:循环执行第二步,直到找到一个最大的排列,算法结束。
那么如何计算比当前队列更大一点的排列呢?只要对字符串反复求出下一个排列,全排列的也就迎刃而解了。如"1234"的下一个排列就是"1243"。
举个例子,来考虑"926520"这个字符串,我们从后向前找第一对相邻的递增数字,"20"、"52"、"65"都是递减的,"26"即满足要求,称前一个数字2为替换数,替换数的下标称为替换点。
替换点之后的数都是递减排序的,这样,替换点之后的数已经是最大的数了(6520)。此时,再从最后开始往前,找第一个比替换数大的数。0、2都不行,5可以,将5和2交换得到"956220",此时,替换点上的数已经换成了比2稍大一点的5,替换点之后的数依然是递减排列的。这样,将替换点后的字符串"6220"颠倒即得到"950226"。这就是"926520"下一排列。
上述的思想,参见”26520”这个数,”6520”已经递减排列,也就是最大的4位数了。目前的最高位是2,所以,要想找一个比”26520”还大的数,就要找到比2还大的最高位,所以从后往前找,找到了5,交换2和5,此时变成了56220,替换点之后的数依然是递减排列的:5之后的数是6220,同样是最大的4位数了,只要反转,变成0226就成了最小的数了。
代码如下:
void nocur_permutation(char *a,int length)
{
if(length<2) return;
quicksort(a,0, length-1); //先进行排序,求得最小排列
while(1)
{
printall(a,length); //打印当前队列
int i,j;
for(i=length-2; i>=0; --i) //找到替换点
{
if(a[i]<a[i+1])break;
else if(i==0) return;
}
for(j=length-1;j>i; --j) //从后往前找第一个比替换数大的数
{
if(a[j]>a[i])break;
}
swap(a,i,j); //交换替换点
reverse(a,i+1,length-1); //反转替换点之后的数
}
}
二:跳台阶问题
题目:一个台阶总共有n 级,如果一次可以跳1 级,也可以跳2 级。求总共有多少总跳法,并分析算法的时间复杂度。
首先考虑最简单的情况。如果只有1级台阶,那显然只有一种跳法。如果有2级台阶,那就有两种跳的方法了:一种是分两次跳,每次跳1级;另外一种就是一次跳2级。
现在我们再来讨论一般情况。我们把n级台阶时的跳法看成是n的函数,记为f(n)。当n>2时,第一次跳的时候就有两种不同的选择:一是第一次只跳 1级,此时跳法数目等于后面剩下的n-1级台阶的跳法数目,即为f(n-1);另外一种选择是第一次跳2级,此时跳法数目等于后面剩下的n-2级台阶的跳 法数目,即为f(n-2)。因此n级台阶时的不同跳法的总数f(n)=f(n-1)+(f-2)。
/ 1 n=1
f(n)= 2 n=2
\ f(n-1) +f(n-2) n>2
这样上述问题就是平常所熟知的Fibonacci数列问题。
三:奇偶排序问题
问题描述:输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。要求时间复杂度为O(n)。
分析:维护两个指针,一个指针指向数组的第一个数字,向后移动;一个指针指向最后一个数字,向前移动。如果第一个指针指向的数字是偶数而第二个指针指向的数字是奇数,我们就交换这两个数字。
代码实现:
while(pBegin < pEnd)
{
if(!isEven(*pBegin))
{
pBegin ++;
continue;
}
if(isEven (*pEnd))
{
pEnd --;
continue;
}
int temp = *pBegin;
*pBegin = *pEnd;
*pEnd = temp;
}
(http://blog.csdn.net/v_july_v/article/details/6879101)
(http://www.cnblogs.com/bakari/archive/2012/08/02/2620826.html)
(http://blog.csdn.net/e3399/article/details/7543861)