第二天
数组篇
/**
* 长度最小的子数组
* 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
*
* 示例:
*
* 输入:s = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。
*
* 提示:
*
* 1 <= target <= 10^9
* 1 <= nums.length <= 10^5
* 1 <= nums[i] <= 10^5
*/
/**
* 滑动窗口
* 时间复杂度:O(n)
* 空间复杂度:O(1)
* @param arr
* @param s
*/
private static void mostMinChildArr2(int[] arr,int s){
int result = arr.length;
int i = 0;
int sum = 0;
int length;
for(int j=0;j<arr.length;j++){
sum += arr[j];
while (sum>=s){
length = j - i + 1;
result = result>length ? length:result;
sum -= arr[i++];
}
if(j==arr.length-1&&sum<s){
result = 0;
}
}
System.out.println(result);
}
同类型例题
/*
* 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
*
*
*
* 注意:
*
* 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
* 如果 s 中存在这样的子串,我们保证它是唯一的答案。
*
*
* 示例 1:
*
* 输入:s = “ADOBECODEBANC”, t = “ABC”
* 输出:“BANC”
* 解释:最小覆盖子串 “BANC” 包含来自字符串 t 的 ‘A’、‘B’ 和 ‘C’。
* 示例 2:
*
* 输入:s = “a”, t = “a”
* 输出:“a”
* 解释:整个字符串 s 是最小覆盖子串。
* 示例 3:
*
* 输入: s = “a”, t = “aa”
* 输出: “”
* 解释: t 中两个字符 ‘a’ 均应包含在 s 的子串中,
* 因此没有符合条件的子字符串,返回空字符串。
*
*
* 提示:
*
* m == s.length
* n == t.length
* 1 <= m, n <= 105
* s 和 t 由英文字母组成
*
*
* 进阶:你能设计一个在 o(m+n) 时间内解决此问题的算法吗?
*/
/**
* 滑动窗口
* @param s
* @param t
* i头指针,j尾指针
*/
private static void mostMinChildStr(String s,String t){
int i = 0;
int flag = 0;
Map targetMap = new HashMap();
//暂存j,用于头指针向右移动时保持j不变
int temp = 0;
//判断是否是头指针向右移动的情景下
boolean temp2 = true;
//头指针和尾指针初始位置:指向主串的第一个和最后一个字母
int first = 0,last = s.length()-1;
//特殊情况:t的长度大于s的长度或一样长的情况
// start
if(s.length()<t.length()){
System.out.println("不存在");
return ;
} else if(s.length()==t.length()){
if (s.equals(t)){
for(int k=first;k<=last;k++){
System.out.println(s.charAt(k));
}
} else {
System.out.println("不存在");
}
return;
}
// end
//键值对存放t字符串,方便后期比较
for(int j=0;j<t.length();j++){
targetMap.put(t.charAt(j),0);
}
for(int j=0;j<s.length();j++){
//判断是否有对应值并且值为0
if(targetMap.containsKey(s.charAt(j))&&targetMap.get(s.charAt(j)).equals(0)){
targetMap.put(s.charAt(j),1);
flag++;
} else if(targetMap.containsKey(s.charAt(j))&&temp2){
targetMap.put(s.charAt(j),(int)targetMap.get(s.charAt(j))+1);
}
temp2 = true;
temp = j;
//flag==t.length()用来判断头尾指针截取的子串是否满条件,为真满足
while(flag==t.length()){
//temp2为假是头指针向右移动情况下的,此时j比实际小1,所以实际满足条件的截取尾指针得加一
if((j-i+2<last-first+1)&&temp2==false){
first = i;
last = j+1;
} else if((j-i+1<last-first+1)&&temp2==true){
first = i;
last = j;
}
if(targetMap.containsKey(s.charAt(i))&&(int)targetMap.get(s.charAt(i))>1){
targetMap.put(s.charAt(i),(int)targetMap.get(s.charAt(i))-1);
} else if(targetMap.containsKey(s.charAt(i))&&(int)targetMap.get(s.charAt(i))==1){
targetMap.put(s.charAt(i),0);
flag--;
}
//根据滑动窗口原理,满足条件下 头指针往右移,即i++,j=temp-1则为for循环里在i右移的情况下保持j不变
i++;
j=temp-1;
//temp2=false 判断当前情况是i右移,j不变的情况下
temp2 = false;
}
}
for(int k=first;k<=last;k++){
System.out.println(s.charAt(k));
}
}
个人感觉:有思路归有思路(因为和第一题思路一样),但是细节之处却是不同,实际上手写出来还遇到很多坑,各种问题需要处理,总之,不能眼高手低0.o
参考链接:代码随想路
ps:希望大佬们能给出进阶解法,学习学习。