LeetCode-Weekly Contest 149

1154. 一年中的第几天

https://leetcode-cn.com/classic/problems/ordinal-number-of-date/description/

给你一个按 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

提示:
date.length == 10
date[4] == date[7] == '-',其他的 date[i] 都是数字。
date 表示的范围从 1900 年 1 月 1 日至 2019 年 12 月 31 日。

分别求出年月日,再做闰年的判断,时间一加就好了

class Solution {
public:
    int dayOfYear(string date) {
        int ms[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
        int ans=0;
        int y = stoi(date.substr(0,4));
        int m = stoi(date.substr(5,2));
        int d = stoi(date.substr(8));
        if((y%4==0&&y%100!=0)||y%400==0) ms[2]++;
        for(int i=1;i<m;i++) ans+=ms[i];
        ans+=d;
        return ans;
    }
};

1155. 掷骰子的N种方法

https://leetcode-cn.com/classic/problems/number-of-dice-rolls-with-target-sum/

这里有 d 个一样的骰子,每个骰子上都有 f 个面,分别标号为 1, 2, ..., f。
我们约定:掷骰子的得到总点数为各骰子面朝上的数字的总和。
如果需要掷出的总点数为 target,请你计算出有多少种不同的组合情况(所有的组合情况总共有 f^d 种),模 10^9 + 7 后返回。

示例 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[m][n]表示用了m个筛子后的总点数n,

所以dp[i][j]可以由dp[i-1][j-k]得到,其中,k为筛子可掷的点数

class Solution {
public:
    int numRollsToTarget(int d, int f, int target) 
    {
        int mod = 1e9 + 7;
        int dp[d+2][target+2];
        memset(dp,0,sizeof(dp));
        dp[0][0]=1;
        for(int i=1;i<=d;i++)
        {
            for(int j=1;j<=target;j++)
            {
                for(int k=1;k<=f && k<=j;k++) dp[i][j] = (dp[i][j]+dp[i-1][j-k])%mod;
            }
        }
        return dp[d][target];
    }
};

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

https://leetcode-cn.com/classic/problems/swap-for-maximum-repeated-substring/description/

如果字符串中的所有字符都相同,那么这个字符串是单字符重复的字符串。
给你一个字符串 text,你只能交换其中两个字符一次或者什么都不做,然后得到一些单字符重复的子串。返回其中最长的子串的长度。

示例 1:
输入:text = "ababa"
输出:3
示例 2:
输入:text = "aaabaaa"
输出:6
示例 3:
输入:text = "aaabbaaa"
输出:4
示例 4:
输入:text = "aaaaa"
输出:5
示例 5:
输入:text = "abcdef"
输出:1

提示:
1 <= text.length <= 20000
text 仅由小写英文字母组成。

这道题我是先遍历一遍求出每个字母的数量nums,用count记录当前遍历字母的连续数量,k表示交换情况,maxx为结果。

因为题目要求只能交换一次,那么肯定要换过来相同的字母才有更大的连续数量,我们可以考虑这一次交换有什么情况,

  1. 交换后右边是不同的字母,maxx只能在交换前的数量上加1
  2. 交换后右边是相同的字母,可以继续往右边计算

如果直接在字符串里交换,不便于后续遍历,我们可以考虑用k来记录是否交换过字母,然后跳过这一位(本来这里要判断count<nums才进行交换,但由于我的写法,在最后一位的判断中其实把这里包含了,此处可默认为都能跳一次)从后一位接着计算连续count,然后注意最后边界值的处理

class Solution {
public:
    int maxRepOpt1(string text) 
    {
        int nums[26],maxx=0,count=0,k=0;
        int N=text.length();
        memset(nums,0,sizeof(nums));
        for(int i=0;i<N;i++) nums[text[i]-'a']++;
        for(int i=0;i<N;i++)
        {
            int x = text[i];
            count = 1;
            k=0;
            // printf("\ni=%d ,x=%c\n",i,x);
            for(int j=i+1;j<=N;j++)
            {
                if(j!=N && x==text[j]) count++;
                else if(k || j>=N-1) 
                {
                    if(count<nums[x-'a']) count++;
                    maxx = max(count,maxx);
                    break;
                }
                else
                {
                    k=1;
                }
                // printf("j=%d ,text[j]=%c,count=%d,k=%d\n",j,text[j],count,k);
            }
        }
        return maxx;
    }
};


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。