递归笔试题

1、一个楼梯有20级,每次走1级或是2级,从底走到顶一共有多少中走法?
算法:
    设 n 是阶数,f(n) 是上 n 阶的不同走法数,则第一步可以走一阶或者是两阶,
    那么这三种情况下剩余的阶数分别为 n-1、n-2,
    所以 f(n) = f(n-1) + f(n-2)。

//递归解法
int solution1(int n)
{
    if(n == 0 || n == 1) return 1;
    else return solution1(n-1) + solution1(n-2);
}

//非递归解法
int f[100];
int solution2(int n)
{
    f[0] = 1;
    f[1] = 1;
    for(int i=2; i<=n; ++i)
      f[i] = f[i-1] + f[i-2];
    return f[n];
}

2、质因数分解:得到num的所有质因数

void prime_number(int num, int n)
{
    if(num > n)
    {
        while(num % n)  n++; //找到一个质因数
        num /= n; //除以这个质因数
        cout<<n<<endl; //打印这个质因数
        prime_number(num,n);
    }
}
int main()
{
    int n = 1001;
    prime_number(n,2);
    return 0;
}

3、不用任何中间变量,如何获取字符串的长度

int my_strlen(const char* str)
{
    if(*str == '\0') return 0;
    else return my_strlen(str+1)+1;
}

不用任何中间变量,以递归反序输出一个字符串:

void reverse(const char *p)
{
    if(*p == '\0') return;
    reverse(p+1);
    printf("%c",*p);
}

4、全排列和全组合

#include <iostream>
using namespace std;

template <class Type>
void permute(Type a[], int start, int end)
{
    if(start == end)
    {
        for(int i = 0; i <= end; ++i)
        {
            cout<<a[i]<<" ";
        }
        cout<<endl;
    }
    else
    {
        for(int i = start; i <= end; ++i)
        {
            swap(a[i],a[start]);
            permute(a,start+1,end);
            swap(a[i],a[start]);
        }
    }
}

template <class Type>
void combine(Type a[], bool b[], int start, int end)
{
    if(start > end)
    {
        for(int i = 0; i <= end; ++i)
        {
            if(b[i])
                cout<<a[i]<<" ";
        }
        cout<<endl;
    }
    else
    {
        b[start] = true;
        combine(a,b,start+1,end);
        b[start] = false;
        combine(a,b,start+1,end);
    }
}

int main()
{
    int p[3]={1,2,3};
    int N = 3;
    cout<<"permute:"<<endl;
    permute(p,0,N-1);
    cout<<"combine:"<<endl;
    bool b[3];
    combine(p,b,0,N-1);

    return 0;
}

全组合还有一个有趣的解法:可以构照一个长度为n(字符串的长度)的01字符串(或二进制数)表示输出结果中最否包含某个字符,比如:对于字符串“abc”,"001"表示输出结果中不含字符a、b,只含c,即输出结果为c,而"101",表示输出结果为ac。原题就是要求输出"001"到"111"这2^n–1个组合对应的字符串。
参考:http://www.cnblogs.com/luxiaoxun/archive/2012/08/08/2628153.html

5、给出一个集合,如{1, 2, 3, 4},打印出该集合的所有子集 分析一下问题,子集是指取原集合中的任意多个元素,转化一下问题,就是对于原集合中的任何一个元素,都有两个选择,包含或者不包含,所以对于n个元素的集合,其子集数为:2*2*2... = 2^n,去掉空集就是2^n-1个。那么可以得出其递归算法,本题实质上和打印字符串的所有组合是一样的。

void Recursive_Subsets(int* a, bool* b, int start, int end) 
{ 
    if(start <= end) 
    {
        b[start] = true; // pick the a[start]
        Recursive_Subsets(a, b, start+1, end); 

        b[start] = false; // not pick the a[start] 
        Recursive_Subsets(a, b, start+1, end); 
    } 
    else
    { 
        for(int i = 0; i <= end; i++) 
        { 
            if (b[i]) cout << a[i]; 
        } 
        cout << endl; 
    }
} 

void PrintAllSubsets(int* a, int n) 
{ 
    bool* b = new bool[n]; 
    Recursive_Subsets(a, b, 0, n-1); 
    delete b; 
}

6、电话号码对应的字符组合

题目:在电话或者手机上,一个数字如2对应着字母ABC,7对应着PQRS。那么数字串27所对应的字符的可能组合就有3*4=12种(如AP,BR等)。现在输入一个3到11位长的电话号码,请打印出这个电话号码所对应的字符的所有可能组合和组合数。

#include<iostream>
using namespace std;

const char* letter[10]={"","","ABC","DEF","GHI","JKL","MNO","PQRS","TUV","WXYZ"};
const int num[10]={0,0,3,3,3,3,3,4,3,4};
char input[20];
char output[20];

void solve(int p,int len)
{
    if(p == len)
    {
        output[len] = '\0';
        cout<<output<<endl;
        return;
    }
    int i;
    for(i=0; i<num[input[p]]; i++)
    {
        output[p] = letter[input[p]][i];
        solve(p+1,len);
    }
}

int main()
{
    scanf("%s",input);
    len = strlen(input);
    
    int total = 1;
    for(int i=0; i<len; i++) 
    {
        input[i] -= '0';
        total *= num[input[i]];
    }
    solve(0,len);

    cout<<"The total num of combination is "<<total<<endl;
    return 0;
}

