在线笔试题汇总 4.12
2016-04-12 21:18
239 查看
1)问:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
答:
分析一下代码: 这段小小的代码,很是巧妙。
如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。
举个例子:一个二进制数1100,从右边数起第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011.我们发现减1的结果是把最右边的一个1开始的所有位都取反了。这个时候如果我们再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。如1100&1011=1000.也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。
2)问:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。
答:
3)问:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
答:
对于第n个台阶来说,只能从n-1或者n-2的台阶跳上来,所以
F(n) = F(n-1) + F(n-2)
斐波拉契数序列,初始条件
n=1:只能一种方法
n=2:两种
递归一下就好了
4)问:我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
答:
依旧是斐波那契数列
2*n的大矩形,和n个2*1的小矩形
其中target*2为大矩阵的大小
有以下几种情形:
1⃣️target <= 0 大矩形为<= 2*0,直接return 1;
2⃣️target = 1大矩形为2*1,只有一种摆放方法,return1;
3⃣️target = 2 大矩形为2*2,有两种摆放方法,return2;
4⃣️target = n 分为两步考虑:
第一次摆放一块 2*1 的小矩阵,则摆放方法总共为f(target - 1)
第一次摆放一块1*2的小矩阵,则摆放方法总共为f(target-2)
因为,摆放了一块1*2的小矩阵(用√√表示),对应下方的1*2(用××表示)摆放方法就确定了,所以为f(targte-2)
代码:
6)问:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
答:
关于本题,前提n个台阶会有一次n阶的跳法。分析如下:
f(1) = 1
f(2) = f(2-1) + f(2-2) //f(2-2) 表示2阶一次跳2阶的次数。
f(3) = f(3-1) + f(3-2) + f(3-3)
...
f(n) = f(n-1) + f(n-2) + f(n-3) + ... + f(n-(n-1)) + f(n-n)
说明:
1. 这里的f(n) 代表的是n个台阶有一次1,2,...n阶的 跳法数。
2. n = 1时,只有1种跳法,f(1) = 1
3. n = 2时,会有两个跳得方式,一次1阶或者2阶,这回归到了问题(1) ,f(2) = f(2-1) + f(2-2)
4. n = 3时,会有三种跳得方式,1阶、2阶、3阶,
那么就是第一次跳出1阶后面剩下:f(3-1);第一次跳出2阶,剩下f(3-2);第一次3阶,那么剩下f(3-3)
因此结论是f(3) = f(3-1)+f(3-2)+f(3-3)
5. n = n时,会有n中跳的方式,1阶、2阶...n阶,得出结论:
f(n) = f(n-1)+f(n-2)+...+f(n-(n-1)) + f(n-n) => f(0) + f(1) + f(2) + f(3) + ... + f(n-1)
6. 由以上已经是一种结论,但是为了简单,我们可以继续简化:
f(n-1) = f(0) + f(1)+f(2)+f(3) + ... + f((n-1)-1) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2)
f(n) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2) + f(n-1) = f(n-1) + f(n-1)
可以得出:
f(n) = 2*f(n-1)
7. 得出最终结论,在n阶台阶,一次有1、2、...n阶的跳的方式时,总得跳法为:
| 1 ,(n=0 )
f(n) = | 1 ,(n=1 )
| 2*f(n-1),(n>=2)
以后遇到这类问题,用类比法列公式就好了。
7)问:用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
答:
栈:限定仅在表尾进行插入和删除操作的线性表,栈顶(top)栈底(bottom)
队列:只允许在一端进行插入操作,而在另一端进行删除操作的线性表
入队:将元素进栈A
出队:判断栈B是否为空,如果为空,则将栈A中所有元素pop,并push进栈B,栈B出栈;
如果不为空,栈B直接出栈。
8)问:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
答:先序遍历第一个位置肯定是根节点node,中序遍历的根节点位置在中间p,在p左边的肯定是node的左子树的中序数组,p右边的肯定是node的右子树的中序数组。另一方面,先序遍历的第二个位置到p,也是node左子树的先序子数组,剩下p右边的就是node的右子树的先序子数组。把四个数组找出来,分左右递归调用即可
9)有一棵二叉树,请设计一个算法,按照层次打印这棵二叉树。
给定二叉树的根结点root,请返回打印结果,结果按照每一层一个数组进行储存,所有数组的顺序按照层数从上往下,且每一层的数组内元素按照从左往右排列。保证结点数小于等于500。
答:
分析一下代码: 这段小小的代码,很是巧妙。
如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。
举个例子:一个二进制数1100,从右边数起第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011.我们发现减1的结果是把最右边的一个1开始的所有位都取反了。这个时候如果我们再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。如1100&1011=1000.也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。
class Solution { public: int NumberOf1(int n) { int count = 0; while(n!= 0){ count++; n = n & (n - 1); } return count; } };
2)问:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。
答:
class Solution { public: int Fibonacci(int n) { int* array=new int ; array[0]=1; array[1]=1; array[2]=2; for(int i=3;i<n;i++) array[i]=array[i-1]+array[i-2]; return array[n-1]; }; };
3)问:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
答:
对于第n个台阶来说,只能从n-1或者n-2的台阶跳上来,所以
F(n) = F(n-1) + F(n-2)
斐波拉契数序列,初始条件
n=1:只能一种方法
n=2:两种
递归一下就好了
class Solution { public: int jumpFloor(int number) { if(number <= 0) return 0; else if(number == 1) return 1; else if(number == 2) return 2; else return jumpFloor(number-1) + jumpFloor(number-2); } };
4)问:我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
答:
依旧是斐波那契数列
2*n的大矩形,和n个2*1的小矩形
其中target*2为大矩阵的大小
有以下几种情形:
1⃣️target <= 0 大矩形为<= 2*0,直接return 1;
2⃣️target = 1大矩形为2*1,只有一种摆放方法,return1;
3⃣️target = 2 大矩形为2*2,有两种摆放方法,return2;
4⃣️target = n 分为两步考虑:
第一次摆放一块 2*1 的小矩阵,则摆放方法总共为f(target - 1)
第一次摆放一块1*2的小矩阵,则摆放方法总共为f(target-2)
因为,摆放了一块1*2的小矩阵(用√√表示),对应下方的1*2(用××表示)摆放方法就确定了,所以为f(targte-2)
代码:
public:class Solution { int rectCover(int number) { if(number<=0)return 1; else if(number==1)return 1; else if(number==2)return 2; else return rectCover(number-1)+rectCover(number-2); } };
6)问:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
答:
关于本题,前提n个台阶会有一次n阶的跳法。分析如下:
f(1) = 1
f(2) = f(2-1) + f(2-2) //f(2-2) 表示2阶一次跳2阶的次数。
f(3) = f(3-1) + f(3-2) + f(3-3)
...
f(n) = f(n-1) + f(n-2) + f(n-3) + ... + f(n-(n-1)) + f(n-n)
说明:
1. 这里的f(n) 代表的是n个台阶有一次1,2,...n阶的 跳法数。
2. n = 1时,只有1种跳法,f(1) = 1
3. n = 2时,会有两个跳得方式,一次1阶或者2阶,这回归到了问题(1) ,f(2) = f(2-1) + f(2-2)
4. n = 3时,会有三种跳得方式,1阶、2阶、3阶,
那么就是第一次跳出1阶后面剩下:f(3-1);第一次跳出2阶,剩下f(3-2);第一次3阶,那么剩下f(3-3)
因此结论是f(3) = f(3-1)+f(3-2)+f(3-3)
5. n = n时,会有n中跳的方式,1阶、2阶...n阶,得出结论:
f(n) = f(n-1)+f(n-2)+...+f(n-(n-1)) + f(n-n) => f(0) + f(1) + f(2) + f(3) + ... + f(n-1)
6. 由以上已经是一种结论,但是为了简单,我们可以继续简化:
f(n-1) = f(0) + f(1)+f(2)+f(3) + ... + f((n-1)-1) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2)
f(n) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2) + f(n-1) = f(n-1) + f(n-1)
可以得出:
f(n) = 2*f(n-1)
7. 得出最终结论,在n阶台阶,一次有1、2、...n阶的跳的方式时,总得跳法为:
| 1 ,(n=0 )
f(n) = | 1 ,(n=1 )
| 2*f(n-1),(n>=2)
以后遇到这类问题,用类比法列公式就好了。
class Solution { public: int jumpFloorII(int number) { if(number<=0) return -1; else if(number==1) return 1; else return 2*jumpFloorII(number-1); } };
7)问:用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
答:
栈:限定仅在表尾进行插入和删除操作的线性表,栈顶(top)栈底(bottom)
队列:只允许在一端进行插入操作,而在另一端进行删除操作的线性表
入队:将元素进栈A
出队:判断栈B是否为空,如果为空,则将栈A中所有元素pop,并push进栈B,栈B出栈;
如果不为空,栈B直接出栈。
class Solution { public: void push(int node) { stack1.push(node); } int pop() { int a; if(stack2.empty()) { while(!stack1.empty()) { a=stack1.top(); stack2.push(a); stack1.pop(); } } a=stack2.top(); stack2.pop(); return a; } private: stack<int> stack1; stack<int> stack2; };
8)问:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
答:先序遍历第一个位置肯定是根节点node,中序遍历的根节点位置在中间p,在p左边的肯定是node的左子树的中序数组,p右边的肯定是node的右子树的中序数组。另一方面,先序遍历的第二个位置到p,也是node左子树的先序子数组,剩下p右边的就是node的右子树的先序子数组。把四个数组找出来,分左右递归调用即可
/** * 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 in_size = in.size(); if(in_size == 0) return NULL; vector<int> pre_left, pre_right, in_left, in_right; int val = pre[0]; TreeNode* node = new TreeNode(val);//root node is the first element in pre int p = 0; for(p; p < in.size(); ++p){ if(in[p] == val) //Find the root position in in break; } for(int i = 0; i < in.size(); ++i){ if(i < p){ in_left.push_back(in[i]);//Construct the left pre and in pre_left.push_back(pre[i+1]); } else if(i > p){ in_right.push_back(in[i]);//Construct the right pre and in pre_right.push_back(pre[i]); } } node->left = reConstructBinaryTree(pre_left, in_left); node->right = reConstructBinaryTree(pre_right, in_right); return node; } };
9)有一棵二叉树,请设计一个算法,按照层次打印这棵二叉树。
给定二叉树的根结点root,请返回打印结果,结果按照每一层一个数组进行储存,所有数组的顺序按照层数从上往下,且每一层的数组内元素按照从左往右排列。保证结点数小于等于500。
class TreePrinter { public: vector<vector<int> > printTree(TreeNode* root) { TreeNode* last=root; TreeNode* nlast=NULL; vector<vector<int>> res; vector<int> cur_line; queue<TreeNode*> que; que.push(last); while(!que.empty()) { TreeNode* front=que.front(); que.pop(); cur_line.push_back(front->val); if(front->left) { que.push(front->left); nlast=front->left; } if(front->right) { que.push(front->right); nlast=front->right; } if(front==last) { res.push_back(cur_line); cur_line.clear(); last=nlast; } } return res; } };
相关文章推荐
- 动态input file多文件上传到后台没反应的解决方法!!!
- 关于继承,类,抽象类,接口的实际操作
- 广播接收器的使用
- hibernate入门
- Struts2 入门学习笔记(二)——拦截器应用
- 欢迎使用CSDN-markdown编辑器
- [BZOJ 1420 && BZOJ 1319]
- dp让宝宝疯掉
- 基于LBS功能应用的Geohash方案
- 阅读器关闭时尝试调用 Read 无效
- Intellij IDEA 的使用
- 持续集成Jenkins环境配置+使用
- 机器学习 笔记(三) 到底选择哪种机器学习算法来分类
- hdu 1102A + B Problem II
- RabbitMQ Spring AMQP
- android NDK编程:使用posix多线程与mutex相互排斥同步
- Java设计模式系列之迭代器模式
- CDISC SDTM DM domain 学习笔记
- FLV 结构分析
- 1214 线段覆盖——http://codevs.cn/problem/1214/