LeetCode-华为面试题库做题笔记一

写在前面

华为面试题库刷题第一天题目整理
欢迎访问我的个人博客网站:flamsteed

32. 最长有效括号

给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。

一共有三种时间复杂度O(N)的解法,分别是dp,栈,和计数,我们都实现一下:

dp

dp思路:dp一位数组存放到目前这一位字符的有效子串长度,所以所有’(‘对应的位置都是0,而’)'分两种情况:

  1. s[i]=’)’ 且 s[i-1]=’(’,则

    dp[i] = dp[i-2] + 2;

  2. s[i]=’)’ 且 s[i-1]=’)’,此时若s[i-dp[i-1]-1]=’(’,则

    dp[i] = dp[i-1] + dp[i-dp[i-1]-2] + 2;

只有这两种情况会出现有效的括号子串,遍历一遍之后统计最大长度即可。

代码:

class Solution {
public:
    int longestValidParentheses(string s) {
        if(s.empty()||s.length()==1) return 0;
        int l = s.length();
        vector dp(l,0);
        for(int i=1; i=0 ? dp[i-2] : 0 ) +2;//边界情况需要考虑,不能越界
            }
            else if(s[i]==')'&&s[i-1]==')'){//情况2
                if(i-dp[i-1]>=1 && s[i-dp[i-1]-1]=='(')
                    dp[i] = dp[i-1] + (i-dp[i-1]>=2 ? dp[i-dp[i-1]-2]:0) + 2;//同上
            }
        }
        int ans = 0;
        for(auto i : dp)
            if(i>ans) ans = i;
        return ans;
    }
};

括号匹配的题目用栈这个数据结构其实是最合适的,先将-1存放进栈顶。

  1. 对于每一个’(’,将下标放入栈中。
  2. 对于每一个’)’,弹出栈顶元素,并将现在的栈顶元素与当前下标作差,得出有效长度。如果栈已经是空的了,则插入当前下标。

代码:

class Solution {
public:
    int longestValidParentheses(string s) {
        if(s.empty()||s.length()==1) return 0;
        int l = s.length();
        stack a;
        a.push(-1);
        int maxl(0);
        for(int i=0; imaxl) maxl = i-a.top();
            }
        }
        return maxl;
    }
};

计数法

这个方法比较tricky,只需要两个变量left和right就能统计出答案,空间复杂度O(1)。

思路:先从左往右遍历字符串:

  1. 遇到’(’,left加1
  2. 遇到’)’,right加1,同时进行判断,如果此时left=right,则记录是不是最长的长度,如果right>left,则left和right同时清零。

然后再从右往左遍历一遍,用一样的方法统计一遍,此时存储的maxlength就是答案。

代码:

class Solution {
public:
    int longestValidParentheses(string s) {
        if(s.empty()||s.length()==1) return 0;
        int l = s.length();
        int left(0), right(0),maxl(0);
        for(int i=0; imaxl)
                        maxl = left+right;
                }
                else if(right>left){
                    left = 0;
                    right = 0;
                }
            }
        }
        left = 0;
        right = 0;
        for(int i=l-1; i>=0; i--){
            if(s[i]==')')
                right++;
            else{
                left++;
                if(left==right){
                    if(left+right>maxl)
                        maxl = left+right;
                }
                else if(left>right){
                    left = 0;
                    right = 0;
                }
            }
        }
        return maxl;
    }
};

45. 跳跃游戏 II

给定一个非负整数数组,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

示例:

输入: [2,3,1,1,4]

输出: 2

解释: 跳到最后一个位置的最小跳跃数是 2。从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

O(N)的解法有两种:贪心和动态规划

贪心

每一跳都跳在下一跳最远的位置

代码:

