一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情。
一、题目
leetcode 旋转字符串
给定两个字符串, s 和 goal。如果在若干次旋转操作之后,s 能变成 goal ,那么返回 true 。
s 的 旋转操作 就是将 s 最左边的字符移动到最右边。
例如, 若 s = 'abcde',在旋转一次之后结果就是'bcdea' 。
示例 1:
输入: s = "abcde", goal = "cdeab"
输出: true
示例 2:
输入: s = "abcde", goal = "abced"
输出: false
提示:
1 <= s.length, goal.length <= 100
s 和 goal 由小写英文字母组成
二、题解
方法一
要使字符串s经过若干次操作变为字符串goal,那么字符串s和字符串goal的长度必定要相等,所以如果这两个字符串不相等可以直接返回false。如果s旋转之后会与goal相等,那么在s中肯定能找到一段子字符串与goal的中前一段子字符串相等,其余的可能需要从
s的前一段子字符串查询。所以我们可以遍历字符串s的字符,首先需要找到s中一个字符与goal的第一个字符相等的位置,如果找不到就返回false,否则就先记录下s中这个字符位置为mark,然后我们用一个p指针来遍历字符串goal,遍历过程中我们将与字符串
s中的mark之后的字符匹配,即s[mark + p] == goal[p]。然后当mark + p超出字符串s的长度时,我们就需要从新到字符串s的第一个字符开始匹配了。最后匹配完发现p指向goal字符串最后位置,说明完全匹配直接返回true,否则需要继续遍历字符串s。
方法二
方法一的操作可能不太好理解,方法一其实是逐个字符来匹配,那么可以稍微优化一下,用整个字符串来比较。同样的首先需要判断字符串s和字符串goal的长度,不相等直接返回false。否则我们遍历字符串s找到其中一个字符与字符串goal第一个字符相等的位置i。
然后我们将字符串s中位置i之后的子字符串与i位置之前的子字符串重新拼接上,相当于在字符串s的位置i上就行了翻转得到一个新字符串,然后将其与字符串goal匹配比较,相等直接返回true,否则继续遍历字符串s来进行这个判断操作,遍历完了就是没有匹配上
返回fals。
方法三
通过前面两次比较,可以发现一个骚操作,前提是字符串s不要太长,否则效率不太好。因为字符串s进行旋转的操作就是头部的字符移动到尾部,所以我们可以将字符串s与字符串s进行拼接获得一个两倍s长度的新字符串ss,那么在字符串s的任意次的旋转之后必定
存在于ss的一个子字符串,所以可以直接判断字符串goal是否是ss的一个子字符串,是说明能匹配返回true,否则返回false。
三、代码
方法一 Java代码
class Solution {
public boolean rotateString(String s, String goal) {
int len1 = s.length();
int len2 = goal.length();
if (len1 != len2) {
return false;
}
int p;
for (int i = 0; i < len1; i++) {
p = 0;
if (s.charAt(i) == goal.charAt(p)) {
int mark = i;
// 往后面匹配看看
while (p < len2 && s.charAt(mark + p) == goal.charAt(p)) {
p++;
if (mark + p >= len1) {
mark = -p;
}
}
if (p == len2) {
return true;
}
}
}
return false;
}
}
时间复杂度:O(n^2),需要循环遍历判断两个字符串的字符。
空间复杂度:O(1),只需常数个空间变量。
方法二 Java代码
class Solution {
public boolean rotateString(String s, String goal) {
int len1 = s.length();
int len2 = goal.length();
if (len1 != len2) {
return false;
}
for (int i = 0; i < len1; i++) {
if (s.charAt(i) == goal.charAt(0)) {
String s2 = s.substring(i) + s.substring(0, i);
if (s2.equals(goal)) {
return true;
}
}
}
return false;
}
}
时间复杂度:O(n),需要循环遍历一次s字符串(不考虑库函数)。
空间复杂度:O(n),可能会拼接生成多个新字符串。
方法三 Java代码
class Solution {
public boolean rotateString(String s, String goal) {
if (s.length() != goal.length()) {
return false;
}
return (s + s).contains(goal);
}
}
时间复杂度:O(1),(不考虑库函数)。
空间复杂度:O(n),生成一个两倍s的新字符串。