3.无重复字符的最长子串
题目
给定一个字符串 s
,请你找出其中不含有重复字符的 最长 子串 的长度。
示例 1:
输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc" ,所以其长度为 3。
代码
import java.util.*;
public class hot100 {
public static void main(String[] args) {
/*无重复字符的最长子串,滑动窗口+哈希表
* start固定左边,end向右滑动,进行扩张,只要字母不重复,即哈希中不存在,不断扩张,更新长度
* 如果重复,收缩start,更新start=重复字母下标+1
* !!!hm.get(c) >= start,保证重复字母是在窗口内的重复*/
//时间复杂度o(n)
//空间复杂度o(n)
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
int start = 0;
int end = 0;
int res = 0;
HashMap<Character, Integer> hm = new HashMap<>();
while(end < s.length()){
char c = s.charAt(end);
///!!!hm.get(c) >= start,保证重复字母是在窗口内的重复
if(hm.containsKey(c) && hm.get(c) >= start){ //字母重复,且重复下标在start滑动区间后
start = hm.get(c) + 1; //收缩start,重复字母的后一个位置
}
hm.put(c, end);
res = Math.max(res, end-start+1);
end++;
}
System.out.println(res);
}
}
438.找到字符串中所有字母异位词
题目
给定两个字符串 s
和 p
,找到 s
中所有 p
的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
示例 1:
输入: s = "cbaebabacd", p = "abc" 输出: [0,6] 解释: 起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。 起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
代码
import java.util.*;
public class hot100 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
String p = sc.nextLine();
HashMap<Character, Integer> need = new HashMap<>();
HashMap<Character, Integer> window = new HashMap<>();
int lenp = p.length();
int lens = s.length();
for(int i=0; i < lenp; i++){
char c = p.charAt(i);
need.put(c, need.getOrDefault(c, 0) + 1);
}
int flag = need.size();
int valid = 0;
List<Integer> res = new ArrayList<>();
for(int i=0; i < lens; i++){
char c = s.charAt(i);
if(need.containsKey(c)){
window.put(c, window.getOrDefault(c, 0) + 1);
if(need.get(c).equals(window.get(c))){
valid++;
}
if(valid == flag){
res.add(i - lenp + 1);
}
}
if(i >= lenp - 1){
char start = s.charAt(i - lenp + 1);
if(need.containsKey(start)){
if(need.get(start).equals(window.get(start))){
valid--;
}
window.put(start, window.get(start) - 1);
}
}
}
System.out.println(res);
}
}
560.和为k的子数组
题目
给你一个整数数组 nums
和一个整数 k
,请你统计并返回 该数组中和为 k
的子数组的个数 。
子数组是数组中元素的连续非空序列。
示例 1:
输入:nums = [1,1,1], k = 2 输出:2
代码
public int subarraySum(int[] nums, int k) {
int[] sum = new int[nums.length + 1];
sum[0] = 0;
for(int i=0; i < nums.length; i++){
sum[i+1] = sum[i] + nums[i];
}
int res = 0;
HashMap<Integer, Integer> hm = new HashMap<>();
for(int i=0; i < sum.length; i++){
if(hm.containsKey(sum[i] - k)){
res += hm.get(sum[i] - k);
}
hm.put(sum[i], hm.getOrDefault(sum[i], 0) + 1);
}
return res;
}
239.滑动窗口最大值
题目
给你一个整数数组 nums
,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6 7 5 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7
代码
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int[] res = new int[nums.length - k + 1];
Deque<Integer> deque = new ArrayDeque<>();
for(int i=0; i < k; i++){
while(!deque.isEmpty() && nums[i] > deque.getLast()){
deque.pollLast();
}
deque.offer(nums[i]);
}
int index = 0;
res[index++] = deque.peek();
for(int i=k; i < nums.length; i++){
if(deque.peek() == nums[i-k]){
deque.poll();
}
//!!!nums[i] > deque.getLast(),没有等号
while(!deque.isEmpty() && nums[i] > deque.getLast()){
deque.pollLast();
}
deque.offer(nums[i]);
res[index++] = deque.peek();
}
return res;
}
}
76.最小覆盖子串
题目
给你一个字符串 s
、一个字符串 t
。返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
注意:
- 对于
t
中重复字符,我们寻找的子字符串中该字符数量必须不少于t
中该字符数量。 - 如果
s
中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC" 输出:"BANC" 解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
代码
class Solution {
public String minWindow(String s, String t) {
HashMap<Character, Integer> need = new HashMap<>();
HashMap<Character, Integer> window = new HashMap<>();
int lent = t.length();
int lens = s.length();
for(int i=0; i < lent; i++){
char c = t.charAt(i);
need.put(c, need.getOrDefault(c, 0) + 1);
}
int flag = need.size();
int valid = 0;
int minlen = Integer.MAX_VALUE;
int minstart = 0;
int start = 0;
int end = 0;
while(end < lens){
char c = s.charAt(end);
//扩张
if(need.containsKey(c)){
//窗口字母
window.put(c, window.getOrDefault(c, 0) + 1);
//窗口有效位
if(need.get(c).equals(window.get(c))){
valid++;
}
//只要满足条件了,收缩到最小长度
while(valid == flag){
int len = end - start + 1;
if(len < minlen){ //!!!只有最小长度,才能更新minlen和minstart
//如果不是更小的长度,minstart不用更新的
minlen = len;
minstart = start;
}
//收缩
char cc = s.charAt(start);
if(need.containsKey(cc)){
if(need.get(cc).equals(window.get(cc))){
valid--;
}
window.put(cc, window.get(cc) - 1);
}
start++;
}
}
end++;
}
if(minlen == Integer.MAX_VALUE){
return "";
}
else{
return s.substring(minstart,minstart+minlen);
}
}
}