一个渣渣的刷题思路记录
2018/9/10
题目:报数杀人
海盗船1000人围成一圈(编号1到1000),报数如果是三的倍数就扔进海里(一直报不要停eg.998 999(dead) 1000 1001/原来的1号 1002(dead)/原来的2号 ...),最后一个人为几号
思路:是朋友问的一道面试题目,想法大概就是每轮剩下活着的人,再进行新的一轮淘汰,递归算法如下(更优的算法并不懂,后面懂了再改吧
#include <iostream>
#include <vector>
using namespace std;
int find(vector<int> test,int num){
int length = test.size();
vector<int> test2;
for(int i=0; i<length; i++){
if(num == 3){
num = 1;
}
else{
test2.push_back(test[i]);
num++;
}
}
if(test2.size() == 1){
cout << test2[0] << endl;
return test2[0];
}
return find(test2,num);
}
int main(){
vector<int> test;
for(int i=1; i<=10; i++){
test.push_back(i);
}
int num = 1;
int result = find(test,num);
cout << result << endl;
}
题目:跳台阶:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
思路:第一印象是使用递归实现,每次进入函数有俩种选择,跳1或跳2,再调用自身,当级数为0时,返回跳法数+1,但很可惜,牛客会提示说时间空间不符合要求,所以没办法使用递归简单实现了
只能换思路了,仔细想了一下,也很简单的(找规律),当阶数大于3的时候,很容易就明白说,到这层阶梯的方法是只有俩种,一种是从n-1层跳上去,一种是n-2层跳,也就是跳法总数f(n)=f(n-1)+f(n-2),而f(1)=1,f(2)=2,接下去的迭代上去就可以了,也就可以知道f(0)=1,f(-1)=0(虽然后面的没什么必要,但开心就好)
代码如下:
class Solution {
public:
int jumpFloor(int number) {
int f1=0,f2=1,f3=0;
while(number--){
f3 = f2+f1;
f1 = f2;
f2 = f3;
}
return f3;
}
};
题目:变态跳台阶:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。(真是只有活力的青蛙)
思路:完全放弃递归想法,由上面那题,思考规律吧,总感觉是数学题其实,跟上面那道类似其实,只不过需要加的变多了而已,就变成了f(n)=f(n-1)+f(n-2)+......+f(1)+f(0),就是最后一步都是一次跳完的,所以呢,f(n)=,推导过程就不给了,反正随便猜都可以猜到的其实
class Solution {
public:
int jumpFloorII(int number) {
int sum=1;
while(--number){
sum = sum*2;
}
return sum;
}
};
题目:矩形覆盖:我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
思路:乍一看好像很厉害,特么的不就是青蛙跳那道题么,代码都不用改,思路就是,竖=1,横=2,其他参考青蛙跳思路。
2018/8/9 刷题笔记
二叉树重建问题
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
思路:由于前序遍历的第一个点是根结点,而中序遍历以根结点作为左右子树的分界,故以此为切入点,每次得到该树的根节点,以及左右子树的先序遍历中序遍历的结果,将俩个vector分割为四个vector
代码如下:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
int length = pre.size();
if(length==0){
return NULL;
}
TreeNode *tree = new TreeNode(pre[0]);
vector<int> left_pre,left_vin,right_pre,right_vin;
int gen=0;
while(vin[gen]!=pre[0]){
gen++;
}
for(int i=0; i<gen; i++){
left_vin.push_back(vin[i]);
left_pre.push_back(pre[i+1]);
}
for(int i=gen+1; i<length; i++){
right_vin.push_back(vin[i]);
right_pre.push_back(pre[i]);
}
tree->left=reConstructBinaryTree(left_pre,left_vin);
tree->right=reConstructBinaryTree(right_pre,right_vin);
return tree;
}
题目:用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
思路:栈是先进后出,队列是先进先出,所以将一个栈反转过来,顺序就同队列一样了,一个栈只做存储数据,另一个栈做输出中转,也就是输出时将栈反转,输出队头,再将栈反转回来,保留存储顺序
class Solution
{
public:
void push(int node) {
stack1.push(node);
}
int pop() {
while(!stack1.empty()){
stack2.push(stack1.top());
stack1.pop();
}
int top = stack2.top();
stack2.pop();
while(!stack2.empty()){
stack1.push(stack2.top());
stack2.pop();
}
return top;
}
private:
stack<int> stack1;
stack<int> stack2;
};
题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
思路:将数据进行遍历排序,思路简单明了,具体做法使用sort算法,也可自行实现
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
sort(rotateArray.begin(),rotateArray.end());
return rotateArray[0];
}
};
题目:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。n<=39
class Solution {
public:
int Fibonacci(int n) {
if(n == 0){
return n;
}
int sum=0,a=0,b=1;
for(int m=0; m<n; m++){
sum = a+b;
a = b;
b = sum;
}
return a;
}
};