C++面试题

来源:互联网 发布:东莞网络优化推广公司 编辑:程序博客网 时间:2024/06/01 07:12

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

/***********************************************************************题目:一个台阶总共有n级,如果一次可以跳1级,也可以跳2级。求总共有多少总跳法。分析:首先我们考虑最简单的情况。如果只有1级台阶,那显然只有一种跳法。如果有2级台阶,那就有两种跳的方法了:一种是分两次跳,每次跳1级;另外一种就是一次跳2级。现在我们再来讨论一般情况。我们把n级台阶时的跳法看成是n的函数,记为f(n)。当 n=1 时有 1 种跳法;当 n=2 时有 2 种跳法;当n>2时,第一次跳的时候就有两种不同的选择:一是第一次只跳1级,此时跳法数目等于后面剩下的n-1级台阶的跳法数目,即为f(n-1);另外一种选择是第一次跳2级,此时跳法数目等于后面剩下的n-2级台阶的跳法数目,即为f(n-2)。因此n级台阶时的不同跳法的总数f(n)=f(n-1)+ f(n-2)。***********************************************************************/#include <iostream>using namespace std;int f(int n){if(n < 1){cout<<"台阶数至少为1!"<<endl;return -1;}if(1 == n)return 1;if(2 == n)return 2; return f(n-1) + f(n-2);}int main(){int num;cout<<"请输入台阶数: ";cin>>num;cout<<"共有 "<<f(num)<<" 种跳法."<<endl;return 0;}



2. 求子数组的最大和

/************************************************************************ 题目: 输入一个整形数组,数组里有正数也有负数。  数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。  求所有子数组的和的最大值。要求时间复杂度为O(n)。  例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5, 和最大的子数组为3, 10, -4, 7, 2,  因此输出为该子数组的和18。 ************************************************************************/  #include <iostream>  using namespace std;    int getMaxSubArraySum(int R[],int n);    int main()  {      int arr[8] = {1,-2,3,10,-4,7,2,-5};        int maxSubSum = getMaxSubArraySum(arr,8);        cout<<maxSubSum<<endl;        return 0;  }    int getMaxSubArraySum(int R[],int n)  {      int maxSumValue = 0;//结果      int subArraySumValue = 0;//累加和      int max = R[0];//保存数组中的最大值      for(int i=0;i<n;++i)      {          subArraySumValue += R[i];          if(subArraySumValue < 0)          {              subArraySumValue = 0;          }          if(subArraySumValue > maxSumValue)          {              maxSumValue = subArraySumValue;          }          if(max < R[i])          {              max = R[i];          }      }      if(max < 0)      {          //若数组中所有的数都为负数,则返回最大的一个数          return max;      }      return maxSumValue;  }  


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

/********************************************************** 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。 要求: 不能创建任何新的结点,只能调整指针的指向。 **********************************************************/ 

/********************************************************** 思路: 1.构造二叉查找树; 2.中序遍历二叉查找树;  3.将访问到的结点调整为双向链表。 **********************************************************/    //测试程序  #include <iostream>  using namespace std;    //定义二元查找树结点的数据结构  struct BSTreeNode  {      int m_value;      BSTreeNode *m_pLeft;      BSTreeNode *m_pRight;  };    BSTreeNode *pHead = NULL;  BSTreeNode *pIndex = NULL;//指向前一个结点    //建立二叉排序树  void addBSTreeNode(BSTreeNode *&pCurrent, int val);  //中序遍历,同时调整结点指针  void inOrderBSTreeNode(BSTreeNode *pNode);  //调整结点指针  void convert2DoubleLinkedList(BSTreeNode *pCurrent);    int main()  {      BSTreeNode *pRoot = NULL;      addBSTreeNode(pRoot,10);      addBSTreeNode(pRoot,6);      addBSTreeNode(pRoot,14);      addBSTreeNode(pRoot,4);      addBSTreeNode(pRoot,8);      addBSTreeNode(pRoot,12);      addBSTreeNode(pRoot,16);      inOrderBSTreeNode(pRoot);      return 0;  }      void addBSTreeNode(BSTreeNode *&pCurrent, int val)  {      if(NULL == pCurrent)      {          BSTreeNode *pNode = new BSTreeNode();          pNode->m_value = val;          pNode->m_pLeft = NULL;          pNode->m_pRight = NULL;          pCurrent = pNode;      }      else      {          if(pCurrent->m_value < val)          {              addBSTreeNode(pCurrent->m_pRight,val);          }          else if(pCurrent->m_value > val)          {              addBSTreeNode(pCurrent->m_pLeft,val);          }          else          {              cout<<"Node repeated!!!"<<endl;          }      }  }  void inOrderBSTreeNode(BSTreeNode *pNode)  {      if(NULL == pNode)      {          return;      }      if(NULL != pNode->m_pLeft)      {          inOrderBSTreeNode(pNode->m_pLeft);      }      convert2DoubleLinkedList(pNode);      if(NULL != pNode->m_pRight)      {          inOrderBSTreeNode(pNode->m_pRight);      }  }  void convert2DoubleLinkedList(BSTreeNode *pCurrent)  {      //使当前结点的左指针指向双向链表中的最后一个结点      pCurrent->m_pLeft = pIndex;      if(NULL == pIndex)//双向链表尚未建立      {          pHead = pCurrent;      }      else      {          pIndex->m_pRight = pCurrent;      }      pIndex = pCurrent;      cout<<pCurrent->m_value<<" ";  }  

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

