LeetCode Hot100 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 * 104
s 和 p 仅包含小写字母
解法
本题采用滑动窗口解法。但是在遍历启始位置的同时,维持一个滑动窗口会超时,因此要想办法在O(n)的时间复杂度内解决问题。
一般的滑动窗口总是在窗口之中遍历,这样做显然比较浪费时间。但是我们仔细观察便会发现,窗口移动的过程中,每次仅有一个元素出窗口,一个元素进入窗口。抓住这个特性,我们可以写出一下代码:
class Solution {
public List<Integer> findAnagrams(String s, String p) {
if(s.length()<p.length()) return new ArrayList<>();
int slen = s.length();
int plen = p.length();
int[] pcount = new int[26];
int[] scount = new int[26];
for(int i=0;i<plen;i++){
pcount[p.charAt(i)-'a']++;
scount[s.charAt(i)-'a']++;
}
List<Integer> ans = new ArrayList<>();
if(Arrays.equals(pcount,scount)) ans.add(0);
for(int i=0;i<slen-plen;i++){
--scount[s.charAt(i)-'a'];
++scount[s.charAt(i+plen)-'a'];
if(Arrays.equals(pcount,scount)){
ans.add(i+1);
}
}
return ans;
}
}
这里我们采用桶排序的方法,把p的每个字母映射到对应的角标之下。同时把s的前plen个元素也映射过来。这样当两个数组相同的时候,第0号位置绝对会是一个有效角标。
然后我们开始考虑窗口移动。当窗口向前移动一位,一个元素出去,一个元素进来。出去的元素我们对应位置–。同时进来的元素对应位置我们++操作(此处注意i++与++区别----++i是先执行++操作,i++是先执行外面的语句,再++)。当这番操作结束后,判断两个数组是否相同。如若相同,则记录下来。这样我们便可以把时间复杂度降低到O(n)
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!