剑指Offer(第二版):43. 1~n 整数中 1 出现的次数 19. 正则表达式匹配

sdas在这里插入图片描述
sddsdsssdsas在这里插入图片描述

/**
解题思路:找规律的题,首先我们要找每一位出现1的个数,然后考虑每一位'0'~'9'不同时,分别对应的1的个数的计算公式,然后遍历所有位,这道题可以看题解,讲解的很好。
我们令当前位为cur,然后低于他的位为low,高于他的位为high,dight为cur对应的10^cur

    当cur==0, 1的个数为 high*dight

    当cur==1, 1的个数为high*dight+low+1

    当cur=2~9,1的个数为(high+1)*dight

    然后初始值
    high = n/10  , low =0 , cur=hig%10, dight=1

    遍历所有位怎么结束的呢?当high==0,且cur==0时,则结束

    递归方程:

    low += cur*dight    cur = hight%10 high/=10  dight *= 10
 */
class Solution {
    public int countDigitOne(int n) {
        
        //初始值
        int low = 0 , cur = n%10 , high = n/10 , dight=1;
        //返回值
        int res=0;

        //遍历位置
        while(high!=0 || cur!=0){
            //计算值
            if(cur == 0)
                res += high*dight;
            else if(cur == 1)
                res += high*dight+low+1;
            else   
                res += (high+1)*dight;
            //转移方程
            low += cur*dight;
            cur = high%10;
            high /= 10;
            dight *= 10;
        }
        return res;
    }
}

在这里插入图片描述

/**
解题思路:第四遍了 , 动态规划dp[i][j],p的前j个字符能否匹配前i个字符
    首先是边界值:dp[0][j],只有"x*x*这样的情况才为true"
    接下来考虑转移方程:

        1、当p.charAt(j)>='a'&&p.charAt(j)<='z',则如果p.charAt(j)==s.charAt(j),则dp[i][j] = dp[i-1][j-1];
        2、当p.charAt(j) = '.' , dp[i][j] = dp[i-1][j-1]
        3、当p.charAt(j) = '*' :
            3.1   当*匹配0个, dp[i][j] = dp[i][j-2]
            3.2   当*匹配1个(其实也对应着多个), 如果p.charAt(j-1)==s.charAt(i) dp[i][j] = dp[i-1][j]
            3.3   当p.charAt(j-1) = '.' , 则dp[i][j] = dp[i-1][j]
 */
class Solution {
    public boolean isMatch(String s, String p) {
        int sLen = s.length();
        int pLen = p.length();
        //if(sLen==0 || pLen ==0) return false; //这是错的!!!比如:s="" p =".*"

        boolean[][] dp = new boolean[sLen+1][pLen+1];

        //边界
        dp[0][0] = true;

        for(int i=2 ; i<=pLen ; i++){
            if(p.charAt(i-1) == '*'){
                dp[0][i] = dp[0][i-2];
            }
        }
        //转移方程
        for(int i=1 ; i<=sLen ; i++){
            for(int j=1 ; j<= pLen ; j++){
                int sCurChar = s.charAt(i-1);       //技巧,因为我们要比较大小,所以我们要将其转换成int
                int pCurChar = p.charAt(j-1);
                //开始判断  前两种情况可以结合起来,
                if(pCurChar == '.' || sCurChar == pCurChar)
                    dp[i][j] = dp[i-1][j-1];
                else if(pCurChar == '*'){    //然后开始判断'*'的情况
                    //0个的情况
                    if(dp[i][j-2])
                        dp[i][j] = dp[i][j-2];
                    else if(sCurChar == p.charAt(j-2) || p.charAt(j-2) == '.')
                        dp[i][j] = dp[i-1][j];
                } 
            }
        }
        return dp[sLen][pLen];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值