LeetCode 第 149 场周赛 【一年中的第几天】【掷骰子的N种方法】【单字符重复子串的最大长度】

1154. 一年中的第几天

给你一个按 YYYY-MM-DD 格式表示日期的字符串 date,请你计算并返回该日期是当年的第几天。

通常情况下,我们认为 1 月 1 日是每年的第 1 天,1 月 2 日是每年的第 2 天,依此类推。每个月的天数与现行公元纪年法(格里高利历)一致。
示例 1:

输入:date = "2019-01-09"
输出:9

示例 2:

输入:date = "2019-02-10"
输出:41

示例 3:

输入:date = "2003-03-01"
输出:60

示例 4:

输入:date = "2004-03-01"
输出:61

注意:
能被4整除但不能被100整除的年份为普通闰年。
能被400整除的为世纪闰年。
即闰年是能被4整除但是不能被100整除,或者能被400整除。

代码:

	public int dayOfYear(String date) {
        String[] str = date.split("-");
        int[] data = new int[str.length];
        for (int i = 0; i < str.length; i++) {       
            data[i] = Integer.valueOf(str[i]);
        }
        int sum=0;
        int Mon=data[1];
        int Year=data[0];
        int Day=data[2];
        switch(Mon){
            case 12:sum += 30;
            case 11:sum += 31;
            case 10:sum += 30;
            case 9 :sum += 31;
            case 8 :sum += 31;
            case 7 :sum += 30;
            case 6 :sum += 31;
            case 5 :sum += 30;
            case 4 :sum += 31;
            case 3 :
                if((Year % 4 == 0 && Year % 100 != 0) || (Year % 400 == 0)){
                    //System.out.println("这一年是闰年!");
                    sum += 29;
                }
                else{
                    //System.out.println("这一年是平年!");
                    sum += 28;
                }
            case 2 :sum += 31;
            case 1 :sum += Day;
        }
        System.out.println(sum);
        return sum;
    }

1155. 掷骰子的N种方法

这里有 d 个一样的骰子,每个骰子上都有 f 个面,分别标号为 1, 2, …, f。

我们约定:掷骰子的得到总点数为各骰子面朝上的数字的总和。

如果需要掷出的总点数为 target,请你计算出有多少种不同的组合情况(所有的组合情况总共有 f^d 种),模 10^9 + 7 (10000000007)后返回。
示例 1:

输入:d = 1, f = 6, target = 3
输出:1

示例 2:

输入:d = 2, f = 6, target = 7
输出:6

示例 3:

输入:d = 2, f = 5, target = 10
输出:1

示例 4:

输入:d = 1, f = 2, target = 3
输出:0

示例 5:

输入:d = 30, f = 30, target = 500
输出:222616187

提示:

1 <= d, f <= 30
1 <= target <= 1000

思路:dp
dp[i][j]表示投第i个骰子表示值为j的次数
假如第i+1个骰子扔值为d,那么转移方程:dp[i+1][j]=dp[i][j-d] (j-d>=0)
dp[0][0]=1表示刚开始还没有扔,和为0,这种情况只有1种。

代码:

	//int MOD=10000000007;
    int mod = (int)1e9+7;
    int numRollsToTarget(int d, int f, int target) {
        // dp表示投第i个骰子表示值为j的次数
        int [][]dp=new int [35][1000];
        dp[0][0]=1;
        for(int i=1;i<=d;i++){
            for(int now=1;now<=f;now++){
                for(int pre=0;pre+now<=target;pre++){
                    dp[i][pre+now]=(dp[i][pre+now]+dp[i-1][pre]);
                    if(dp[i][pre+now]>=mod){
                        dp[i][pre+now]%=mod;
                    }
                }
            }
        }
        return dp[d][target];
    }  

1156. 单字符重复子串的最大长度

如果字符串中的所有字符都相同,那么这个字符串是单字符重复的字符串。

给你一个字符串 text,你只能交换其中两个字符一次或者什么都不做,然后得到一些单字符重复的子串。返回其中最长的子串的长度。
示例 1:

输入:text = "ababa"
输出:3

示例 2:

输入:text = "aaabaaa"
输出:6

示例 3:

输入:text = "aaabbaaa"
输出:4

示例 4:

输入:text = "aaaaa"
输出:5

示例 5:

输入:text = "abcdef"
输出:1

思路:使用区间法(双指针),区间中可以容忍一个字符不是目标字符

代码:

	public int maxRepOpt1(String text) {
        // 首先统计每个字符的数量,记录在数组中
        int []cnt=new int[30];
        for(int i=0;i<text.length();i++){
            cnt[text.charAt(i)-'a']++;
        }
        int ans=0;
        for(char c='a';c<='z';c++){
            // 使用双指针 now:区间中目标字母个数,other:区间中非目标字母个数
            int i=c-'a',l=0,now=0,other=0;
            for(int r=0;r<text.length();r++){
                // 区间重置,初始化
                if(l==r){
                    now=other=0;
                }
                // r右指针当前就是目标字符,now++,否则分两种情况
                if(text.charAt(r)==c){
                    ++now;
                }else{
                    // 1.区间内暂时全是目标字符,那么可以将当前非目标字符加入
                    // 2.区间内已经有一个非目标字符,那么循环从左边开始遍历,直到将那个非目标字符删除之后,再将当前非目标字符加入
                    while(other>=1&&l<r){
                        if(text.charAt(l)==c){
                            --now;
                        }else{
                            --other;
                        }
                        l++;
                    }
                    // 加入这个新的非目标字符
                    ++other;
                }
                // 1.如果区间内包含了所有的字符,所以不能再交换,那么当前结果就是为cnt[i]
                // 2.区间还不是包含所有字符,更新长度
                ans=Math.max(ans,Math.min(cnt[i],r-l+1));
            }
            
        }
        return ans;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值