LeetCode算法-实现strStr()

题目描述

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1 。

说明:

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

示例 1:

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

示例 2:

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

示例 3:

输入:haystack = "", needle = ""
输出:0

提示:

  • 0 <= haystack.length, needle.length <= 5 * 104
  • haystack 和 needle 仅由小写英文字符组成

题目思路

我们采取暴力破解法,让我们的needle字符串与haystack的所有长度为needle长度的子串进行挨个的匹配,如果匹配成功,返回当前的下标,如果匹配都不成功,返回-1。如果haystack字符串的剩余长度小于needle字符串,则不用进行匹配,直接返回-1。

Java实现方案

public int strStr(String haystack, String needle) {
            if (needle.length() == 0) {
                return 0;
            }
            int sourceLength = haystack.length();
            int targetLength = needle.length();
            int result = -1;
            for (int i = 0; i + targetLength <= sourceLength; i++) {
                boolean flag = true;
                for (int j = 0; j < targetLength; j++) {
                    if (needle.charAt(j) != haystack.charAt(i + j)) {
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    result = i;
                    break;
                }
            }
            return result;
        }

代码详细解析

由题目详情可知,如果needle字符串为空,我们要返回0。所以我们先对这种特殊情况进行一次处理,于是有了一下三行的代码。

if (needle.length() == 0) {
	return 0;
}

小伙伴们,也许会问,如果我不处理,由下面的代码进行统一处理呢,那么一定是返回-1的,不符合题意,所以我们选择先行处理一次。

接下来,我们要获取两个字符串的长度,已经定义一个返回值,返回值我们默认为-1。因为除了上述情况外,其他所有不符合的情况都应该返回-1。于是有了下面的三行代码。

int sourceLength = haystack.length();
int targetLength = needle.length();
int result = -1;

接下来是我们的重头戏,遍历子串。我们先来看一眼for循环的条件。

for (int i = 0; i + targetLength <= sourceLength; i++) {}

我们定义一个下标初始的值为0,代表我们从haystack字符串的第一个字符开始进行对比。循环的条件是i + targetLength <= sourceLength。为什么是<=呢,因为我们要考虑的就是两个字符串长度相等的情况。比如a和a做比较,两个字符串的长度都为1。如果我们选择了<。那么0+1 < 1 这是不成立的。直接就会跳出循环,返回-1。而我们的正确结果是匹配成功应该返回0。所以我们在此进行匹配的时候,要选择<=。

有些小伙伴会考虑另一个问题,单看这个循环,如果i真的达到了等于的条件,那么不会产生数组越界吗?答案是不会的。因为我们下面的break判断会直接跳出当前的循环。

最后看下我们循环体里面的主代码逻辑

boolean flag = true;
for (int j = 0; j < targetLength; j++) {
  if (needle.charAt(j) != haystack.charAt(i + j)) {
    flag = false;
    break;
  }
}
if (flag) {
  result = i;
  break;
}

我们先设置一个flag 为true,他的意义代表,我们完全找到了这个子串,每次进入循环,我们都要重新置这个状态,因为我们是暴力破解,每次子串对比的状态一定要重置。

接下来开始遍历needle字符串。从第一个字符开始,因为随着我们的needle字符串,向后变更,haystack字符串也要同样的向后变更,所以haystack字符串为i+j作为下标。一旦有一个不一致,我们置flag为false然后跳出循环,当我们的needle字符串全部遍历完毕,而且没有跳出循环,此时的flag为true的话,那么i就是我们要找到的下表,直接跳出父循环,返回result即可。

总结

以上就是这道题的全部思路,欢迎大家在评论区进行探讨。

posted @ 2022-03-05 18:22  经典鸡翅  阅读(72)  评论(0编辑  收藏  举报