C++面试题

来源:互联网 发布:比特币源码编译 编辑:程序博客网 时间:2024/06/02 05:50

1. 一个台阶总共有n级,如果一次可以跳1级,也可以跳2级。求总共有多少总跳法?

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /*********************************************************************** 
  2. 题目:一个台阶总共有n级,如果一次可以跳1级,也可以跳2级。 
  3. 求总共有多少总跳法。 
  4. 分析:首先我们考虑最简单的情况。如果只有1级台阶,那显然只有一种跳法。 
  5. 如果有2级台阶,那就有两种跳的方法了:一种是分两次跳,每次跳1级; 
  6. 另外一种就是一次跳2级。 
  7. 现在我们再来讨论一般情况。我们把n级台阶时的跳法看成是n的函数,记为f(n)。 
  8. 当 n=1 时有 1 种跳法;当 n=2 时有 2 种跳法; 
  9. 当n>2时,第一次跳的时候就有两种不同的选择: 
  10. 一是第一次只跳1级,此时跳法数目等于后面剩下的n-1级台阶的跳法数目, 
  11. 即为f(n-1);另外一种选择是第一次跳2级,此时跳法数目等于后面剩下的n-2级 
  12. 台阶的跳法数目,即为f(n-2)。 
  13. 因此n级台阶时的不同跳法的总数f(n)=f(n-1)+ f(n-2)。 
  14. ***********************************************************************/  
  15.   
  16.   
  17. #include <iostream>  
  18. using namespace std;  
  19.   
  20. int f(int n)  
  21. {  
  22.     if(n < 1)  
  23.     {  
  24.         cout<<"台阶数至少为1!"<<endl;  
  25.         return -1;  
  26.     }  
  27.     if(1 == n)  
  28.         return 1;  
  29.     if(2 == n)  
  30.         return 2;   
  31.     return f(n-1) + f(n-2);  
  32. }  
  33.   
  34. int main()  
  35. {  
  36.     int num;  
  37.     cout<<"请输入台阶数: ";  
  38.     cin>>num;  
  39.     cout<<"共有 "<<f(num)<<" 种跳法."<<endl;  
  40.     return 0;  
  41. }  



2. 求子数组的最大和

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /************************************************************************  
  2. 题目: 输入一个整形数组,数组里有正数也有负数。   
  3. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。   
  4. 求所有子数组的和的最大值。要求时间复杂度为O(n)。   
  5. 例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5, 和最大的子数组为3, 10, -4, 7, 2,   
  6. 因此输出为该子数组的和18。  
  7. ************************************************************************/    
  8. #include <iostream>    
  9. using namespace std;    
  10.     
  11. int getMaxSubArraySum(int R[],int n);    
  12.     
  13. int main()    
  14. {    
  15.     int arr[8] = {1,-2,3,10,-4,7,2,-5};    
  16.     
  17.     int maxSubSum = getMaxSubArraySum(arr,8);    
  18.     
  19.     cout<<maxSubSum<<endl;    
  20.     
  21.     return 0;    
  22. }    
  23.     
  24. int getMaxSubArraySum(int R[],int n)    
  25. {    
  26.     int maxSumValue = 0;//结果    
  27.     int subArraySumValue = 0;//累加和    
  28.     int max = R[0];//保存数组中的最大值    
  29.     for(int i=0;i<n;++i)    
  30.     {    
  31.         subArraySumValue += R[i];    
  32.         if(subArraySumValue < 0)    
  33.         {    
  34.             subArraySumValue = 0;    
  35.         }    
  36.         if(subArraySumValue > maxSumValue)    
  37.         {    
  38.             maxSumValue = subArraySumValue;    
  39.         }    
  40.         if(max < R[i])    
  41.         {    
  42.             max = R[i];    
  43.         }    
  44.     }    
  45.     if(max < 0)    
  46.     {    
  47.         //若数组中所有的数都为负数,则返回最大的一个数    
  48.         return max;    
  49.     }    
  50.     return maxSumValue;    
  51. }    


