剑指OFFER第1-10题

1.二维数组中的查找

在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        vector<int>:: iterator j;
        vector<vector<int>>:: iterator i;
        for(i=array.begin();i!=array.end();i++){
            for(j=(*i).begin();j!=(*i).end();j++){
                if((*j)==target){
                    return 1;
                }
            }
        }
        return 0;
    }
};

使用迭代器遍历,时间复杂度o(n*m),因为数据是递增的也可以用二分法查找,复杂度可优化至o(n*logm)。

2.替换空格

请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

class Solution {
public:
    void replaceSpace(char *str,int length) {
        int after_length=length;
        for(int i=0;i<length;i++){
            if(str[i]==' '){
                after_length+=2;
            }
        }
        str[after_length]='\0';
        for(int i=after_length-1,j=length-1;i>=0;i--,j--){
            if(str[j]==' '){
                str[i--]='0';
                str[i--]='2';
                str[i]='%';
            }else{
                str[i]=str[j];
            }
        }
    }
};

先计算出替换后要占的空间,再从尾到头替换,保证已处理的数据不影响未处理的数据

3.从尾到头打印链表

输入一个链表,从尾到头打印链表每个节点的值。

class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int> ans;
        vector<int> _stack;
        int i=0;
        while(head!=NULL){
            _stack.push_back(head->val);
            i++;
            head=head->next;
        }
        i-=1;
        while(i>=0){
            ans.push_back(_stack[i]);
            i--;
        }
        return ans;
    }
};

输入到栈中再输出

4.重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        if(vin.size()==0){
            return NULL;
        }
        int mid=pre[0];
        TreeNode *node=new TreeNode(mid);
        vector<int> left_pre,right_pre,left_vin,right_vin;
        int i=0;
        while(vin[i]!=mid){
            left_pre.push_back(pre[i+1]);
            left_vin.push_back(vin[i]);
            i++;
        }
        i++;
        while(i<vin.size()){
            right_pre.push_back(pre[i]);
            right_vin.push_back(vin[i]);
            i++;
        }
        node->left=reConstructBinaryTree(left_pre,left_vin);
        node->right=reConstructBinaryTree(right_pre,right_vin);
        return node;
    }
};

前序遍历的第一个数就是根节点,将中序遍历分为左右子树后递归构造

5.用两个栈实现队列

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

class Solution
{
public:
    void push(int node) {
        stack1.push(node);
    }

    int pop() {
        if(stack2.empty()){
            while(!stack1.empty()){
                stack2.push(stack1.top());
                stack1.pop();
            }
        }
        int ans=stack2.top();
        stack2.pop();
        return ans;
    }

private:
    stack<int> stack1;
    stack<int> stack2;
};

入队的元素进入栈1中,栈1的元素再出栈进入栈2,则栈2的元素按照队列顺序排列。出队时栈2的栈顶元素出栈即可。需要注意的是栈2的元素没必要倒入栈1中,需要出队就继续读取栈2中的元素直到为空,因为后来入队的元素不影响队首的已经进入栈2的元素。

6.旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        int nsize=rotateArray.size();
        if(nsize==0)
            return 0;
        for(int i=0;i<nsize-1;i++){
            if(rotateArray[i]>rotateArray[i+1])
                return rotateArray[i+1];
        }
        return rotateArray[0];
    }
};

数组原本是递增的,旋转后最小的数字会在比他大的数字后面,否则就是没有旋转,第一个就是最小数字,遍历一遍即可。也可以用二分法优化,上半部分的数字一定比下半部分的数字大,二分逼近最小数字所在位置,但是有重复数字时只能遍历,比较麻烦。

7.斐波那契数列

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。
n<=39

class Solution {
public:
    int Fibonacci(int n) {
        int a=1,b=1,c;
        if(n==0)
            return 0;
        if(n<3)
            return 1;
        for(int i=3;i<=n;i++){
            c=a+b;
            a=b;
            b=c;
        }
        return b;
    }
};

8.跳台阶

class Solution {
public:
    int jumpFloor(int number) {
        int a=1,b=1,c;
        int n=number;
        if(n==0)
            return 0;
        if(n<2)
            return 1;
        for(int i=2;i<=n;i++){
            c=a+b;
            a=b;
            b=c;
        }
        return b;
    }
};

实际也是斐波那契数列,当前的级数可以从n-1级和n-2级跳上来,即前面两种状态的和

9.变态跳台阶

class Solution {
public:
    int jumpFloorII(int number) {
        int ans[100];
        ans[1]=1;
        ans[2]=2;
        for(int i=3;i<=number;i++){
            ans[i]=1;
            for(int j=1;j<i;j++){
                ans[i]+=ans[j];
            }
        }
        return ans[number];
    }
};

当前状态是前面所有状态之和,实际上找规律可以发现答案只是2的n-1次方。

10.矩阵覆盖

我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

class Solution {
public:
    int rectCover(int number) {
        int a=1,b=1,c;
        int n=number;
        if(n==0)
            return 0;
        if(n<2)
            return 1;
        for(int i=2;i<=n;i++){
            c=a+b;
            a=b;
            b=c;
        }
        return b;
    }
};

实际上也是斐波那契数列。大矩形的最右端的图形只有两种情况,一个竖条或者两个横条,所以组合方法可以理解成(n-1个+1个竖条)和(n-2个+两个横条)的方案之和。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值