开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情
[6180. 最小偶倍数]
做法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. 最长的字母序连续子字符串的长度]
方法:这里只需要理解清楚字母序连续字符串 的含义即可:
- 即: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;
}
};