3. 将二元查找树变成排序的双向链表

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /**********************************************************  
  2. 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。  
  3. 要求: 不能创建任何新的结点,只能调整指针的指向。  
  4. **********************************************************/   

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /**********************************************************  
  2. 思路: 1.构造二叉查找树; 2.中序遍历二叉查找树;   
  3. 3.将访问到的结点调整为双向链表。  
  4. **********************************************************/    
  5.     
  6. //测试程序    
  7. #include <iostream>    
  8. using namespace std;    
  9.     
  10. //定义二元查找树结点的数据结构    
  11. struct BSTreeNode    
  12. {    
  13.     int m_value;    
  14.     BSTreeNode *m_pLeft;    
  15.     BSTreeNode *m_pRight;    
  16. };    
  17.     
  18. BSTreeNode *pHead = NULL;    
  19. BSTreeNode *pIndex = NULL;//指向前一个结点    
  20.     
  21. //建立二叉排序树    
  22. void addBSTreeNode(BSTreeNode *&pCurrent, int val);    
  23. //中序遍历,同时调整结点指针    
  24. void inOrderBSTreeNode(BSTreeNode *pNode);    
  25. //调整结点指针    
  26. void convert2DoubleLinkedList(BSTreeNode *pCurrent);    
  27.     
  28. int main()    
  29. {    
  30.     BSTreeNode *pRoot = NULL;    
  31.     addBSTreeNode(pRoot,10);    
  32.     addBSTreeNode(pRoot,6);    
  33.     addBSTreeNode(pRoot,14);    
  34.     addBSTreeNode(pRoot,4);    
  35.     addBSTreeNode(pRoot,8);    
  36.     addBSTreeNode(pRoot,12);    
  37.     addBSTreeNode(pRoot,16);    
  38.     inOrderBSTreeNode(pRoot);    
  39.     return 0;    
  40. }    
  41.     
  42.     
  43. void addBSTreeNode(BSTreeNode *&pCurrent, int val)    
  44. {    
  45.     if(NULL == pCurrent)    
  46.     {    
  47.         BSTreeNode *pNode = new BSTreeNode();    
  48.         pNode->m_value = val;    
  49.         pNode->m_pLeft = NULL;    
  50.         pNode->m_pRight = NULL;    
  51.         pCurrent = pNode;    
  52.     }    
  53.     else    
  54.     {    
  55.         if(pCurrent->m_value < val)    
  56.         {    
  57.             addBSTreeNode(pCurrent->m_pRight,val);    
  58.         }    
  59.         else if(pCurrent->m_value > val)    
  60.         {    
  61.             addBSTreeNode(pCurrent->m_pLeft,val);    
  62.         }    
  63.         else    
  64.         {    
  65.             cout<<"Node repeated!!!"<<endl;    
  66.         }    
  67.     }    
  68. }    
  69. void inOrderBSTreeNode(BSTreeNode *pNode)    
  70. {    
  71.     if(NULL == pNode)    
  72.     {    
  73.         return;    
  74.     }    
  75.     if(NULL != pNode->m_pLeft)    
  76.     {    
  77.         inOrderBSTreeNode(pNode->m_pLeft);    
  78.     }    
  79.     convert2DoubleLinkedList(pNode);    
  80.     if(NULL != pNode->m_pRight)    
  81.     {    
  82.         inOrderBSTreeNode(pNode->m_pRight);    
  83.     }    
  84. }    
  85. void convert2DoubleLinkedList(BSTreeNode *pCurrent)    
  86. {    
  87.     //使当前结点的左指针指向双向链表中的最后一个结点    
  88.     pCurrent->m_pLeft = pIndex;    
  89.     if(NULL == pIndex)//双向链表尚未建立    
  90.     {    
  91.         pHead = pCurrent;    
  92.     }    
  93.     else    
  94.     {    
  95.         pIndex->m_pRight = pCurrent;    
  96.     }    
  97.     pIndex = pCurrent;    
  98.     cout<<pCurrent->m_value<<" ";    
  99. }    

4. 找出数组中唯一出现2次的数

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /***********************************************************************  
  2. 题目: 假设你有一个用1001个整数组成的数组,这些整数是任意排列的,  
  3. 但是你知道所有的整数都在1到1000(包括1000)之间。  
  4. 此外,除一个数字出现两次外,其他所有数字只出现一次。  
  5. 假设你只能对这个数组做一次处理,用一种算法找出重复的那个数字。  
  6. 如果你在运算中使用了辅助的存储方式,那么你能找到不用这种方式的算法吗?  
  7. ***********************************************************************/    
  8.     
  9. /***********************************************************************  
  10. 思路: (1001个数异或结果)与(1-1000异或的结果)再做异或,即可。   
  11. 原理: 设重复数为A, 其余999个数异或结果为B。   
  12. 1001个数异或结果为A^A^B, 1-1000异或结果为A^B。  
  13. 由于异或满足交换律和结合律, 且X^X = 0, 0^X = X;   
  14. 则有(A^B)^(A^A^B)=A^B^B=A   
  15. ***********************************************************************/    
  16.     
  17. //测试程序    
  18. #include <iostream>    
  19. using namespace std;    
  20.     
  21. void showRepeated(int R[],int n);    
  22.     
  23. int main()    
  24. {    
  25.     int a[] = {5,2,4,3,4,1,6};      
  26.     showRepeated(a,6);    
  27.     return 0;    
  28. }    
  29.     
  30. void showRepeated(int R[],int n)    
  31. {    
  32.     int result = 0;    
  33.     for(int i=0;i<=n;++i)    
  34.     {    
  35.         result ^= R[i];    
  36.     }    
  37.     for(int i=1;i<=n;++i)    
  38.     {    
  39.         result ^= i;    
  40.     }    
  41.     cout<<"result = "<<result<<endl;    
  42. }    