class Solution {
public:
    int jump(vector& nums) {
        if(nums.empty()) return 0;
        int maxp(0),end(0),step(0);
        for(int i=0; i

dp

dp[i]记录跳到第i位需要的最小的跳数
变量pos记录目前跳到的位置(即dp更新到的位置)
far记录第i位能跳到的最远位置
此时,如果far>pos, dp[pos:far] = dp[i]+1.

代码:

class Solution {
public:
    int jump(vector& nums) {
        int pos = 1;
        int n = nums.size();
        vector dp(n,0);
        int i=0;
        while(i=n) return dp[n-1];
            while(pos<=far){//更新pos~far
                dp[pos] = dp[i]+1;
                pos++;
            }
            i++;
        }
        return dp[n-1];
    }
};

679. 24点游戏

你有 4 张写有 1 到 9 数字的牌。你需要判断是否能通过 *,/,+,-,(,) 的运算得到 24。

示例 1:

输入: [4, 1, 8, 7]

输出: True

解释: (8-4) * (7-1) = 24

解法:四个数字,三个符号位,126244*4=9216种可能的情况,暴搜就完事了,O(1)时间复杂度,用递归就行了,一个运算符一层递归。

代码:

class Solution {
public:
    bool judgePoint24(vector& nums) {
        double a,b,c,d;
        a = nums[0];
        b = nums[1];
        c = nums[2];
        d = nums[3];
        return judgePoint24_4(a,b,c,d);
    }

    bool judgePoint24_1(double a){
        return abs(a-24)<1e-6;
    }

    bool judgePoint24_2(double a, double b){
        return
            judgePoint24_1(a+b)||
            judgePoint24_1(a-b)||
            judgePoint24_1(a*b)||
            judgePoint24_1(a/b)||
            judgePoint24_1(b-a)||
            judgePoint24_1(b/a);
    }

    bool judgePoint24_3(double a, double b, double c){
        return 
            judgePoint24_2(a+b,c)||
            judgePoint24_2(a-b,c)||
            judgePoint24_2(a*b,c)||
            judgePoint24_2(a/b,c)||
            judgePoint24_2(b-a,c)||
            judgePoint24_2(b/a,c)||
            
            judgePoint24_2(a+c,b)||
            judgePoint24_2(a-c,b)||
            judgePoint24_2(a*c,b)||
            judgePoint24_2(a/c,b)||
            judgePoint24_2(c-a,b)||
            judgePoint24_2(c/a,b)||
            
            judgePoint24_2(b+c,a)||
            judgePoint24_2(b-c,a)||
            judgePoint24_2(b*c,a)||
            judgePoint24_2(b/c,a)||
            judgePoint24_2(c-b,a)||
            judgePoint24_2(c/b,a);
    }

    bool judgePoint24_4(double a, double b, double c, double d){
        return
            judgePoint24_3(a+b,c,d)||
            judgePoint24_3(a-b,c,d)||
            judgePoint24_3(a*b,c,d)||
            judgePoint24_3(a/b,c,d)||
            judgePoint24_3(b-a,c,d)||
            judgePoint24_3(b/a,c,d)||
            
            judgePoint24_3(a+c,b,d)||
            judgePoint24_3(a-c,b,d)||
            judgePoint24_3(a*c,b,d)||
            judgePoint24_3(a/c,b,d)||
            judgePoint24_3(c-a,b,d)||
            judgePoint24_3(c/a,b,d)||
            
            judgePoint24_3(a+d,b,c)||
            judgePoint24_3(a-d,b,c)||
            judgePoint24_3(a*d,b,c)||
            judgePoint24_3(a/d,b,c)||
            judgePoint24_3(d-a,b,c)||
            judgePoint24_3(d/a,b,c)||
            
            judgePoint24_3(b+c,a,d)||
            judgePoint24_3(b-c,a,d)||
            judgePoint24_3(b*c,a,d)||
            judgePoint24_3(b/c,a,d)||
            judgePoint24_3(c-b,a,d)||
            judgePoint24_3(c/b,a,d)||
            
            judgePoint24_3(b+d,a,c)||
            judgePoint24_3(b-d,a,c)||
            judgePoint24_3(b*d,a,c)||
            judgePoint24_3(b/d,a,c)||
            judgePoint24_3(d-b,a,c)||
            judgePoint24_3(d/b,a,c)||
            
            judgePoint24_3(c+d,a,b)||
            judgePoint24_3(c-d,a,b)||
            judgePoint24_3(c*d,a,b)||
            judgePoint24_3(c/d,a,b)||
            judgePoint24_3(d-c,a,b)||
            judgePoint24_3(d/c,a,b);
    }
};

782. 变为棋盘

一个 N x N的 board 仅由 0 和 1 组成 。每次移动,你能任意交换两列或是两行的位置。

输出将这个矩阵变为 “棋盘” 所需的最小移动次数。“棋盘” 是指任意一格的上下左右四个方向的值均与本身不同的矩阵。如果不存在可行的变换,输出 -1。

示例:

输入: board = [[0,1,1,0],[0,1,1,0],[1,0,0,1],[1,0,0,1]]

输出: 2

解释:

一种可行的变换方式如下,从左到右:

  0110  1010  1010

  0110 --> 1010 --> 0101

  1001  0101  1010

  1001  0101  0101

第一次移动交换了第一列和第二列。

第二次移动交换了第二行和第三行。

解法:题目看起来复杂,其实只要分析清楚了就很简单,行列是正交的,所以可以分开计算代价,且方法一样。

判断方法很多,我这里用了代码较少的一种:任意矩形的四个角的格子必须都是1或者都是0,否则一定不能变成棋盘,因为四个角的关系通过换行和换列无法改变。

判断完之后就计算就行了,行和列只会有两种数列,而且是01互换的,所以只需要计算第一行和第一列的代价就行了。

计算方法:统计位置不对的格子数,然后算较小的一个(需要判断一下边长的奇偶情况,详见代码注释)。

代码:

class Solution {
public:
    int movesToChessboard(vector>& board) 
    {
        int n = board.size();
        for(int i=0;i(n+1)/2) return -1;
        if(col(n+1)/2) return -1;//判断1的个数是否符合要求
        int res=0;
        if(n%2==0)
        {//偶数格两种方法需要比较出较小的
            res+=min(cntrow,n-cntrow);
            res+=min(cntcol,n-cntcol);
        }
        else
        {//奇数格的话只有一种排法,因为只能变偶数格。
            if(cntrow%2==1)
                cntrow = n-cntrow;
            if(cntcol%2==1)
                cntcol = n-cntcol;
            res=cntrow+cntcol;
        }
        return res/2;
    }
};

你可能感兴趣的:(Leetcode,huawei,leetcode,数据结构,算法,动态规划,huawei)