7、Coin Chagne:硬币找零问题

硬币找零问题:给定一个正整数N,和一个正整数集合S,集合中的每个元素都有无限个,如何选定集合中的元素组合使其和为N For example, for N = 4, S = {1,2,3}, there are four solutions: {1,1,1,1},{1,1,2},{2,2},{1,3}.

递归解法:假设集合S中的元素的顺序是递增的,则: C(N,M),表示从M个元素选中若干个满足和为N的解法个数,则C(N,M)=C(N,M-1)+C(N-S[M-1],M-1)
C(N,M)=1, N=0
C(N,M)=0, N<0
C(N,M)=0, N>=1,M<=0

int Count(int N, int *s, int M)
{
    if(N == 0) return 1;
    if(N < 0) return 0;
    if(N >= 1 && M <= 0) return 0;
    return Count(N,s,M-1)+Count(N-s[M-1],s,M-1);
}

最少硬币找零问题:给定一个正整数N,和一个正整数集合S,集合中的每个元素都有无限个,如何选定最少的集合中元素,使其和为N For example, for N = 4, S = {1,2,3}, there are two solutions: {2,2},{1,3}.

递归解法:假设集合S中的元素的顺序是递增的,C(N,M),表示从M个元素选中若干个满足和为N的解法个数,则: C(N,M)=min(C(N,M-1),C(N-S[M-1],M-1))+1

int minCount(int N, int *s, int M)
{
    if(N == 0) return 1;
    if(N < 0) return 0;
    if(N >= 1 && M <= 0) return 0;
    return min(Count(N,s,M-1),Count(N-s[M-1],s,M-1))+1;
}

8、输入两个整数 n 和 m,从数列1,2,3...n 中随意取几个数,使其和等于m ,要求将其中所有的可能组合列出来。

解为:此题等同于整数分解问题,将m分解成n以内的解为:f(n,m),分解成两个子问题:f(n-1,m-n)和f(n-1,m)

vector<int> vec;
void find_factor(int sum, int n)
{
    if(n <= 0 || sum <= 0)
        return;
    if(sum == n)
    {
        for(vector<int>::iterator iter = vec.begin(); iter != vec.end(); iter++)
            cout << *iter << " + ";
        cout << n << endl;
    }
    vec.push_back(n);
    find_factor(sum-n, n-1);   //放n,n-1个数填满sum-n
    vec.pop_back();
    find_factor(sum, n-1);     //不放n,n-1个数填满sum
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 把一个链表反向,递归递归都写一遍。 1.试编写3个函数实现   (1)建立一个双向链表   (2)插入一个节点   (3)删除一个节点 2.自己定义数据结构,写出程序:二叉树的前序遍历。 3.实现双向链表删除一个节点P,在节点P后插入一个节点,写出这两个函数。 4.下面哪种排序法对12354最快 a quick sort b.buble sort c.merge sort 5.哪种结构,平均来讲,获取一个值最快 a. binary tree b. hash table c. stack 6.一个二叉树的三种遍历方法的输出结果 7.链表按升序打印每打印完一个节点就将该节点从链表中删除 8.选择一种算法来整理出一个链接表。你为什么要选择这种方法?现在用o(n)时间来做。 9. 用一种算法在一个循环的链接表里插入一个节点,但不得穿越链接表。    10.给两个变量,如何找出一个带环单链表中是什么地方出现环的? 11.哈希表和数组的定义,区别,优缺点。 12.链接表和数组之间的区别是什么? 任选一门语言,当场定义二叉排序树数据结构,写出两个函数:初始化,删除一个节点,20分钟 13. 递归的折半查找算法[不限语言] 14. 解释一下什么是B+树,如何实现B+树的查找和插入.(用图示) 15.实现双向链表删除一个节点P,在节点P后插入一个节点,写出这两个函数。 13.排序方法比较 (intel) 排序方法 平均时间 最坏时间 辅助存储 直接插入排序 O(N2) O(N2) O(1) 起泡排序 O(N2) O(N2) O(1) 快速排序 O(Nlog2N) O(N2) O(Nlog2N) 简单选择排序 O(N2) O(N2) O(1) 堆排序 O(Nlog2N) O(Nlog2N) O(1) 归并排序 O(Nlog2N) O(Nlog2N) O(n) 基数排序 O(d(n+radix)) O(d(n+radix)) O(radix) 17.一个链表的操作,注意代码的健壮和安全性。要求: (1)增加一个元素; (2)获得头元素; (3)弹出头元素(获得值并删除)。 18.内排序算法 19.折半查找的复杂度,证明 20.sizeof()和strlen()的使用. 21.顺序存储结构的优点,散列法的思想是什么? 22.汉罗塔算法,不能递归... 23.一个链表的结点结构 struct Node { int data ; Node *next ; }; typedef struct Node Node ; (1)已知链表的头结点head,写一个函数把这个链表逆序 ( Intel) (2)已知两个链表head1 和head2 各自有序,请把它们合并成一个链表 依然有序。 (3)已知两个链表head1 和head2 各自有序,请把它们合并成一个链表 依然有序,这次要求用递归方法进行。 ( Autodesk) 24.编最优化Bubble(int *pIntArray,int L),要求:交换元素不能用临时变量,如果有序需要最优。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值