力扣热题100Day04:10.正则表达式,11.盛最多水的容器

10.正则表达式(困难题)

题目链接:10. 正则表达式匹配 - 力扣(Leetcode)

思路:无思路

初步理解了思路10. 正则表达式匹配 - 力扣(Leetcode)

Java代码:(需回头细看)

class Solution {
    public boolean isMatch(String s, String p) {
        /*
        dp五部曲:
        设主串s的长度为m,设模式串p的长度为n;其中s只有小写字母,p有字母/./*
        1.状态定义:dp[i][j]为考虑s[0,i-1]与p[0,j-1]是否能匹配上,能匹配上就为true
        2.状态转移:若要求dp[i][j]就必须考虑到s[i-1]与p[j-1]
            2.1 当p[j-1]不是'*'时
                2.1.1 若s[i-1]==p[j-1]时,即p[j-1]为'a'-'z'且与s[i-1]相等,看dp[i-1][j-1]
                2.1.2 p[j-1] == '.'时,直接将'.'变成s[i-1],看dp[i-1][j-1]
                注意:这里的'.'是匹配一个字符,而不是一连串,如"a.b"->"axb"
            2.2 当p[j-1]是'*'时,主要看p[j-2]做判断
                2.2.1 p[j-2]为'a'-'z'并且p[j-2]==s[i-1],那么此时s继续往前看,p暂时不动
                    即:看dp[i-1][j]
                2.2.2 p[j-2]为'.',那么".*"可以变为"....."可以匹配s[i-1]前面的任何字符(万能串)
                    因此,直接看dp[i-1][j](或者直接返回true)
                2.2.3 剩下的就是p[j-2]为'a'-'z'且p[j-2]!=s[i-1],那么此时p的"x*"作废,看dp[i][j-2]
            这里:2.1.1与2.2.2可以看成一种情形:即s与p均前移一位
                2.2.1与2.2.2可以看成一种情形:即p不动s前移一位
        3.初始化:
            3.1 空的s
                3.1.1 空的p,空的s可以匹配空的p,因此dp[0][0]=true
                3.1.2 非空的p,空的s可能可以匹配非空的p,例如"a*",因此需要经过转移计算
            3.2 空的p
                3.2.1 空的s,同3.1.1
                3.2.2 非空的s,空的p不可能匹配非空的s,因此dp[i][0]=false,i∈[1,m]
            3.3 非空的s与非空的p:需要经过转移计算
            其中:3.1.1与3.2.2可以合并为dp[i][0]=i==0
        4.遍历顺序:显然是正序遍历
        5.返回形式:返回dp[m][n]就是考虑s[0,m-1]与p[0,n-1]是否能匹配上
        */
        int m = s.length(), n = p.length();
        boolean[][] dp = new boolean[m + 1][n + 1];
        // 初始化dp[i][0]
        // for(int i = 0; i <= m; i++) {
        //     dp[i][0] = i == 0;
        // }
        dp[0][0] = true;
        // i从0开始
        for(int i = 0; i <= m; i++) {
            // 注意j从1开始
            for(int j = 1; j <= n; j++) {
                if(p.charAt(j - 1) != '*') {
                    // 1.当p[j-1]不是'*'时(注意j已经从1开始了)
                    // 这里要注意运算优先级问题(加括号)
                    if(i >= 1 && (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '.')) {
                        // s与p均前移一位
                        dp[i][j] = dp[i - 1][j - 1];
                    }
                } else {
                    // 2.当p[j-1]是'*'时,主要看p[j-2]做判断
                    if(j >= 2 && i >= 1 && 
                    (p.charAt(j - 2) == s.charAt(i - 1) || p.charAt(j - 2) == '.')) {
                        // 看"x*":p不动s前移一位
                        dp[i][j] = dp[i - 1][j];
                    }
                    // 不看"x*":
                    // 剩下的为p[j-2]为'a'-'z'且p[j-2]!=s[i-1],那么此时p的"x*"作废,看dp[i][j-2]
                    if(j >= 2) {
                        dp[i][j] |= dp[i][j - 2];
                    }
                    // 这里的|=表示只要满足了其中一个条件就可以使得dp[i][j]==true
                    // 通俗一点的解释就是:当p[j-1]=='*'时,
                    // 若p[j-2]==s[i-1]||p[j-2]=='.',则dp[i][j]可以继承dp[i-1][j]:转移路径1
                    // 若p[j-2]!=s[i-1],则dp[i][j]可以继承dp[i][j-2]:转移路径2
                    // 满足任意一条转移路径就可以使得dp[i][j]=true
                }        
            }
        }
        // 所求即为考虑s[0,m-1]与p[0,n-1]是否能匹配上
        return dp[m][n];
    }
}

11.盛最多水的容器

题目链接:11. 盛最多水的容器 - 力扣(Leetcode)

思路:无思路

看完Krahets文章的思路: 文章链接 11. 盛最多水的容器 - 力扣(Leetcode)

(1)本质上是一个数学问题,相当于有两块板子,一个长板子,一个短板子,用双指针int i 和 int j分别表示长板子和短板子的位置,此时面积应该由短板子决定,就有S = Math.min(h[i],h[j]) X (j - i)

(2)在每个状态下,无论长板或短板向中间收窄一格,都会导致水槽 底边宽度 −1​ 变短:

若向内移动短板 ,水槽的短板 min(h[i],h[j]) 可能变大,因此下个水槽的面积 可能增大 
若向内移动长板 ,水槽的短板 min(h[i],h[j])不变或变小,因此下个水槽的面积 一定变小 

(3)因此,为了获取更大的面积,初始化双指针分列水槽左右两端,循环每轮将短板向内移动一格,并更新面积最大值,直到两指针相遇时跳出;即可获得最大面积

Java代码:

class Solution {
    public int maxArea(int[] height) {
        //先判断特殊情况
        if(height.length == 0 || height == null){
            return 0;
        }
        //定义双指针
        int left = 0;
        int right = height.length - 1;
        //定义面积,并且要实时更新
        int area = 0;
        while(left <= right){
            //先找到短板
            if(height[left] < height[right]){
                area = Math.max((height[left]*(right - left)),area);
                //移动短板
                left++;
            }
            else {
                area = Math.max((height[right]*(right - left)),area);
                //移动短板
                right--;
            }
        }
        return area;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值