Leecode no.567 字符串的排列

package leecode;

import java.util.HashMap;
import java.util.Map;

/**
* 567. 字符串的排列
*
* 给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。
*
* 换句话说,s1 的排列之一是 s2 的 子串 。
*
*  
* @author Tang
* @date 2021/12/3
*/
public class CheckInclusion {

/**
* 判断s2中是否包含s1的所有字符子串,并且要连续
* 与76题相似
* 采用滑动窗口
*
* @param s1
* @param s2
* @return
*/
public boolean checkInclusion(String s1, String s2) {
char[] all = s2.toCharArray();
char[] s = s1.toCharArray();

//初始化need列表
Map<Character, Integer> needMap = new HashMap<>();
for (char c : s) {
needMap.put(c, needMap.getOrDefault(c, 0) +1);
}

//初始化window列表
Map<Character, Integer> window = new HashMap<>();

//表示当前有几个元素满足 0 <= valid <= s.length
//当valid == s.length时
int valid = 0;

int left = 0;
int right = 0;

//执行窗口右移
while(right < all.length) {
char c = all[right];
right++;

//此时说明元素c正需要
//window中可以暂时存储过量的元素,反正最后也可以通过缩窗口调掉
if(needMap.containsKey(c)) {
window.put(c, window.getOrDefault(c, 0) +1);
if(window.get(c).equals(needMap.get(c))) {
valid++;
}
}

//如果这个c我不需要,那么进行缩左窗口试试能不能让这个c变成需要
//如果不能就会把left缩到right对其,再从此刻重来
while(left < right && right - left >= s.length) {
//尝试更新结果
if(valid == needMap.size()) {
return true;
}

char d = all[left];
left++;

if(needMap.containsKey(d)) {
if(window.get(d).equals(needMap.get(d))) {
valid--;
}
//把元素d干掉
window.put(d, window.get(d) - 1);
}

}
}


return false;
}


public static void main(String[] args) {
String s1 = "abcdxabcde";
String s2 = "abcdeabcdx";

new CheckInclusion().checkInclusion(s1,s2);

}


}
posted @ 2021-12-03 15:58  六小扛把子  阅读(42)  评论(0编辑  收藏  举报