- 字符串的最大公因子
其实就是对于两个字符串的长度 来取公约数 只要能当做两个整除的 就作为备选的
然后一个一个看 按照这些每一个长度 截取到字符串的前几个字符 作为公因子 假如以他们来填充 是对的 那么作为res 遍历完备选的长度 就可以了
class Solution {
public:
string gcdOfStrings(string str1, string str2) {
vector<int>temp;
int it;
int len1=str1.size();
int len2=str2.size();
for(it=1;it<=str1.size() && it<=str2.size();it++){
if(len1%it==0 && len2%it==0){
temp.push_back(it);
}
}
string res="";
for(auto c:temp){
string A,B;
string le=str1.substr(0,c);
for(int i=0;i<len1/c;i++){
A+=le;
}
for(int j=0;j<len2/c;j++){
B+=le;
}
if(str1==A && str2==B){
res=le;
}
}
return res;
}
};
- 复原IP地址
解题思路:
IP地址由32位二进制数组成,为便于使用,常以XXX.XXX.XXX.XXX形式表现,每组XXX代表小于或等于255的10进制数。所以说IP地址总共有四段,每一段可能有一位,两位或者三位,范围是[0, 255],题目明确指出输入字符串只含有数字,所以当某段是三位时,我们要判断其是否越界(>255),还有一点很重要的是,当只有一位时,0可以成某一段,如果有两位或三位时,像 00, 01, 001, 011, 000等都是不合法的,所以我们还是需要有一个判定函数来判断某个字符串是否合法。
这道题其实也可以看做是字符串的分段问题,在输入字符串中加入三个点,将字符串分为四段,每一段必须合法,求所有可能的情况。根据目前刷了这么多题,得出了两个经验,一是只要遇到字符串的子序列或配准问题首先考虑动态规划DP,二是只要遇到需要求出所有可能情况首先考虑用递归。这道题并非是求字符串的子序列或配准问题,更符合第二种情况,所以我们要用递归来解。我们用k来表示当前还需要分的段数,如果k = 0,则表示三个点已经加入完成,四段已经形成,若这时字符串刚好为空,则将当前分好的结果保存。若k != 0, 则对于每一段,我们分别用一位,两位,三位来尝试,分别判断其合不合法,如果合法,则调用递归继续分剩下的字符串,最终和求出所有合法组合。
所以这道题需要用递归来做
class Solution {
public:
vector<string> restoreIpAddresses(string s) {
vector<string> res;
helper(s, 0, "", res);
return res;
}
void helper(string s, int n, string out, vector<string>& res) {
if (n == 4) {
if (s.empty()) res.push_back(out);
} else {
for (int k = 1; k < 4; ++k) {
if (s.size() < k) break;
int val = stoi(s.substr(0, k));
if (val > 255 || k != std::to_string(val).size()) continue;
helper(s.substr(k), n + 1, out + s.substr(0, k) + (n == 3 ? "" : "."), res);
}
}
}
};
- 乘积最大子数组
这道题的原理就是他同时维持最大值和最小值
这两个值一旦遇到负数相乘 就交换
否则 不断乘
class Solution {
public:
int maxProduct(vector<int>& nums) {
int m_max=1;
int m_min=1;
int biggest=INT_MIN;
for(int i=0;i<nums.size();i++){
if(nums[i]<0){
int temp=m_min;
m_min=m_max;
m_max=temp;
}
m_max=max(nums[i],m_max*nums[i]);
m_min=min(nums[i],m_min*nums[i]);
biggest=max(biggest,m_max);
}
return biggest;
}
};