LeetCode 438 – 找到字符串中所有字母异位词

题目描述

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

示例 1:

输入: s = “cbaebabacd”, p = “abc”
输出: [0,6]
解释:
起始索引等于 0 的子串是 “cba”, 它是 “abc” 的异位词。
起始索引等于 6 的子串是 “bac”, 它是 “abc” 的异位词。
示例 2:

输入: s = “abab”, p = “ab”
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 “ab”, 它是 “ab” 的异位词。
起始索引等于 1 的子串是 “ba”, 它是 “ab” 的异位词。
起始索引等于 2 的子串是 “ab”, 它是 “ab” 的异位词。

提示:

1 <= s.length, p.length <= 3 * 10^4
s 和 p 仅包含小写字母

题目分析

异位词的长度是固定的,因此只要从左到右遍历一遍即可,滑动窗口。
重点是如何判断两个字符串是异位词,由于限制为小写字母,所以可以通过记录每个字母的个数来进行判断。开一个数组用于记录 p 的每个字母的数量,p中的字母让计数+1,而 s 内的字母让计数-1。每移动一次窗口,就判断这个数组是不是全为0,全为0说明当前窗口中的字符串和目标p是异位词。
时间复杂度 O(n).

Java

public List<Integer> findAnagrams(String s, String p) {
    List<Integer> ans = new ArrayList<>();
    int[] num = new int[26];
    int size = p.length();
    if (s.length() < size) {
        return ans;
    }
    for (int i = 0; i < size; i++) {
        num[p.charAt(i) - 'a']++;
        num[s.charAt(i) - 'a']--;
    }
    for (int i = 0; i + size <= s.length(); i++) {
        boolean allZero = true;
        for (int t = 0; t < 26; t++) {
            if (num[t] != 0) {
                allZero = false;
                break;
            }
        }
        if (allZero) {
            ans.add(i);
        }

        if (i + size < s.length()) {
            num[s.charAt(i) - 'a']++;
            num[s.charAt(i + size) - 'a']--;
        }
    }

    return ans;
}

Kotlin

fun findAnagrams(s: String, p: String): List<Int> {
    val ans = ArrayList<Int>()
    val num = IntArray(26)
    val size = p.length
    if (s.length < p.length) {
        return ans
    }
    for (i in 0 until size) {
        num[p[i] - 'a']++
        num[s[i] - 'a']--
    }

    for (i in 0..s.length - size) {
        if (num.all { it == 0 }) {
            ans.add(i)
        }

        if (i + size < s.length) {
            num[s[i] - 'a']++
            num[s[i + size] - 'a']--
        }
    }

    return ans
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部