有关循环、递归与概率 的面试题

递归是程序设计中的一种算法。

有些数据结构(如二叉树),其自身就有递归的性质,有些问题其自身没有明显递归结构,单用递归求解更简单。

递归算法具有天生的低效率问题。

1.一个射击运动员打靶,靶一共10环,连开10枪打中90环的可能性有多少种?递归编程实现。

   代码:

#include<iostream>
using namespace std;
int sum; //统计次数
int store[10];//记录十次打靶得分
void Output(){
  for(int i=9;i>=0;i--){
    cout<<store[i]<<" ";    //输出每一种可能
  }
  cout<<endl;
  ++sum;
}

void Comput(int score,int num){
   if(score<0||score>(num+1)*10)//次数unm为0~9 出现这种情况,即便后面每枪10环也不能满足就退出递归
       return;
   if(num==0){
    store[num]=score;
    Output();
    return;
   }
   for(int i=0;i<=10;i++){    //每靶10环
    store[num]=i;
    Comput(score-i,num-1);
   }
}
int main(){
    Comput(90,9);
    cout<<"总数:"<<sum<<endl;
    return 0;
}

 2.八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。在国际象棋盘上排放八个皇后使其不能相互攻击,即任意两个皇后都不能处于同一行,同一列或同一斜线上,问有多少种摆法。

一种8皇后的摆法:

0 0 0 0 0 0 0 1

0 0 0 1 0 0 0 0

1 0 0 0 0 0 0 0

0 0 1 0 0 0 0 0

0 0 0 0 0 1 0 0

0 1 0 0 0 0 0 0

0 0 0 0 0 0 1 0

0 0 0 0 1 0 0 0

#include<stdio.h>
//#include<memory.h>
static int Queen[8][8];
static int a[8]; //标记列冲突
static int b[15]; //标记主对角线冲突  b[i-j+7]
static int c[15]; //标记从对角线冲突  c[i+j]

static int QueenNum=0;//记录总的棋盘状态数
void qu(int i); //参数i代表行

int main()
{
   //初始化棋盘 为0 放置棋子的位置为1
   for(int i=0;i<8;i++){
    a[i]=0; //初始化标记
    for(int j=0;j<8;j++){
    Queen[i][j]=0;
    }
   }

   for(int i=0;i<15;i++){
    b[i]=0;
   }
   qu(0);
   return 0;
}

void qu(int i){
    for(int iColum=0;iColum<8;iColum++){
      if(a[iColum]==0&&b[i-iColum+7]==0&&c[i+iColum]==0)
            //无冲突
      {
          Queen[i][iColum]=1;
          a[iColum]=1;    //标记,下一次该列上不能放
          b[i-iColum+7]=1; //标记,下一次该主对角线上不能放
          c[i+iColum]=1;   //标记,下一次该从对角线上不能放
          if(i<7)qu(i+1);
          else{
            //输出棋盘状态
            int iLine,iColum;
            printf("第%d种状态为:\n",++QueenNum);
            for(iLine=0;iLine<8;iLine++){
                for(iColum=0;iColum<8;iColum++){
                    printf("%d ",Queen[iLine][iColum]);
                }
                printf("\n");
            }
            printf("\n\n");
          }
          //如果前次皇后的放置导致后面的放置无论如何都不能满足,则回溯
          Queen[i][iColum]=0;
          a[iColum]=0;
          b[i-iColum+7]=0;
          c[i+iColum]=0;
      }
    }
}

3.编写一个程序,把字符串中的所有字符子串的各种组合形式都显示出来,顺序不同字母相同的看作一种组合。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int sum=0;
char str[]="hart";  //待分解字符串
int length;         //字符串长度
char *out;          //结果字符串

void DoCombine(char in[],char out[],int length,int rec,int start){  
   int i;
   for(i=start;i<length;i++){
    out[rec]=in[i];
    out[rec+1]=0;
    printf("%s\n",out);
    if(i<length-1)
        DoCombine(in,out,length,rec+1,i+1);
   }
}
int main(){
   length=strlen(str);
   out=(char*)malloc(length+1);
   DoCombine(str,out,length,0,0);
   return 0;
}

 4.0-1背包问题

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

#include<iostream>
#include<cstring>
using namespace std;
int mVal,nVal;   //mVal是目标容量 n是物品最大重量
int *pOut;

void calFun(int m,int n){
  if(m<1||n<1||(n==1&&m!=1))
    return;   //递归出口
  if(m==n){
    pOut[n]=1;
    for(int i=1;i<=nVal;++i){
        if(pOut[i]){
            cout<<i<<" ";
        }
    }
    cout<<endl;
    pOut[n]=0;
  }
  calFun(m,n-1);  //不取n
  pOut[n]=1;
  calFun(m-n,n-1); //取n
  pOut[n]=0;

}
int main(){
  cout<<"m=:";
  cin>>mVal;
  cout<<"n=:";
  cin>>nVal;
  if(mVal<nVal)nVal=mVal;  //比较n,m哪个大 因为n>m的话n与m之间的数是没有意义的
  pOut=new int[nVal+1];
  memset(pOut,0,(nVal+1)*sizeof(int));
  calFun(mVal,nVal);
  delete []pOut;
  return 0;

}

概率:

5.给出下面程序的输出

#include<stdlib.h>
#include<stdio.h>
#define LOOP 1000
int mian(){
   int rgnC=0;
  for(int i=0;i<LOOP;i++){
     int x=rand();
     int y=rand();
     if(x*x+y*y<RAND_MAX*RAND_MAX)rgnC++;
  }
  printf("%d\n",rgnC);
  return 0;
}

 RAND_MAX是随机数中的最大值,也就相当于圆的最大半径R,x和y是某点的横纵坐标,他们的平方和就是到原点的距离,上诉问题就退化成随机正方形里落1000个点,落在半径里面的点有多少个。

求落点可能性之比就是求一个1/4圆面积和一个正方形面积之比。

1/4圆的面积:(1/4)*π*r*r

正方形的面积:r*r

两者之比:π/4≈785

转载于:https://www.cnblogs.com/junglefish/p/5468888.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值