/*********************************************************************** 题目: 假设你有一个用1001个整数组成的数组,这些整数是任意排列的, 但是你知道所有的整数都在1到1000(包括1000)之间。 此外,除一个数字出现两次外,其他所有数字只出现一次。 假设你只能对这个数组做一次处理,用一种算法找出重复的那个数字。 如果你在运算中使用了辅助的存储方式,那么你能找到不用这种方式的算法吗? ***********************************************************************/    /*********************************************************************** 思路: (1001个数异或结果)与(1-1000异或的结果)再做异或,即可。  原理: 设重复数为A, 其余999个数异或结果为B。  1001个数异或结果为A^A^B, 1-1000异或结果为A^B。 由于异或满足交换律和结合律, 且X^X = 0, 0^X = X;  则有(A^B)^(A^A^B)=A^B^B=A  ***********************************************************************/    //测试程序  #include <iostream>  using namespace std;    void showRepeated(int R[],int n);    int main()  {      int a[] = {5,2,4,3,4,1,6};        showRepeated(a,6);      return 0;  }    void showRepeated(int R[],int n)  {      int result = 0;      for(int i=0;i<=n;++i)      {          result ^= R[i];      }      for(int i=1;i<=n;++i)      {          result ^= i;      }      cout<<"result = "<<result<<endl;  }  

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

//输入一个数,判断它是不是回文数。  #include <iostream>  using namespace std;    bool isPalindromicNumber(int x);    int main()  {      int x = 0;      cout<<"Please input a number:";      cin>>x;      if(isPalindromicNumber(x))          cout<<x<<"是回文数."<<endl;      else          cout<<x<<"不是回文数."<<endl;      return 0;  }    bool isPalindromicNumber(int x)  {      int y = 0;      int result = 0;      int temp = x;      while(x!=0){              y = x%10;          x /= 10;          result = result*10+y;      }      if(result==temp)          return true;      else           return false;  }  


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

#include <stdio.h>  #include <string.h>  int getCount(char* str,char* substr)  {      int i=0,j=0,count=0;      while(*(str+i)){          if(*(str+i)==*(substr+j)){              i++;              j++;          }          else{              if(j==0)                  i++;              else                  j = 0;          }          if(j==strlen(substr)){              count++;              j = 0;          }      }      return count;  }  int main()  {      char* str = "HHiHelloHHioHhiHrlHIodHioplloHHii";      char* substr = "Hi";      int count = getCount(str,substr);      printf("子串出现的次数:%d\n",count);      return 0;  }  


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

//如果一个数恰好等于它的真因子之和,则称该数为“完全数”。  //根据完全数的定义,先计算所选取的整数num的真因子,将各因子累加于sum,若sum等于num,则num为完全数。  #include <iostream>  using namespace std;    bool isWanQuanShu(int num);//判断num是否为完全数        int main(){      for(int i=2;i<1000;i++){          if(isWanQuanShu(i)){              cout<<i<<" ";          }      }      cout<<endl;      return 0;  }    bool isWanQuanShu(int num){      int sum = 0;      for(int i=1;i<=num/2;i++)          if(num%i == 0)              sum += i;      if(sum == num)          return true;      else          return false;  }  


