题目描述
- 旋转字符串
给定两个字符串, A 和 B。
A 的旋转操作就是将 A 最左边的字符移动到最右边。 例如, 若 A = ‘abcde’,在移动一次之后结果就是’bcdea’ 。如果在若干次旋转操作之后,A 能变成B,那么返回True。
示例 1:
输入: A = ‘abcde’, B = ‘cdeab’
输出: true
示例 2:
输入: A = ‘abcde’, B = ‘abced’
输出: false
注意:
A 和 B 长度不超过 100。
思路&代码:
最开始的思路:直接匹配,暴力遍历每一种。
class Solution {
public boolean rotateString(String s, String goal) {
if(s.length()!=goal.length())return false;
if(s.length()>100||goal.length()>100)return false;
if((s.length()==0&&goal.length()==0))return true;
for(int i=0;i<s.length();i++){
if(s.compareTo(goal)==0)return true;
char temp = s.charAt(0);
s=s.substring(1);
s=s+temp;
}
return false;
}
}
很简单,用Java提供的字符串处理函数一个个的把字符向后移,直到找到匹配或字符串移回原样。
优化思路:
class Solution {
public boolean rotateString(String s, String goal) {
if(s.length()!=goal.length())return false;
if(s.length()>100||goal.length()>100)return false;
if((s.length()==0&&goal.length()==0))return true;
int j=0;
for(int i=s.length();i>0;i--) {
if(s.equals(goal))return true;
if(s.charAt(j)==goal.charAt(0)) {
String ss = s.substring(0, j);
s = s.substring(j);
s += ss;
j=0;
}
j++;
}
/*由于在最后缺少一次匹配,在这里补上。
在循环里再加一次会让J越界*/
if(s.equals(goal))return true;
return false;
}
}
没什么值得注意的地方,简单讲就是在字符串s中找到和goal首字母相同的字母后再对s做旋转和比较。
答案思路:
思路一
class Solution {
public boolean rotateString(String A, String B) {
return A.length() == B.length() && (A + A).contains(B);
}
}
作者:LeetCode
链接:https://leetcode-cn.com/problems/rotate-string/solution/xuan-zhuan-zi-fu-chuan-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
这个比我第一种更暴力。直接将A复制一次再在AA中招子串。
思路二
class Solution {
public boolean rotateString(String A, String B) {
int N = A.length();
if (N != B.length()) return false;
if (N == 0) return true;
//Compute shift table
int[] shifts = new int[N+1];
Arrays.fill(shifts, 1);
int left = -1;
for (int right = 0; right < N; ++right) {
while (left >= 0 && (B.charAt(left) != B.charAt(right)))
left -= shifts[left];
shifts[right + 1] = right - left++;
}
//Find match of B in A+A
int matchLen = 0;
for (char c: (A+A).toCharArray()) {
while (matchLen >= 0 && B.charAt(matchLen) != c)
matchLen -= shifts[matchLen];
if (++matchLen == N) return true;
}
return false;
}
}
作者:LeetCode
链接:https://leetcode-cn.com/problems/rotate-string/solution/xuan-zhuan-zi-fu-chuan-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
KMP算法。不赘述。
思路三:
import java.math.BigInteger;
class Solution {
public boolean rotateString(String A, String B) {
if (A.equals(B)) return true;
int MOD = 1_000_000_007;
int P = 113;
int Pinv = BigInteger.valueOf(P).modInverse(BigInteger.valueOf(MOD)).intValue();
long hb = 0, power = 1;
for (char x: B.toCharArray()) {
hb = (hb + power * x) % MOD;
power = power * P % MOD;
}
long ha = 0; power = 1;
char[] ca = A.toCharArray();
for (char x: ca) {
ha = (ha + power * x) % MOD;
power = power * P % MOD;
}
for (int i = 0; i < ca.length; ++i) {
char x = ca[i];
ha += power * x - x;
ha %= MOD;
ha *= Pinv;
ha %= MOD;
if (ha == hb && (A.substring(i+1) + A.substring(0, i+1)).equals(B))
return true;
}
return false;
}
}
作者:LeetCode
链接:https://leetcode-cn.com/problems/rotate-string/solution/xuan-zhuan-zi-fu-chuan-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
哈希算法,这个很有意思,哈希函数采用的是:hash(S) = (S[0] * P ** 0 + S[1] * P **1 + S[2] * P **2 + …) % MOD。然后计算出A和B的hash值进行比较。hash值相等则认为两串相等。感觉本质上还是暴力穷举,但是用数学减少了穷举的代价,每次旋转只需要计算:
A_newhash = (A_hash - S[0]) / P + S[0]*P **n
即可,不需要每次都对字符串进行比较。
( ** 表示次方,同^)