想法给定两个字符串,
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
由小写英文字母组成
这题简单啊,不就不直接模拟吗?等等,先看一下会不会超时,哦,长度都在100以内,那没事了。
搞起来!(java的StringBuffer不太熟悉,先用python试试)
class Solution:
def rotateString(self, s: str, goal: str) -> bool:
sLs = list(s) # 字符串转换成列表,便于 *** 作
for i in range(len(sLs)-1): # n-1轮,每一轮移除第一个字符,然后加到末尾
a = sLs[0]
sLs.remove(sLs[0])
sLs.append(a)
if "".join(sLs)==goal: # 将列表中的元素合成字符串,判断一下是否与goal相同
return True
return False
提交,过了!
托这次规模比较小的福,用时28ms,打败了96%的人!(可能也没多少人用python写。
。
。
)
但,应该还有更加智慧的解法!
于是我去看了一下官方。
哦,原来s和goal的长度还可以不一样啊。
。
。
(方法一不赘述,本质上还是匹配字符串,只是写得比较高级,用了循环队列的mod运算)
方法二:搜索子字符串
首先,如果 s 和 goal 的长度不一样,那么无论怎么旋转,s 都不能得到 goal,返回 false。
字符串 s + s 包含了所有 s 可以通过旋转 *** 作得到的字符串,只需要检查 goal 是否为 s + s 的子字符串即可。
这里用到了一个很巧妙的思路,将s所有旋转可能得到的字符串都包含在了一个更大的字符串里,即s+s,这样j就省去了每次变换s的 *** 作。
class Solution{
public boolean rotateString(String s,String goal){
//先判断s和goal的长度是否相等,再判断s+s中是否包含goal
return s.length()==goal.length() && (s+s).contains(goal);
}
}
今天主要还是学习了这个contains()函数的用法,有些库函数确实有必要去学习记忆,无需所有功能都自己去手写实现。
后记:
不过官方(还有很多大佬)是如何想到这个s+s字符串的呢?为什么我只想到了简单的模拟,而没有跳到更高一层去看待这个问题呢?
一方面是由于我的经验没有那些大佬丰富,没有太多这种数据的直觉。
官方出题自然是按照自己的套路出,为了体现一种想法而特意设计的一个题目。
但我们还是得来看看这里面的思维过程,如何从简单的模拟跳到高层次的更大的字符串:
首先我们如果在脑子中模拟的话,会发现,一个 长度为n的字符串s,如果一直在旋转(将首字符移到末尾),那么经过n次,必然会恢复成原来的字符串,也就是说,我们其实只要进行n-1次旋转,即可遍历s的所有状态,这是模拟的思路。
那么,如果我们把字符串想象在一个模具里,每次旋转都是将第一个字符拿到最后的位置,则容易发现,这个模具如果想表示字符串的所有状态,那么它最短的长度就是2n,也即s+s,这里面可能涉及到了函数里的最小正周期的概念。
但最重要的,我们首先得要有这样一种思想 :将所有有限的可能性都包含在一个可 *** 作的区域内, 这样第二种解法的萌芽才会在脑海中生根。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)