8. 求1+2+…+n

/********************************************************** 题目: 求1+2+…+n 要求: 不能使用乘除法、for、while、if、else、switch、case 等关键字以及条件判断语句(A?B:C) **********************************************************/    /********************************************************** 思路: 定义一个类,我们new一个含有n个这种类型元素的数组,那么该类 的构造函数将会被调用n次。可以将需要执行的代码放到构造函数里。 **********************************************************/  #include <iostream>  using namespace std;    class Temp  {  public:      Temp()      {          ++m_n;          m_sum += m_n;      }      static void Reset(){m_n = 0; m_sum = 0;}      static int getSum(){return m_sum;}  private:      static int m_n;      static int m_sum;  };    int Temp::m_n = 0;  int Temp::m_sum = 0;    int Sum(int n)  {      Temp::Reset();      Temp *tmp = new Temp[n];      delete[] tmp;      tmp = NULL;      return Temp::getSum();  }    int main()  {      cout<<Sum(100)<<endl;      return 0;  }  

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

/************************************************************** 题目:输入一个已经按升序排序过的数组和一个数字, 在数组中查找两个数, 使得它们的和正好是输入的那个数字。 要求时间复杂度是O(n)。如果有多对 数字的和等于输入的数字,输出任意一对即可。  例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。 **************************************************************/    #include <iostream>  using namespace std;    void find(int R[],int n,int sum);    int main()  {      int arr[6] = {1,2,4,7,11,15};      int sum = 15;      find(arr,6,sum);      return 0;  }    void find(int R[],int n,int sum)  {      int i=0;      int j=n-1;      while(i < j)      {          if(R[i]+R[j] == sum)          {              cout<<sum<<" = "<<R[i]<<" + "<<R[j]<<endl;              return;          }          R[i]+R[j]<sum ? ++i : --j;      }      cout<<"Cannot find!"<<endl;  }  

10. 约瑟夫环

/**************************************************************************** 题目:n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字 (第一个为当前数字本身,第二个为当前数字的下一个数字)。当一个数字删除后,从被删除 数字的下一个继续删除第m个数字。求出在这个圆圈中剩下的最后一个数字。   分析:既然题目有一个数字圆圈,很自然的想法是我们用一个数据结构来模拟这个圆圈。 在常用的数据结构中,我们很容易想到用环形列表。我们可以创建一个总共有m个数字的环形列表, 然后每次从这个列表中删除第m个元素。 我们用STL中std::list来模拟这个环形列表。 由于list并不是一个环形的结构,因此每次跌代器扫描到列表末尾的时候, 要记得把跌代器移到列表的头部。这样就是按照一个圆圈的顺序来遍历这个列表了。  这种思路需要一个有n个结点的环形列表来模拟这个删除的过程,因此内存开销为O(n)。 而且这种方法每删除一个数字需要m步运算,总共有n个数字,因此总的时间复杂度是O(mn)。 ****************************************************************************/      #include <iostream>  using namespace std;  #include <list>    int getLastNumber(list<int> numList,unsigned m);    int main()  {      list<int> numList;      unsigned n;      unsigned m;      cout<<"请输入n:";      cin>>n;      cout<<"请输入m:";      cin>>m;      if(n<1 || m<1)      {          cout<<"\n输入有误!\n"<<endl;          return -1;      }                for(unsigned i=0;i<n;++i)          numList.push_back(i);      cout<<"Last Number: "<<getLastNumber(numList,m)<<endl;        return 0;  }    int getLastNumber(list<int> numList, unsigned m)  {      list<int>::iterator currentIter = numList.begin();      list<int>::iterator nextIter;            while(numList.size() > 1)      {          for(unsigned i=1;i<m;++i)          {              ++currentIter;              if(currentIter == numList.end())                  currentIter = numList.begin();          }          // 找到第m个数,将其从list中移出          nextIter = ++currentIter;          if(nextIter == numList.end())              nextIter = numList.begin();          --currentIter;          numList.erase(currentIter);          currentIter = nextIter;      }      return *(currentIter);  }  


0 0
原创粉丝点击