算法-leetcode-滑动窗口问题- 438. 找到字符串中所有字母异位词

12, 438. 找到字符串中所有字母异位词

https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/

思路1: 暴力法

思路2: 滑动窗口法

package com.shangguigu.dachang.algrithm.A04_SlidingWindow;

import java.util.ArrayList;
import java.util.List;

/**
 * @author : 不二
 * @date : 2022/4/10-下午8:09
 * @desc : 438. 找到字符串中所有字母异位词
 * https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/
 **/
public class A44_findAnagrams {
    public static void main(String[] args) {

//        String s = "cbaebabacd", p = "abc";
//        String s = "abab", p = "ab";
        String s = "cbaebabacd", p = "abc";
//        List<Integer> anagrams = findAnagrams_by_violance(s, p);
         List<Integer> anagrams = findAnagrams_by_window(s, p);
//        List<Integer> anagrams = findAnagrams(s, p);
        System.out.println("结果是:" + anagrams);

    }


    /**
     * 思路2:思路1其实就是滑动窗口的实现
     *       双指针
     */
    public static List<Integer> findAnagrams_by_window(String s, String p){
        List<Integer> result = new ArrayList<>();

        if (p.length() > s.length()) {
            return result;
        }
        int[] target = new int[26];
        for (int i = 0; i < p.length(); i++) {
            target[p.charAt(i) - 'a']++;
        }

        int[] subStr = new int[26];
        int start = 0, end = 0;
        while (end < s.length()) {
            char newChar = s.charAt(end);
            subStr[newChar - 'a']++;
            // 说明新进入的字符要么不在target中,要不字母的个数超了
            // 通过移动start看下是否能抵消
            // 判断当前子串是否符合要求: 说明当前的这个字符不符合要求,开始位置++,看一下是否能抵消当前字母
            // 如果是抵消不了的话,那么start会一直加到end后面
            // 这个地方:如果比如说某个字母abce在最后,比如这里的e,那么end指向e的时候, start可以直接加到end+1位置哈
            while (subStr[newChar - 'a'] > target[newChar - 'a'] && start < end+1) {
                char removeChar = s.charAt(start);
                subStr[removeChar-'a']--;
                start++;
            }

            // 到这里说明:对应字母个数都不大于目标值,而且字母个数相同。那就一定是了
            if (end - start == p.length()-1) {
                result.add(start);
            }
            end++;
        }
        return result;
    }


    /**
     * 思路1:暴力解法
     *      第一层遍历s
     *      第二层遍历对应位置开始的窗口,看下是否满足
     *
     *      时间复杂度:O(nk-k*k), 因为k比n要小的多,所以k*k可以忽略
     *
     */
    public static List<Integer> findAnagrams_by_violance(String s, String p) {
        List<Integer> result = new ArrayList<>();

        if (p.length() > s.length()) {
            return result;
        }

        int[] target = new int[26];
        for (int i = 0; i < p.length(); i++) {
            target[p.charAt(i) - 'a']++;
        }

        for (int i = 0; i < s.length() - p.length() + 1; i++) {
            // System.out.print("i:" + i);
            int[] subStr = new int[26];
            boolean isMatched = true;
            for (int j = i; j < i + p.length(); j++) {
                // System.out.print( s.charAt(j));
                subStr[s.charAt(j) - 'a']++;
                if (subStr[s.charAt(j) - 'a'] > target[s.charAt(j) - 'a']) {
                    isMatched = false;
                    break;
                }
            }
            // System.out.println();
            if (isMatched) {
                result.add(i);
            }
        }
        return result;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值