递归设计经验
1.找重复(分析问题,将问题转化成子问题,可以尝试“切蛋糕”的方法。子问题与原问题具有相同的形式,可以由一到多,例如T8汉诺塔,即将原问题化为多个子问题)
2.找重复中的变化量(需要传递到函数中的参数)
3.找出口(递归结束的点,参数变化到何值时可以结束)
注意:如果涉及的递归函数有返回值,函数中调用自身的那一行需要加一个return ,不然就算在后一层在出口位置返回了,也无法返回到最初的调用递归函数的位置,也就是没有返回值。在下面的T11在有空字符串的有序字符串数组中查找某一字符串(非空)中,可以体现这一点。但是如果不加return不报错,而且返回值一直是1,暂时还不知道这是为什么。
贴几个简单的递归例题训练递归思想。
T1 阶乘 O(1)+O(n-1)=O(1)+O(1)+O(n-2)...=O(n)
int factorial(int n)
{
if(n == 2)
return 2;
else
return n * factorial(n - 1);
}
T2 打印i-j O(j-i)
void printi2j(int i,int j)
{
if(i>j)
{
cout<<i<<endl;
printi2j(i-1,j);
}
else if(i<j)
{
cout<<i<<endl;
printi2j(i+1,j);
}
else
{
cout<<i;
return;
}
}
T3 数组求和 O(1)+O(n-1)=O(1)+O(1)+O(n-2)...=O(n)
int sumArray(int *arr,int n)
{
if(n == 0)
return 0;
else
return arr[n-1] + sumArray(arr,n-1);
}
T4 翻转字符串 O(1)+O(n-1)=O(1)+O(1)+O(n-2)...=O(n)
string reverseString(string str,int end)
{
if(end == 0)
return "";
return str[end-1]+reverseString(str,end-1);
}
T5 斐波那契数列 O(n-1)+O(n-2)+O(1)=2O(n-1)+O(1)=2(2O(n-2)+O(1))+O(1)... = O(2^n)
int Fibonacci(int n)
{
if(n ==1 || n == 2)
return 1;
else
return Fibonacci(n-1) + Fibonacci(n-2);
}
T6 辗转相除法 m%n < m/2 n%(m%n) < n/2 每迭代两次n减半,迭代k次,n变为n/2^(k/2)趋近于1时,有O(log n)
int division(int m,int n)
{
if(n == 0)
return m;
else
division(n,m%n);
}
T7 插入排序改递归 O(n-1)+O(n)=O(n-2)+O(n)+O(n)...=O(n^2)
void insertSort_recursive(int arr[],int length)
{
if(length == 0)
return;
insertSort_recursive(arr,length-1);
int x = arr[length];
int index = length-1;
while(index>-1 && x<arr[index])
{
arr[index+1] = arr[index];
index--;
}
arr[index+1] = x;
}
T8 汉诺塔(分三步,1-n从from到to,help辅助)
void hanoiTower(int n,string from,string to,string help)
{
if(n == 1)
{
cout<<"move "<<n<<" from "<<from<<" to "<<to<<endl;
return;
}
else
{
hanoiTower(n-1,from,help,to);//1到n-1从from到help,to辅助
cout<<"move "<<n<<" from "<<from<<" to "<<to<<endl;//n从from到to
hanoiTower(n-1,help,to,from);//1到n-1从help到to,from辅助
}
}
T9 爬楼梯 ,n阶台阶,每次爬1/2/3阶,求多少种爬楼梯方式
int upStairs(int n)
{
if(n == 0)
return 0;
if(n == 1)
return 1;
if(n == 2)
return 2;
if(n == 3)
return 4;
else
return upStairs(n-1) + upStairs(n-2) + upStairs(n-3);
}
T10 旋转数组的最小数字
int rotateArray(int arr[],int low,int high)
{
int mid;
mid = low + ((high - low) >> 1);
if(arr[low] == arr[mid] && arr[mid] == arr[high])//解决a[] = {4,3,4,4,4};
{
int min = arr[low];
for(int i=low+1;i<=high;i++)
{
if(arr[i]<min)
min = arr[i];
}
return min;
}
else if(arr[low] < arr[high])
return arr[low];
else if(low + 1 == high)
return arr[high];
else
{
if(arr[low] <= arr[mid])
rotateArray(arr,mid,high);
else
rotateArray(arr,low,mid);
}
}
T11 在有空字符串的有序字符串数组中查找某一字符串(非空)
int searchString(string arr[],int low,int high,string s)
{
if(low == high)
{
//cout<<"????"<<endl;
return -1;
}
else
{
int mid = low + ((high - low) >> 1);
//cout<<"mid = "<<mid<<endl;
while(arr[mid] == "")
{
mid++;
//cout<<mid<<endl;
if(mid > high)
return -1;
else
continue;
}
if(arr[mid] < s)
{
//cout<<"111111\t"<<mid<<endl;
return searchString(arr,mid+1,high,s);
}
else if(arr[mid] > s)
{
//cout<<"222222\t"<<mid<<endl;
return searchString(arr,low,mid-1,s);
}
else
{
//cout<<mid;
return mid;
}
}
}