实现strStr()

本文介绍了如何实现类似C的strStr()或Java的indexOf()方法,旨在找出子串在目标字符串中的首次出现索引。首先讨论了简单的遍历法,利用Java的startsWith()方法判断,然后提及Java String类的indexOf()方法源码,虽然复杂,但作者计划后续深入研究并整理思路。
摘要由CSDN通过智能技术生成

implement strStr()

Implement strStr()

Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.

Clarification:

What should we return when needle is an empty string? This is a great question to ask during an interview.

For the purpose of this problem, we will return 0 when needle is an empty string. This is consistent to C’s strStr() and Java’s indexOf().

在这里插入图片描述

今天这道题呢,又是一个简单难度的,是让我们实现类似C中的strStr()方法或者Java中的indexOf()方法,也就是找出给定的子串在目标字符串中第一次出现的索引。

咦,indexOf()?这个我熟,那我先试试这样

/**
 * @author: LittleWang
 * @date: 2021/4/20
 * @description:
 */
public class Solution {
    public int strStr(String haystack, String needle) {
        return haystack.indexOf(needle);
    }
}

(投机取巧)提交!

在这里插入图片描述

哎?这……咳咳,我们这是投机取巧,当然不建议使用了,毕竟刷题的主要目的是学习嘛,这样就没有意思了。

我们还是自己来好好想一想,这种算法应该怎么实现。

​ 我首先想到的就是非常简单粗暴的,遍历法,用两重循环来遍历两个字符串。这里我使用了Java的startsWith()方法,基本思路如下:

​ 定义一个索引index,用来遍历haystack,判断以每个字符开头的子串是不是以needle开头,如果是,那就返回这个index的值,否则就继续向后遍历。如果没有找到满足条件的index,那就返回-1。代码如下:

/**
 * @author: LittleWang
 * @date: 2021/4/20
 * @description:
 */
public class Solution2 {
    public int strStr(String haystack, String needle) {
        if(needle.isBlank())
            return 0;

        for (int index = 0; index < haystack.length(); index++) {
            if(haystack.substring(index).startsWith(needle)) {
                return index;
            }
        }

        return -1;
    }
}

这其实本质上来说就是简单的遍历,我只是换了一种表达的形式而已,效率比起Java自带的IndexOf方法就差一些了。

在这里插入图片描述

那我们来看看Java中String类的indexOf方法的源码是怎么实现的吧。

说实话,Java中的String类有一点复杂,我并不是完全看得懂,根据自己读的源码,在它的基础上做了一点点简化,加上了自己的理解,主要是为了突出indexOf这个方法的实现,别的方法细节也是能省则省了。

/**
 * @author: LittleWang
 * @date: 2021/4/20
 * @description:
 */
public class String{
    private final char value[];     //String类的底层实际上是维护了一个不可变的字符串数组

    public String(char[] str) {     //构造函数是我自己加上的,实际不是这样实现的
        value = str;
    }       

    public int indexOf(String str) {    //入口函数
        return indexOf(str, 0);
    }   

    public int indexOf(String str, int fromIndex) {     //这是Java中indexOf的另一个重载实现,在使用上一个方法的时候实际是调用了该方法
        return indexOf(value, value.length, str, fromIndex);
    }

    static int indexOf(char[] source, int sourceCount,
                       String target, int fromIndex) {      //最终实现在这里
        char[] tgt = target.value;
        int tgtCount = tgt.length;
        if(fromIndex >= sourceCount) {      //检查所有的特殊情况
            return tgtCount == 0 ? 0 : -1;
        }
        if(fromIndex < 0) {
            return 0;
        }
        if(tgtCount == 0) {
            return fromIndex;
        }
        if(tgtCount > sourceCount) {
            return -1;
        }

        char first = tgt[fromIndex];        //目标字符串的第一个字符
        int max = sourceCount - tgtCount;   //如果索引大于max,target就必不可能在source中出现了,因为target剩余的长度已经小于target的长度了

        for(int i = fromIndex; i <= max; i++) {
            //找到满足第一个字符相等的位置
            if(source[i] != first) {
                while(++i <= max && source[i] != first)
                    ;
            }

            if(i <= max) {
                int j = i + 1;
                int end = j + tgtCount - 1;
                for(int k = 1; j < end && source[j] == tgt[k]; j++, k++)
                    ;
                //只有当判断的字符全都一样时,最终j的值才会等于end,否则循环会提前结束,说明target不匹配
                if(j == end) {
                    return i;
                }
            }
        }

        return -1;
    }
}

嗯,差不多了,今天的每日一题就到这里了,关于源码我可能没有把思路讲清楚,先在这立个flag吧,我后面会读懂String类的所有源码,并把所有的实现思路整理出来放在博客里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值