3. 无重复字符的最长子串
给定一个字符串 `s` ,请你找出其中不含有重复字符的 最长子串 的长度。
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
做这道题出现了两个错误:
1.set的大小是size不是length。
2.max = Math.max(set.size,max)这个式子是放在求无重复的set那
var lengthOfLongestSubstring = function(s) {
let i = 0;
let j = 0;
let set = new Set();
let max = 0;
if(s.length === 0) return 0;
for(i; i < s.length; i++){
// 不断遍历s,如果滑动窗口没有这个元素就加入set
if(!set.has(s[i])){
set.add(s[i]);
max = Math.max(set.size,max)
}else{
while(set.has(s[i])){
set.delete(s[j]);
j++;
}
set.add(s[i]);
}
}
return max
};
219. 存在重复元素 II
给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 i 和 j ,满足 nums[i] == nums[j] 且 abs(i - j) <= k 。如果存在,返回 true ;否则,返回 false 。
输入: nums = [1,2,3,1], k = 3
输出: true
题解:不断将元素加入滑动窗口中,也就是加入set,如果set中存在重复元素并且窗口大小小于指定大小就返回,否则加入set中,当滑动窗口超过了指定大小,缩小窗口
var containsNearbyDuplicate = function(nums, k) {
let set = new Set();
for(let i = 0; i < nums.length; i++){
if(set.has(nums[i])){
return true;
}
set.add(nums[i]);
if(set.size > k){
set.delete(nums[i-k])
}
}
return false
};
76. 最小覆盖子串
给你一个字符串 `s` 、一个字符串 `t` 。返回 `s` 中涵盖 `t` 所有字符的最小子串。如果 `s` 中不存在涵盖 `t` 所有字符的子串,则返回空字符串 `""` 。
输入: s = "ADOBECODEBANC", t = "ABC"
输出: "BANC"
思路:这道题目有目标框,我们先设置need框和window框。用左右指针,right指针这个字符x,need有,就加入window里面,当window[x] == need[x],valid+1。当valid==need的长度说明s已经包含了t字符串,这时候我们需要移动left,如果这个left指向y,y是need里面需要的,我们移除y的时候need[y]-1,window[y]-1,valid-1。这个时候就是valid==need的长度不成立了,我们就要跳出循环。值得注意的是我们要求最小子串,所以我们需要start和截取长度,所以我们在满足valid==need的长度时先获取这两个值。
var minWindow = function(s, t) {
let need = {};
let window = {};
for(let x of t){
need[x] = (need[x] || 0) + 1;
}
let right=0,left = 0, start = 0, len = Number.MAX_VALUE, valid = 0;
while(right < s.length){
// 先操作右指针
let x = s[right];
right++;
if(need[x]){
window[x] = (window[x] || 0 ) + 1;
if(window[x] === need[x]){
valid++
}
}
// 满足t字符串了
while(valid === Object.keys(need).length){
// 先更新最新的
if(right - left < len){
start = left;
len = right - left
}
// 操作左指针,来跳出循环从而继续移动右指针
let y = s[left];
left++;
if(need[y]){
if(need[y] === window[y]){
valid--;
}
window[y]--;
}
}
}
return len == Number.MAX_VALUE ? "" : s.substr(start, len);
};
438. 找到字符串中所有字母异位词
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
var findAnagrams = function(s, p) {
let need = {};
let window = {};
for(let x of p){
need[x] = (need[x] || 0) + 1;
}
let right = 0, left = 0, valid = 0;
let res = [];
while(right < s.length){
let x = s[right];
right++;
if(need[x]){
window[x] = (window[x] || 0) + 1;
if(need[x] === window[x]){
valid++;
}
}
// 这里移动左指针的条件是right-left>=p.length
while(right - left >= p.length){
if(valid === Object.keys(need).length){
res.push(left)
}
let y = s[left];
left++;
if(need[y]){
if(window[y] === need[y]){
valid--;
}
window[y]--;
}
}
}
return res
};
1456. 定长子串中元音的最大数目
给你字符串 s 和整数 k 。
请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。
英文中的 元音字母 为(a, e, i, o, u)。
输入: s = "abciiidef", k = 3
输出: 3
解释: 子字符串 "iii" 包含 3 个元音字母。
var maxVowels = function (s, k) {
let set = new Set(['a', 'e', 'i', 'o', 'u'])
let count = 0, l = 0, r = 0;
while(r < k){
set.has(s[r]) && count++;
r++;
}//这个时候r=3
let max = count;
while(r < s.length){
// 因为现在r是从3开始
set.has(s[r]) && count++;
set.has(s[l]) && count--;
l++;
r++;
max = Math.max(max, count)
}
return max
};
904. 水果成篮
你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。
你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。
输入: fruits = [0,1,2,2]
输出: 3
解释: 可以采摘 [1,2,2] 这三棵树。
如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。
思路:用滑动窗口遍历fruits,当有新种类的水果进入窗口时
1.如果窗口中只有一种水果,将这种水果加入arr数组
2.如果有两种水果,更新窗口的左边界,更新arr中水果的种类
3.如果进来了一种新的类型的水果 更新前一种水果的位置
4.更新滑动窗口的最大值
var totalFruit = function(fruits) {
let left = 0, right = 0, n = 0;//表示前一个水果刚开始的位置,主要是用来更新left
let arr = [fruits[0]];
let max = 0;
for(right; right < fruits.length; right++){
// 先加水果再更新left
if(!arr.includes(fruits[right])){//如果窗口中不包含 进窗口的水果
if(arr.length <=1 ){//窗口只有一个水果
arr[1] = fruits[right]
}else{// 窗口有两个水果了,要加新水果
//因为只能有两种水果,所所以我们要不断跟新第一个水果的开始位置
left = n;
// arr[0] = arr[1]; 不能这样写,比如101414,arr[1]=0,但是我们要的是1
arr[0] = fruits[right-1]
arr[1] = fruits[right]
}
}
// 开始更新 新的位置
if(fruits[right] !== fruits[n]){
n = right
}
max = Math.max(max,right-left+1)
}
return max
};