必须掌握的超高频旋转算法题目!

今天是小浩算法 “365刷题计划” 第103天。分享的这道题虽然很简单,但是在笔试或者面试当中,出现的频率却非常高。

01

PART

旋转字符串

经典常考类算法题目。

第796题:给定两个字符串, 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。

题意还是很容易理解的,说白了就是每次把前面的元素放到最后面:

02

PART

题解分析

这道题目看起来简单,但其实很容易出错。

这道题目最容易想到的解法,其实就是跟着题意来。每次将旋转后的A和目标串对比:

//java
class Solution {
    public boolean rotateString(String A, String B) {
        if (A.equals("") && B.equals("")) {
            return true;
        }
        int len = A.length();
        for (int i = 0; i < len; i++) {
            String first = A.substring(0, 1);
            String last = A.substring(1, len);
            A = last + first;
            if (A.equals(B)) {
                return true;
            }
        }
        return false;
    }
}

但是代码其实并不优雅,我们继续观察一下这个字符串:

无论它怎样旋转,最终的 A + A 包含了所有可以通过旋转操作从 A 得到的字符串:

那我们是不是只需要判断 B 是否为 A + A 的子串就可以了:

//java
class Solution {
    public boolean rotateString(String A, String B) {
        return A.length() == B.length() && (A + A).contains(B);
    }
}

一般面试写的话,基本就是到这个程度。但是大概率面试官这时还会问你一个问题:如何继续进行优化?

注意我们上面问题,其实已经转化为了:判断 B 是否为 A + A 的子串。那我们就可以引申答出 KMP,SUNDAY,BF 等字符串匹配策略。(当然,这里其实 SUNDAY 并不是特别适合)

然后就是用相应的匹配策略,来实现转化后的问题。

这里附上一份 KMP 解题代码:

 1//java
 2class Solution {
 3    public boolean rotateString(String A, String B) {
 4        int N = A.length();
 5        if (N != B.length()) return false;
 6        if (N == 0) return true;
 7
 8        int[] shifts = new int[N+1];
 9        Arrays.fill(shifts, 1);
10        int left = -1;
11        for (int right = 0; right < N; ++right) {
12            while (left >= 0 && (B.charAt(left) != B.charAt(right)))
13                left -= shifts[left];
14            shifts[right + 1] = right - left++;
15        }
16
17        //Find match of B in A+A
18        int matchLen = 0;
19        for (char c: (A+A).toCharArray()) {
20            while (matchLen >= 0 && B.charAt(matchLen) != c)
21                matchLen -= shifts[matchLen];
22            if (++matchLen == N) return true;
23        }
24        return false;
25    }
26}

这个有兴趣可以看看,代码是 leetcode 官方的。

03

PART

算法小知识

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n)。

大家有兴趣可以看我之前写的一篇KMP教程:

这可能是全网最简单的KMP了


好好学习

天天向上

和大家唠唠关于图的基础知识(一)

漫画:六九式是一道简单有趣的算法题(开车...)

漫画:常考的荷兰国旗问题你还不会吗?(初级)

如果你问我对学习算法有什么建议,这篇文章是必看的:

漫画:小白为了面试如何刷题?(呕心沥血算法指导篇)

漫画:呕心泣血算法指导篇(真正的干货,怒怼那些说算法没用的人)

 小浩算法,每日

关注领取《图解算法题》高清版

进群的小伙伴请加右侧私人微信(备注:进群)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值