在线笔试题汇总 4.12

2 篇文章 0 订阅
1 篇文章 0 订阅

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,就可以进行多少次这样的操作。

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[n];
        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的小矩形横着或者竖着去覆盖更大的矩形。请问用n2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

答:

依旧是斐波那契数列

2*n的大矩形,和n2*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阶台阶,一次有12...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)问:用两个栈来实现一个队列,完成队列的PushPop操作。 队列中的元素为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;
    }
};



 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值