题目
给定两个字符串, s 和 goal。如果在若干次旋转操作之后,s 能变成 goal ,那么返回 true 。
s 的 旋转操作 就是将 s 最左边的字符移动到最右边。
例如, 若 s = ‘abcde’,在旋转一次之后结果就是’bcdea’ 。
题解
这道题本身不是很难,但是从不同的解法中可以收获不少知识
方法一
这里我采取的是 用s[0]作为标准点,在goal字符串从后到前遍历找出相同的字符的位置pos, 这里就可以用pos将字符串分成两半了,判断 s的前半段是否等于 goal的后半段, s的后半段是否等于goal的前半段
class Solution {
private:
bool satisfy(string& s,string& goal,int pos,int len){
return s.substr(0,len-pos) == goal.substr(pos,len-pos) &&s.substr(len-pos,pos) == goal.substr(0,pos) ;
}
public:
bool rotateString(string s, string goal) {
if(s.length() != goal.length()) return false;
int len = s.length();
for(int i = len - 1;i>=0;i--){
if(goal[i] != s[0]) continue;
if(satisfy(s,goal,i,len)) return true;
}
return false;
}
};
方法二
这个旋转的操作就类似于圆环问题,有个数学关系, 设旋转i位,那么goal[j]的位置对应的是s[(j+i)%len], 这里旋转的位数从0到n遍历一次,如果满足条件就 return true
class Solution {
public:
bool rotateString(string s, string goal) {
int len = s.length();
if(len != goal.length()) return false;
for(int i = 0;i<len;i++){
bool flag = true;
for(int j = 0; j<len;j++){
if(s[(i+j)%len] == goal[j]) continue;
flag = false;
break;
}
if(flag) return true;
}
return false;
}
};
方法三
这个方法我感觉是非常巧妙的,因为无论你怎么旋转, 两个原字符串拼接必定包含goal字符,所以代码如下
class Solution {
public:
bool rotateString(string s, string goal) {
return s.length() == goal.length() && (s+s).find(goal) != string::npos;
}
};