# 【小Y学算法】⚡️每日LeetCode打卡⚡️——15.实现 strStr()

  *     *       *         * 📢前言
    * 🌲原题样例
    *       * 🌻C#方法一：暴力法
      * 🌻C#方法二：傻瓜解法
      * 🌻Java 方法一：暴力法
      * 🌻Java 方法二： KMP 解法
    * 💬总结



#### 📢前言

🚀 算法题 🚀   
---  
  
>   * 🌲 每天打卡一道算法题，既是一个学习过程，又是一个分享的过程😜
>   * 🌲 提示：本专栏解题 编程语言一律使用 C# 和 Java 两种进行解题
>   * 🌲 要保持一个每天都在学习的状态，让我们一起努力成为算法大神吧🧐！
>   * 🌲  今天是力扣算法题持续打卡第15天🎈！
> 


🚀 算法题 🚀   
---  
  
## 🌲原题样例

实现 `strStr()`函数。

给你两个字符串 `haystack`和 `needle`，请你在 haystack 字符串中找出 `needle`字符串出现的第一个位置（下标从 0 开始）。

如果不存在，则返回 `-1`。

**说明:**

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

对于本题而言，当 `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 仅由小写英文字符组成



### 🌻C#方法一：暴力法

**思路解析**

我看到题目的第一想法是使用`IndexOf`直接就可以返回第一个下标了

但是这样毫无算法可言哈哈，后面也把代码贴上~

暴力法，使用双层for循环，让字符串`needle` 与字符串 `haystack`的所有长度为 `m` 的子串均匹配一次。

为了减少不必要的匹配，我们每次匹配失败即立刻停止当前子串的匹配，对下一个子串继续匹配。

如果当前子串匹配成功，我们返回当前子串的开始位置即可。如果所有子串都匹配失败，则返回 `−1`。

**代码：**
    
    
        public int strStr(string haystack, string needle)
        {
            int n = haystack.Length, m = needle.Length;
            for (int i = 0; i + m <= n; i++)
            {
                bool flag = true;
                for (int j = 0; j < m; j++)
                {
                    if (haystack.Substring(i + j,1) != needle.Substring(j,1))
                    {
                        flag = false;
                        break;
                    }
                }
                if (flag)
                {
                    return i;
                }
            }
            return -1;
        }
    

**执行结果**
    
    
    通过
    执行用时：1373 ms，在所有 C# 提交中击败了13.13%的用户
    内存消耗：38.2 MB，在所有 C# 提交中击败了61.91%的用户
    

**复杂度分析**
    
    
    时间复杂度：O(n * m)
    空间复杂度：O(1)
    

### 🌻C#方法二：傻瓜解法

此方法使用C#的IndexOf方法直接拿到符合条件的索引，体现不出算法的精髓。。

**代码：**
    
    
    public class Solution {
        public int RemoveElement(int[] nums, int val) {
            if(nums.Length == 0) return 0;
            int count = 0;
            for(int i = 0; i < nums.Length; i++)
                if(nums[i] != val) 
                    nums[count++] = nums[i];
            return count;
        }
    }
    

**执行结果**
    
    
    通过
    执行用时：920 ms，在所有 C# 提交中击败了30.06%的用户
    内存消耗：24.3 MB，在所有 C# 提交中击败了13.88%的用户
    

### 🌻Java 方法一：暴力法

此方法跟C#第一种解题思路一致

**代码：**
    
    
    class Solution {
        public int strStr(String haystack, String needle) {
            int n = haystack.length(), m = needle.length();
            for (int i = 0; i + m <= n; i++) {
                boolean flag = true;
                for (int j = 0; j < m; j++) {
                    if (haystack.charAt(i + j) != needle.charAt(j)) {
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    return i;
                }
            }
            return -1;
        }
    }
    

**执行结果**
    
    
    通过
    执行用时：1373 ms，在所有 Java  提交中击败了13.03%的用户
    内存消耗：38.2 MB，在所有 Java 提交中击败了61.91%的用户
    

**复杂度分析**
    
    
    时间复杂度：O(n*m)
    空间复杂度：O((1)
    

### 🌻Java 方法二： KMP 解法

**思路解析**

只能说我还不懂。。从力扣大佬参考过来的！

  
  
  
  
  
  
  
  
  


**代码：**
    
    
    class Solution {
        // KMP 算法
        // ss: 原串(string)  pp: 匹配串(pattern)
        public int strStr(String ss, String pp) {
            if (pp.isEmpty()) return 0;
            
            // 分别读取原串和匹配串的长度
            int n = ss.length(), m = pp.length();
            // 原串和匹配串前面都加空格，使其下标从 1 开始
            ss = " " + ss;
            pp = " " + pp;
    
            char[] s = ss.toCharArray();
            char[] p = pp.toCharArray();
    
            // 构建 next 数组，数组长度为匹配串的长度（next 数组是和匹配串相关的）
            int[] next = new int[m + 1];
            // 构造过程 i = 2，j = 0 开始，i 小于等于匹配串长度 【构造 i 从 2 开始】
            for (int i = 2, j = 0; i <= m; i++) {
                // 匹配不成功的话，j = next(j)
                while (j > 0 && p[i] != p[j + 1]) j = next[j];
                // 匹配成功的话，先让 j++
                if (p[i] == p[j + 1]) j++;
                // 更新 next[i]，结束本次循环，i++
                next[i] = j;
            }
    
            // 匹配过程，i = 1，j = 0 开始，i 小于等于原串长度 【匹配 i 从 1 开始】
            for (int i = 1, j = 0; i <= n; i++) {
                // 匹配不成功 j = next(j)
                while (j > 0 && s[i] != p[j + 1]) j = next[j];
                // 匹配成功的话，先让 j++，结束本次循环后 i++
                if (s[i] == p[j + 1]) j++;
                // 整一段匹配成功，直接返回下标
                if (j == m) return i - m;
            }
    
            return -1;
        }
    }
    链接：https://leetcode-cn.com/problems/implement-strstr/solution/shua-chuan-lc-shuang-bai-po-su-jie-fa-km-tb86/
    

**执行结果**
    
    
    通过
    执行用时：3 ms，在所有 Java  提交中击败了72.84%的用户
    内存消耗：38.5 MB，在所有 Java 提交中击败了29.32%的用户
    

**复杂度分析**
    
    
    时间复杂度：O(m+n)
    空间复杂度：O((m)
    

## 💬总结

  * 今天是力扣算法题打卡的第十五天！
  * 文章采用 `C#`和 `Java` 两种编程语言进行解题
  * 一些方法也是参考力扣大神写的，也是边学习边分享，再次感谢算法大佬们
  * 那今天的算法题分享到此结束啦，明天再见！