剑指刷题1--C++

1.在二维数组中查找

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

解题思路:

找到左下角 从左下角看 向上是递减 向上是递增

代码时注意数组的越界问题

STL的使用方法 在 verctor使用size() 获取列array[0].size()获取列

`class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        int row=array.size();
        int col=array[0].size();
        int i=row-1,j=0;
        while(i>=0&&j<col){
           if(target<array[i][j])
                i--;
            else if (target>array[i][j])
               j++;
            else 
                 return true; 
        }
        return false;
    }
};`

2.替换空格

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

解题思路:

从前向后遍历 从后向前插入

0123456789101112131415
wearehappy
we%20are%20happy

插入前后可以看出 空格从2 号位变为 2-4号位 插入时从后插入用i+count*2 可以定位到%20的尾位

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

3.从头到尾打印链表

输入一个链表,按链表从尾到头的顺序返回一个ArrayList。

解题思路:

题目要求打印出一个数组 并不是链表反转

思路:1 利用栈

class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        ListNode *p=NULL;
        p=head;
        vector<int> value;
        stack<int > temp;
        while(p!=NULL)
        {
            temp.push(p->val);
            p=p->next;
        }
        while(!temp.empty()){
            value.push_back(temp.top());
            temp.pop();
        }
        return value;
    }
};

思路:2 使用数组反转

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

4.重建二叉树

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

解题思路:

前序遍历第一个数 必是根节点 中序遍历 根节点前的数必为左子树 所以可以确定 左子树的长度

然后通过递归 不断对剩下的子树切分 让他们分为左右子树

注意 数组边界 前序数组左半边包括根节点 所以需要i+1 右半边则和中序数组一致

class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
       int len=vin.size();
       if(len==0)
           return NULL;
        vector<int> pre_left,pre_right,vin_left,vin_right;
        TreeNode *head=new  TreeNode(pre[0]);
        int rp=0;
        for(int i=0;i<len;i++)
        {
            if(vin[i]==pre[0])
            {
                rp=i;
                break;
            }
        }
        for(int i=0;i<rp;i++)
        {
            pre_left.push_back(pre[i+1]);
            vin_left.push_back(vin[i]);
        }
        for(int i=rp+1;i<len;i++)
        {
            pre_right.push_back(pre[i]);
            vin_right.push_back(vin[i]);
        }
        head->left=reConstructBinaryTree( pre_left,vin_left);
        head->right=reConstructBinaryTree(pre_right,vin_right);c
        return head;
    }
};

5.用两个栈实现队列

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

解题思路:

一个栈用来入栈,另外一个栈用来出栈,当栈2为空时,栈1数据弹出到栈2

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 temp=stack2.top();
            stack2.pop();
            return temp;
        
    }

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

6.旋转数组的最小数字

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

解题思路:

二分法,题中意思为非递减数组,则可以分为两个有序数组

利用mid 获取 两个数组的边界 当left=mid或者大于mid时结束循环

注意 若有重复数字时 出现left =mid 直接使left向右移动 不然程序会卡住 只能移动left 移动right 会使最小数字被删除

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
         if(rotateArray.size()==0)
         {
            return 0;
         }
         int left=0;
         int right=rotateArray.size()-1;
         while(left<right)
         {
             if(rotateArray[left]<rotateArray[right])
             {
                 return rotateArray[left];
             }
            int mid=(left+right)/2;
             if (rotateArray[left]<rotateArray[mid])
             {
                 left=mid+1;
             }
             else if(rotateArray[left]>rotateArray[mid])
             {
                 right=mid;
             }
             else{
                 left++;
             }
             

         }
        return rotateArray[left];
    }

};

7.斐波那契数列

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。

n<=39

解题思路:

直接使用迭代 注意前三项值为0 1 1 然后直接使用前两项求和即可

class Solution {
public:
    int Fibonacci(int n) {
        if(n==0) return 0;
        if(n==1||n==2) return 1;
        int res=1;
        int last=1;
          for(int i=3;i<=n;i++)
          {
              int temp=res;
              res=res+last;
              last=temp;
          }
        return res;
    }
};

8.跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

解题思路:

从顶向下递归

(1)假设台阶有n级 ,则到达第n级的方法有f(n)种

(2)当青蛙最后一步走一个台阶时,而达到最后一步之前则走了(n-1)级台阶,则此时达到n-1级时的方法有f(n-1)种

(3)当青蛙最后一步走二个台阶时,而达到最后一步之前则走了(n-2)级台阶,则此时达到n-2级时的方法有f(n-2)种

故走n级台阶的方法有f(n)=f(n-1)+f(n-2)

所以可以开始递归 递归结束条件设定:当n=1时 f(n)=1;当n=2时 f(n)=2 n–即可

class Solution {
public:
    int jumpFloor(int number) {
        if(number==0)
        {
            return 0;
        }
        if(number==1)
        {
            return 1;
        }
        if(number==2)
        {
            return 2;
        }
        return jumpFloor(number-1)+jumpFloor(number-2);
        }

};


9.变态跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

解题思路:

假设台阶有n级 ,则到达第n级的方法有f(n)种

当第一次跳1级时 方法有f(1)种

当第一次跳2级时 若第一次跳一级台阶 则剩下 1级 则有f(2-1)种方法

​ 若第一次跳二级台阶 则剩下 1级 则有f(2-2)种方法

当第一次跳3级时 若第一次跳一级台阶 则剩下 1级 则有f(3-1)种方法

​ 若第一次跳二级台阶 则剩下 1级 则有f(3-2)种方法

						 若第一次跳三级台阶  则剩下 1级 则有f(3-3)种方法

则第一次跳n级时 共有f(n)=f(n-1)+…+f(1)

又 f(n-1)=f(n-2)+…+f(1)

所以 f(n)=2*f(n-1)

class Solution {
public:
    int jumpFloorII(int number) {
        if(number==0)
        {
            return 0;
        }
         if(number==1)
        {
            return 1;
        }
        if(number==2)
        {
            return 2;
        }
        return 2*jumpFloorII(number-1);
    }
};

10.矩形覆盖

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

比如n=3时,2*3的矩形块有3种覆盖方法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2O3efc1y-1596631268443)(C:\Users\ian\AppData\Roaming\Typora\typora-user-images\image-20200805105249149.png)]

解题思路:

img

假设 n种矩形有f(n)种解法

当n=1 解法为f(1)=1

当n=2 解法为f(2)=2

当n=3 则有两种情形 则为 f(n-1)+f(n-2)

class Solution {
public:
    int rectCover(int number) {
        if(number==0)
        {
            return 0;
        }
        if(number==1)
        {
            return 1;
        }
        if(number==2)
        {
            return 2;
        }
        return rectCover(number-1)+rectCover(number-2);
    }
};

假设 n种矩形有f(n)种解法

当n=1 解法为f(1)=1

当n=2 解法为f(2)=2

当n=3 则有两种情形 则为 f(n-1)+f(n-2)

class Solution {
public:
    int rectCover(int number) {
        if(number==0)
        {
            return 0;
        }
        if(number==1)
        {
            return 1;
        }
        if(number==2)
        {
            return 2;
        }
        return rectCover(number-1)+rectCover(number-2);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值