/** * @param {number[]} nums * @param {number} target * @return {number[]} */ var twoSum = function (nums, target) { let map = newMap() for (let i = 0; i < nums.length; i++) { let e = nums[i] let n = target - e if (map.has(n)) { return [map.get(n), i] } else { map.set(e, i) } } };
/** * @param {string} s * @return {number} */ var lengthOfLongestSubstring = function (s) { let res = 0// 最长长度 let a = 0// 滑动窗口起点 const map = newMap() // 存储字符的字典 for (let b = 0; b < s.length; b++) { const e = s[b]; if (map.has(e) && map.get(e) >= a) { // 如果存在重复元素 // 如果是abba 这样的情况,需要防止滑动窗口起始点变小,已经在滑动窗口外面了,不应当考虑 a = map.get(e) + 1// 滑动窗口左边前进一位 } map.set(e, b) // 存储当前值的最后的下标 用于下次计算起始点 res = Math.max(res, b - a + 1) // 当前长度与已知最大长度 } return res }
/** * @param {string} s * @param {string} t * @return {string} */ var minWindow = function (s, t) { // 最小子串大于字符串s,毕竟不存在最小子串,直接返回空 if(t.length > s.length) { return'' } let start = 0// 指针开头 let end = 0// 指针结尾 let result = ''// 存储最小覆盖子串
const need = newMap() // 存储最小子串数据 for (let i = 0; i < t.length; i++) { const e = t[i]; need.set(e, need.has(e) ? need.get(e) + 1 : 1) } // need 为 "ABC" => {'A' => 1,'B' => 1,'C' => 1 } let needType = need.size// 最小子串的长度,用于记录滑动窗户口还未包含几位数
// 先走后指针 while (end < s.length) { const c = s[end] // 滑动窗口右边向前 if (need.has(c)) { // 判断当前元素是否在map中 need.set(c, need.get(c) - 1) // 如果在map中,其值减1 if (need.get(c) == 0) { // 如果当前值,在map中为0了,说明当前滑动窗口包含了当前值的所有数量 // 所以对记录map数量的数值再减1 needType -= 1 } } // 如果needType为0了,说明次数滑动窗口已经包含所有子串 while (needType === 0) { // 获取当前子串 let carry = s.substring(start, end + 1) // 对比存储子串与当前子串,获取最小的 if (result == '' || result.length > carry.length) { result = carry } const c2 = s[start] if (need.has(c2)) { // 判断当前元素是否在map中,在,这说明某个值移出了,此时已经不是最小子串,因此map中的当前值,+1 // 因为去除了存在的值,当前子串已经不符合标准,needType记录值+1 // 左指针停止,开始右指针行动,知道它再次覆盖了子串 need.set(c2, need.get(c2) + 1) if (need.get(c2) === 1) { needType += 1 } } start += 1// 左指针前进 } end += 1// 右指针前进 } return result };