5. 输入一个数,判断它是不是回文数

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //输入一个数,判断它是不是回文数。    
  2. #include <iostream>    
  3. using namespace std;    
  4.     
  5. bool isPalindromicNumber(int x);    
  6.     
  7. int main()    
  8. {    
  9.     int x = 0;    
  10.     cout<<"Please input a number:";    
  11.     cin>>x;    
  12.     if(isPalindromicNumber(x))    
  13.         cout<<x<<"是回文数."<<endl;    
  14.     else    
  15.         cout<<x<<"不是回文数."<<endl;    
  16.     return 0;    
  17. }    
  18.     
  19. bool isPalindromicNumber(int x)    
  20. {    
  21.     int y = 0;    
  22.     int result = 0;    
  23.     int temp = x;    
  24.     while(x!=0){        
  25.         y = x%10;    
  26.         x /= 10;    
  27.         result = result*10+y;    
  28.     }    
  29.     if(result==temp)    
  30.         return true;    
  31.     else     
  32.         return false;    
  33. }    


6. 编写一个程序,计算一个字符串中子串出现的次数

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>    
  2. #include <string.h>    
  3. int getCount(char* str,char* substr)    
  4. {    
  5.     int i=0,j=0,count=0;    
  6.     while(*(str+i)){    
  7.         if(*(str+i)==*(substr+j)){    
  8.             i++;    
  9.             j++;    
  10.         }    
  11.         else{    
  12.             if(j==0)    
  13.                 i++;    
  14.             else    
  15.                 j = 0;    
  16.         }    
  17.         if(j==strlen(substr)){    
  18.             count++;    
  19.             j = 0;    
  20.         }    
  21.     }    
  22.     return count;    
  23. }    
  24. int main()    
  25. {    
  26.     char* str = "HHiHelloHHioHhiHrlHIodHioplloHHii";    
  27.     char* substr = "Hi";    
  28.     int count = getCount(str,substr);    
  29.     printf("子串出现的次数:%d\n",count);    
  30.     return 0;    
  31. }    


7. 求1~1000之间的完全数

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //如果一个数恰好等于它的真因子之和,则称该数为“完全数”。    
  2. //根据完全数的定义,先计算所选取的整数num的真因子,将各因子累加于sum,若sum等于num,则num为完全数。    
  3. #include <iostream>    
  4. using namespace std;    
  5.     
  6. bool isWanQuanShu(int num);//判断num是否为完全数    
  7.         
  8. int main(){    
  9.     for(int i=2;i<1000;i++){    
  10.         if(isWanQuanShu(i)){    
  11.             cout<<i<<" ";    
  12.         }    
  13.     }    
  14.     cout<<endl;    
  15.     return 0;    
  16. }    
  17.     
  18. bool isWanQuanShu(int num){    
  19.     int sum = 0;    
  20.     for(int i=1;i<=num/2;i++)    
  21.         if(num%i == 0)    
  22.             sum += i;    
  23.     if(sum == num)    
  24.         return true;    
  25.     else    
  26.         return false;    
  27. }    


8. 求1+2+…+n

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /**********************************************************  
  2. 题目: 求1+2+…+n  
  3. 要求: 不能使用乘除法、for、while、if、else、switch、case  
  4. 等关键字以及条件判断语句(A?B:C)  
  5. **********************************************************/    
  6.     
  7. /**********************************************************  
  8. 思路: 定义一个类,我们new一个含有n个这种类型元素的数组,那么该类  
  9. 的构造函数将会被调用n次。可以将需要执行的代码放到构造函数里。  
  10. **********************************************************/    
  11. #include <iostream>    
  12. using namespace std;    
  13.     
  14. class Temp    
  15. {    
  16. public:    
  17.     Temp()    
  18.     {    
  19.         ++m_n;    
  20.         m_sum += m_n;    
  21.     }    
  22.     static void Reset(){m_n = 0; m_sum = 0;}    
  23.     static int getSum(){return m_sum;}    
  24. private:    
  25.     static int m_n;    
  26.     static int m_sum;    
  27. };    
  28.     
  29. int Temp::m_n = 0;    
  30. int Temp::m_sum = 0;    
  31.     
  32. int Sum(int n)    
  33. {    
  34.     Temp::Reset();    
  35.     Temp *tmp = new Temp[n];    
  36.     delete[] tmp;    
  37.     tmp = NULL;    
  38.     return Temp::getSum();    
  39. }    
  40.     
  41. int main()    
  42. {    
  43.     cout<<Sum(100)<<endl;    
  44.     return 0;    
  45. }    

