力扣面试经典算法150题:找出字符串中第一个匹配项的下标

找出字符串中第一个匹配项的下标

今天的题目是力扣面试经典150题中的数组的简单题: 找出字符串中第一个匹配项的下标

题目链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/description/?envType=study-plan-v2&envId=top-interview-150

题目描述

给定一个字符串 haystack 和一个字符串 needle,请找出 needle 在 haystack 中第一次出现的位置(下标)。如果 needle 不是 haystack 的一部分,则返回 -1。

  • 示例:
    • 输入:
      haystack = "hello", needle = "ll"
    • 输出:
      2
    • 输入:
      haystack = "aaaaa", needle = "bba"
    • 输出:
      -1

题目分析

题目要求我们在一个字符串 haystack 中找到另一个字符串 needle 第一次出现的位置。如果 needle 不是 haystack 的一部分,则返回 -1。

很明显,字符串needle是被包含在haystack中的一个子串,这意味着needle的字符在haystack中连续出现。

只需要第一次出现的位置则意味着我们需要的结果是needle中的字符第一次在haystack中连续出现时的第一个字符在haystack中的下标。

解题思路

分隔法

第一时间想到的办法:

  1. 判断haystack是否包含needle,不包含直接返回-1。
  2. 判断haystack是否以needle开头, 是的话返回0。
  3. 使用needle分割haystack,获取第一段的字符串长度返回即可。

整串匹配法

在分割法之后再思考想到的办法,使用整个子串去匹配:

  1. 获取两个字符串的长度。
  2. 以两者差值作为循环条件进行循环。
  3. 截取当前下标开始到子串长度的字符串与子串对比,一致则返回下标的值。
  4. 返回-1。

单字符匹配法:

在整串匹配法后想到的,不截取字符串,直接依次比较每个字符:

  1. 获取两个字符串的长度。
  2. 以两者差值作为循环条件进行循环
  3. 从 haystack 的第一个字符开始,逐个字符比较。
  4. 如果发现 haystack 中有一段子串与 needle 相同,则返回这段子串的起始位置。
  5. 如果遍历完整个 haystack 都没有找到匹配的子串,则返回 -1。

KMP 算法:

在上诉方法用完以后,尝试找到该类型题目的特殊算法:

  1. 构建 KMP 的 next 数组,然后根据 next 数组进行快速匹配。
  2. 如果找到匹配的子串,则返回起始位置;否则,返回 -1。

有点抽象,没完全想明白,这里就不贴了。。。

实际算法代码

下面是使用三种方法的 Java 实现:

java 复制代码
public static void main(String[] args) {
        StrStr solution = new StrStr();

        // 示例数据
        String haystack = "hello";
        String needle = "ll";

        // 调用计算第一个匹配项下标的方法
        int index1 = solution.strStr1(haystack, needle);
        int index2 = solution.strStr2(haystack, needle);
        int index3 = solution.strStr3(haystack, needle);

        // 输出结果
        System.out.println("The index1 of the first occurrence is: " + index1);
        System.out.println("The index2 of the first occurrence is: " + index2);
        System.out.println("The index3 of the first occurrence is: " + index3);
    }

    /**
     * 查找字符串中第一个匹配项的下标: 分割法
     *
     * @param haystack 主字符串
     * @param needle   子字符串
     * @return 第一个匹配项的下标
     */
    public int strStr1(String haystack, String needle) {
        if (needle.isEmpty()) {
            return 0;
        }

        if (!haystack.contains(needle)) {
            return -1;
        }
        if (haystack.startsWith(needle)) {
            return 0;
        }
        String[] split = haystack.split(needle);
        if (split.length > 0) {
            return split[0].length();
        }
        return -1;
    }


    /**
     * 查找字符串中第一个匹配项的下标:整串匹配法
     *
     * @param haystack 主字符串
     * @param needle   子字符串
     * @return 第一个匹配项的下标
     */
    public int strStr2(String haystack, String needle) {
        if (needle.isEmpty()) {
            return 0;
        }

        int n = haystack.length();
        int m = needle.length();

        for (int i = 0; i <= n - m; i++) {
            if (needle.equals(haystack.substring(i, i + m))) {
                return i;
            }
        }

        return -1;
    }

    /**
     * 查找字符串中第一个匹配项的下标:单字符匹配法
     *
     * @param haystack 主字符串
     * @param needle   子字符串
     * @return 第一个匹配项的下标
     */
    public int strStr3(String haystack, String needle) {
        if (needle.isEmpty()) {
            return 0;
        }

        int n = haystack.length();
        int m = needle.length();

        for (int i = 0; i <= n - m; i++) {
            boolean found = true;
            for (int j = 0; j < m; j++) {
                if (haystack.charAt(i + j) != needle.charAt(j)) {
                    found = false;
                    break;
                }
            }
            if (found) {
                return i;
            }
        }

        return -1;
    }

结果

同时调用三个方法,返回结果都符合预期:

我们分别提交到力扣:

通过肯定都是通过的,这里贴第三种方法的图,因为这个方法的相对最优。

以下是三种方法的提交结果:

  1. 分割法
  1. 整串匹配法
  1. 单字符匹配法

三种方法最先能想到的容易程度以及理解难度正好按与算法的效果相反,难道这就是算法吗

总结

今天自己想了三种方法,特殊算法KMP有点抽象一下子还没想明白,有兴趣的自行学习,明天我再抽空理解一下。

另外数组简单难度的题目已经做完,下面开始上强度了。。。

加油!!!

相关推荐
Ni-Guvara2 分钟前
函数对象笔记
c++·算法
测试19984 分钟前
2024软件测试面试热点问题
自动化测试·软件测试·python·测试工具·面试·职场和发展·压力测试
WaaTong18 分钟前
《重学Java设计模式》之 原型模式
java·设计模式·原型模式
m0_7430484418 分钟前
初识Java EE和Spring Boot
java·java-ee
AskHarries20 分钟前
Java字节码增强库ByteBuddy
java·后端
泉崎26 分钟前
11.7比赛总结
数据结构·算法
你好helloworld28 分钟前
滑动窗口最大值
数据结构·算法·leetcode
小灰灰__40 分钟前
IDEA加载通义灵码插件及使用指南
java·ide·intellij-idea
马剑威(威哥爱编程)44 分钟前
MongoDB面试专题33道解析
数据库·mongodb·面试
夜雨翦春韭44 分钟前
Java中的动态代理
java·开发语言·aop·动态代理