LeetCode 0028 -- 实现strStr()

实现strStr()

题目描述

示例 1:

输入: haystack = "hello", needle = "ll"
输出: 2

示例 2:

输入: haystack = "aaaaa", needle = "bba"
输出: -1

说明:

needle是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当needle是空字符串时我们应当返回 0 。这与C语言的strstr()以及 Java的indexOf()定义相符。

解题思路

个人AC

声明两个游标hcnc

  • hchaystack cursor,用来辅助遍历字符串haystack
  • ncneedle cursor,用来辅助遍历字符串needle
class Solution {
    public int strStr(String haystack, String needle) {
        int hc = 0, nc = 0; // c即cursor,用来辅助遍历字符串
        int hLen = haystack.length(), nLen = needle.length();
        if (hLen < nLen) return -1;
        if (hLen == 0 && nLen == 0) return 0;
        
        while (hc < hLen) {
            int hRestC = hc;
            while (hRestC < hLen) {
                if (nc == nLen) return hc;
                
                char cOfH = haystack.charAt(hRestC), cOfN = needle.charAt(nc);
                if (cOfH == cOfN) {
                    hRestC++;
                    nc++;
                } else {
                    hc++;
                    nc = 0;
                    break;
                }
            }
        }
        return -1;
    }
}

时间复杂度: O ( n 2 ) O(n^2) O(n2)

空间复杂度: O ( 1 ) O(1) O(1)

最优解

Sunday

Sunday匹配机制

  • 目标字符串:haystacktarget
  • 模式串:needlepattern
  • 当前查询索引:idx(初始为0);
  • 待匹配字符串:target.substring(idx, idx + pattern.length())

每次匹配都会从目标字符串中提取待匹配字符串模式串进行匹配:

  • 如果匹配,则返回idx

  • 若不匹配,则查看待匹配字符串的后一位字符c

    • c位于模式串中,则idx = idx + 偏移表[c]
    • 否则,idx = idx + pattern.length() + 1

    重复上述过程,直到idx + pattern.length() > target.length()

偏移表

偏移表的作用是存储每一个在模式串中出现的字符和其对应的偏移位(该字符在模式串中出现的最右位置到尾部的位置 + 1),如**模式串aab**的偏移表为:

  • a的偏移位为pattern.length() - i = 3 - 1 = 2
  • b的偏移位为pattern.length() - i = 3 - 2 = 1
  • 其它均为pattern.length() + 1 = 3 + 1 = 4

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7j22GM50-1573103113502)(assets/1573100111625.png)]

举例

target = checkthisoutpattern = this

S1:

截屏2019-10-0716.15.15.png

  • idx = 0待匹配字符串 = chec
  • 因为chec != this,所以查看chec下的后一个字符k是否在pattern中(查看偏移表),
  • k不在偏移表中,所以idx = idx + 1

S2:

截屏2019-10-0716.16.44.png

  • idx = 5待匹配字符串 = this
  • 因为this = this,所以返回idx = 5

实现

class Solution {
    public int strStr(String haystack, String needle) {
        int hLen = haystack.length(), nLen = needle.length();
        if (hLen < nLen) return -1;
        if (nLen == 0) return 0;
        
        // 计算偏移表
        HashMap<Character, Integer> shift = getShiftMap(needle);
        int hc = 0; // 即idx
        while (hc + nLen <= hLen) {
            // 待匹配字符串
            String subH = haystack.substring(hc, hc + nLen);
            // 判断是否匹配
            if (subH.equals(needle)) {
                return hc;
            } else {
                // 边界处理
                if (hc + nLen >= hLen) return -1;
                // 判断待匹配字符串的下一个字符是否在偏移表中
                char c = haystack.charAt(hc + nLen);
                if (shift.containsKey(c)) {
                    hc += shift.get(c);
                } else {
                    hc += nLen + 1;
                }
            }
        }
        return hc + nLen >= hLen ? -1 : hc;
    }
    
    private HashMap<Character, Integer> getShiftMap(String pattern) {
        HashMap<Character, Integer> shift = new HashMap<>();
        for (int i = 0; i < pattern.length(); i++) {
            char c = pattern.charAt(i);
            shift.put(c, pattern.length() - i);
        }
        return shift;
    }
}

时间复杂度: O ( n ) O(n) O(n),最坏情况为 O ( m ∗ n ) O(m * n) O(mn),其中n为目标串target的长度,m为模式串pattern的长度;

空间复杂度: O ( n ) O(n) O(n)

KMP
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值