9. 输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /**************************************************************  
  2. 题目:输入一个已经按升序排序过的数组和一个数字, 在数组中查找两个数,  
  3. 使得它们的和正好是输入的那个数字。 要求时间复杂度是O(n)。如果有多对  
  4. 数字的和等于输入的数字,输出任意一对即可。   
  5. 例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。  
  6. **************************************************************/    
  7.     
  8. #include <iostream>    
  9. using namespace std;    
  10.     
  11. void find(int R[],int n,int sum);    
  12.     
  13. int main()    
  14. {    
  15.     int arr[6] = {1,2,4,7,11,15};    
  16.     int sum = 15;    
  17.     find(arr,6,sum);    
  18.     return 0;    
  19. }    
  20.     
  21. void find(int R[],int n,int sum)    
  22. {    
  23.     int i=0;    
  24.     int j=n-1;    
  25.     while(i < j)    
  26.     {    
  27.         if(R[i]+R[j] == sum)    
  28.         {    
  29.             cout<<sum<<" = "<<R[i]<<" + "<<R[j]<<endl;    
  30.             return;    
  31.         }    
  32.         R[i]+R[j]<sum ? ++i : --j;    
  33.     }    
  34.     cout<<"Cannot find!"<<endl;    
  35. }    

10. 约瑟夫环

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /****************************************************************************  
  2. 题目:n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字  
  3. (第一个为当前数字本身,第二个为当前数字的下一个数字)。当一个数字删除后,从被删除  
  4. 数字的下一个继续删除第m个数字。求出在这个圆圈中剩下的最后一个数字。   
  5.   
  6. 分析:既然题目有一个数字圆圈,很自然的想法是我们用一个数据结构来模拟这个圆圈。  
  7. 在常用的数据结构中,我们很容易想到用环形列表。我们可以创建一个总共有m个数字的环形列表,  
  8. 然后每次从这个列表中删除第m个元素。 我们用STL中std::list来模拟这个环形列表。  
  9. 由于list并不是一个环形的结构,因此每次跌代器扫描到列表末尾的时候,  
  10. 要记得把跌代器移到列表的头部。这样就是按照一个圆圈的顺序来遍历这个列表了。  
  11.   
  12. 这种思路需要一个有n个结点的环形列表来模拟这个删除的过程,因此内存开销为O(n)。  
  13. 而且这种方法每删除一个数字需要m步运算,总共有n个数字,因此总的时间复杂度是O(mn)。  
  14. ****************************************************************************/    
  15.     
  16.     
  17. #include <iostream>    
  18. using namespace std;    
  19. #include <list>    
  20.     
  21. int getLastNumber(list<int> numList,unsigned m);    
  22.     
  23. int main()    
  24. {    
  25.     list<int> numList;    
  26.     unsigned n;    
  27.     unsigned m;    
  28.     cout<<"请输入n:";    
  29.     cin>>n;    
  30.     cout<<"请输入m:";    
  31.     cin>>m;    
  32.     if(n<1 || m<1)    
  33.     {    
  34.         cout<<"\n输入有误!\n"<<endl;    
  35.         return -1;    
  36.     }    
  37.             
  38.     for(unsigned i=0;i<n;++i)    
  39.         numList.push_back(i);    
  40.     cout<<"Last Number: "<<getLastNumber(numList,m)<<endl;    
  41.     
  42.     return 0;    
  43. }    
  44.     
  45. int getLastNumber(list<int> numList, unsigned m)    
  46. {    
  47.     list<int>::iterator currentIter = numList.begin();    
  48.     list<int>::iterator nextIter;    
  49.         
  50.     while(numList.size() > 1)    
  51.     {    
  52.         for(unsigned i=1;i<m;++i)    
  53.         {    
  54.             ++currentIter;    
  55.             if(currentIter == numList.end())    
  56.                 currentIter = numList.begin();    
  57.         }    
  58.         // 找到第m个数,将其从list中移出    
  59.         nextIter = ++currentIter;    
  60.         if(nextIter == numList.end())    
  61.             nextIter = numList.begin();    
  62.         --currentIter;    
  63.         numList.erase(currentIter);    
  64.         currentIter = nextIter;    
  65.     }    
  66.     return *(currentIter);    
  67. }   
原创粉丝点击