最小偶倍数&&最长的字母序连续子字符串的长度

172 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情

[6180. 最小偶倍数]

leetcode.cn/problems/sm…

image-20220918191003491

做法1:可以先求2和n的最大公约数, 最小公倍数 = (2*n)/最大公约数

class Solution {
public:
    int gcd(int a,int b)
    {
        return a%b == 0?b:gcd(b,a%b);//辗转相除法
    }
    int smallestEvenMultiple(int n) 
    {
        int x = gcd(2,n);//求出2和n的最大公约数
        return 2*n/x;//最小公倍数 = a*b/最大公约数    
    }
};

做法2:观察规律:

如果n是奇数,那么n和2的最小公倍数 就是 n*2

如果n是偶数,那么n和2的最小公倍数 就是 n

class Solution {
public:
    int smallestEvenMultiple(int n) 
    {
        return n&1?n*2:n;
    }
};

[6181. 最长的字母序连续子字符串的长度]

leetcode.cn/problems/le…

image-20220918191755407

方法:这里只需要理解清楚字母序连续字符串 的含义即可:

  • 即:str[i] == str[i-1]+1 前后字符的asicc码相差1

想到子字符串->联想以i位置结尾时候的单 -> 所以可以暴力枚举以每个字符开头的情况

  • 直接i指针控制起始位置,j指针控制连续字符串的位置,遍历即可
  • 左指针指向连续字符串开始的位置,右指针指向结束的位置, 右指针在右移的过程中统计字符串的长度,最终结果取最大的
class Solution {
public:
    int longestContinuousSubstring(string s) {
        int ans = 0;
        for(int i = 0;i<s.size();i++)
        {
            int j = i+1;
            while(j<s.size() && s[j] == s[j-1]+1) //判断前后字符的字母序是否连续
            {
                j++;
            }
            ans = max(ans,j-i); //此时连续的字母序的范围就是[i,j) 长度为:j-i
        }
        return ans;
    }
};

方法2: 这里也可以使用dp的思路:

和最长递增子序列相似, 这里的 dp[i]的含义是:以i位置结尾的最长字母序的连续子串长度是多长

注意:每个位置的最长字母序至少也是1,即只含有自己一个字符,所以dp表初始化为全1

class Solution {
public:
    int longestContinuousSubstring(string s) {
        if(s.size() == 1) return 1;
        int n = s.size();
        vector<int> dp(n,1);//dp[i]的含义是:以i位置结尾的最长字母序的连续子串长度是多长
        int ans = 0;
        //遍历字符串
        for(int i = 1;i<n;i++)
        {
            //当前字符和前一个字符构成字母序
            if(s[i] == s[i-1]+1) 
                dp[i] = dp[i-1]+1;//当前i位置结尾的..长度=前一个位置结尾的...长度 + 1(当前字符)
            ans = max(ans,dp[i]);
        }
        return ans;
    }
};

优化:由于当前位置的答案之和前面一个位置的答案有关,所以这里我们并不需要定义一个完整的数组,只需要用一个变量进行迭代即可

class Solution {
public:
    int longestContinuousSubstring(string s) {
        if(s.size() == 1) return 1;
        int ans = 0;
        int dp = 1;//长度至少也是1
        for(int i = 1;i<s.size();i++)
        {
            //当前字符和前一个字符构成字母序
            if(s[i] == s[i-1] + 1)  dp+=1;
            else dp = 1; //字母序中断,重开!
            ans = max(ans,dp);
        }
        return ans;
    }
};