C++面试常见算法题与参考答案总结
devil_08
题目一(数组中查找)
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
class Solution { public: bool Find(int target, vector<vector<int> > array) { if (array.empty())return false; //if (target < array[0][0])return false; int _length = array.size(); for (int i = 0; i < _length; i++) { if (array[i].empty())continue; else if(target >= array[i][0]) { if (target <= array[i][array[i].size() - 1]) { for (int j = array[i].size() - 1; j >= 0; j--) { if (target == array[i][j])return 1; else if (target > array[i][j])break; } } else { continue; } } else return false; } return false; } };
题目二(替换空格)
请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
class Solution { public: void replaceSpace(char *str,int length) { if(str==NULL) return ; int CountOfBlanks=0; int Originallength=0; for(int i=0;str[i]!='\0';i++) { Originallength++; if(str[i]==' ') ++CountOfBlanks; } int len =Originallength+2*CountOfBlanks; if(len+1>length) return ; char*pStr1=str+Originallength;//复制结束符‘\0’ char*pStr2=str+len; while(pStr1<pStr2) { if(*pStr1==' ') { *pStr2--='0'; *pStr2--='2'; *pStr2--='%'; } else { *pStr2--=*pStr1; } --pStr1; } } };
题目三(打印链表)
输入一个链表,从尾到头打印链表每个节点的值。
/** * struct ListNode { * int val; * struct ListNode *next; * ListNode(int x) : * val(x), next(NULL) { * } * }; */ class Solution { public: vector<int> printListFromTailToHead(ListNode* head) { vector <int> result; stack<int> arr; ListNode* p=head; while(p!=NULL) { arr.push(p->val); p=p->next; } int len=arr.size(); for(int i=0;i<len;i++) { result.push_back(arr.top()); arr.pop(); } return result; } };
题目四(重建二叉树)
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
/** * Definition for binary tree * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: struct TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> in) { int inlen=in.size(); if(inlen==0) return NULL; vector<int> left_pre,right_pre,left_in,right_in; //创建根节点,根节点肯定是前序遍历的第一个数 TreeNode* head=new TreeNode(pre[0]); //找到中序遍历根节点所在位置,存放于变量gen中 int gen=0; for(int i=0;i<inlen;i++) { if (in[i]==pre[0]) { gen=i; break; } } //对于中序遍历,根节点左边的节点位于二叉树的左边,根节点右边的节点位于二叉树的右边 //利用上述这点,对二叉树节点进行归并 for(int i=0;i<gen;i++) { left_in.push_back(in[i]); left_pre.push_back(pre[i+1]);//前序第一个为根节点 } for(int i=gen+1;i<inlen;i++) { right_in.push_back(in[i]); right_pre.push_back(pre[i]); } //和shell排序的思想类似,取出前序和中序遍历根节点左边和右边的子树 //递归,再对其进行上述所有步骤,即再区分子树的左、右子子数,直到叶节点 head->left=reConstructBinaryTree(left_pre,left_in); head->right=reConstructBinaryTree(right_pre,right_in); return head; } };
题目五(用两个栈实现队列)
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
class Solution{ public: int cou = 0; void push(int node) { stack1.push_back(node); stack2.push_back(cou++); } int pop() { int i = 0; while(stack2[i] == -1) { i++; } stack2[i] = -1; return stack1[i]; } private: vector<int> stack1;//存数 vector<int> stack2;//地址 };
题目六(旋转数组的最小数字)
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
#include <iostream> #include <vector> #include <string> #include <stack> #include <algorithm> using namespace std; class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { int size = rotateArray.size(); if(size == 0){ return 0; }//if int left = 0,right = size - 1; int mid = 0; // rotateArray[left] >= rotateArray[right] 确保旋转 while(rotateArray[left] >= rotateArray[right]){ // 分界点 if(right - left == 1){ mid = right; break; }//if mid = left + (right - left) / 2; // rotateArray[left] rotateArray[right] rotateArray[mid]三者相等 // 无法确定中间元素是属于前面还是后面的递增子数组 // 只能顺序查找 if(rotateArray[left] == rotateArray[right] && rotateArray[left] == rotateArray[mid]){ return MinOrder(rotateArray,left,right); }//if // 中间元素位于前面的递增子数组 // 此时最小元素位于中间元素的后面 if(rotateArray[mid] >= rotateArray[left]){ left = mid; }//if // 中间元素位于后面的递增子数组 // 此时最小元素位于中间元素的前面 else{ right = mid; }//else }//while return rotateArray[mid]; } private: // 顺序寻找最小值 int MinOrder(vector<int> &num,int left,int right){ int result = num[left]; for(int i = left + 1;i < right;++i){ if(num[i] < result){ result = num[i]; }//if }//for return result; } }; int main(){ Solution s; //vector<int> num = {0,1,2,3,4,5}; //vector<int> num = {4,5,6,7,1,2,3}; vector<int> num = {2,2,2,2,1,2}; int result = s.minNumberInRotateArray(num); // 输出 cout<<result<<endl; return 0; }
题目七(斐波那契数列)
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。
n<=39
class Solution { public: int Fibonacci(int n) { if(n == 0){ return 0; } if(n == 1){ return 1; } int a = 0,b = 1; int m = 0; int i; for(i = 2;i <= n;i++){ m = a + b; a = b; b = m; } return m; } };
题目八(跳台阶)
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
class Solution { public: int jumpFloor(int n) { int f=1,g=2; n--; while(n--) { g+=f; f=g-f; } return f; } };
题目九(变态跳台阶)
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
class Solution { public: int jumpFloorII(int number) { if(number==0) return number; int total=1; for(int i=1;i<number;i++) total*=2; return total; } };
题目十(矩形覆盖)
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
class Solution { public: int rectCover(int number) { if (number <= 0) { return number; } int f1 = 1; int f2 = 2; int f3; for (int i = 3; i <= number; i++) { f3 = f1 + f2; f1 = f2; f2 = f3; } return f3; } };