1.字典

  • 与集合类似,字典也是一种存储唯一值的数据结构,但是它是以键值对的形式来存储
  • ES6中也有字典,名为Map
    ```javascript const m = new Map();

// 增 m.set(‘a’, ‘aa’); m.set(‘b’, ‘bb’);

// 删 m.delete(‘b’); // m.clear();

// 改 m.set(‘a’, ‘aaa’);

  1. <a name="glJkG"></a>
  2. # 题目
  3. <a name="4vC6v"></a>
  4. ## 1.两个数组的交集
  5. 给定两个数组,编写一个函数来计算它们的交集。
  6. 示例 1:<br />输入:nums1 = [1,2,2,1], nums2 = [2,2]<br />输出:[2]
  7. 示例 2:<br />输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]<br />输出:[9,4]
  8. 说明:
  9. - 输出结果中的每个元素一定是唯一的。
  10. - 我们可以不考虑输出结果的顺序。
  11. 思路:
  12. - 求num1和num2都有的值
  13. - 用字典建立一个映射关系,记录nums1里有的值
  14. - 遍历nums2,找出nums1里也有的值
  15. - 新建一个字典,遍历nums1,填充字典
  16. - 遍历nums2,遇到字典里的值就选出来,并从字典中删除
  17. ```javascript
  18. /**
  19. * @param {number[]} nums1
  20. * @param {number[]} nums2
  21. * @return {number[]}
  22. */
  23. var intersection = function(nums1, nums2) {
  24. const map = new Map()
  25. // 把num1映射为字典,去重
  26. nums1.forEach(n => {
  27. map.set(n, true)
  28. })
  29. const res = []
  30. nums2.forEach(m => {
  31. // 如果nums2中有这个值就提取出来,并删掉map中的值
  32. // 防止nums2中还有相同的元素,提取重复
  33. if(map.get(m)) {
  34. res.push(m)
  35. map.delete(m)
  36. }
  37. })
  38. return res
  39. };

2.有效的括号(优化)

给定一个只包括 ‘(‘,’)’,’{‘,’}’,’[‘,’]’ 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。


    示例 1:

输入:s = “()”
输出:true
示例 2:

输入:s = “()[]{}”
输出:true
示例 3:

输入:s = “(]”
输出:false
示例 4:

输入:s = “([)]”
输出:false
示例 5:

输入:s = “{[]}”
输出:true

提示:

  • 1<= s.length <= 104
  • s仅由括号 ‘()[]{}’ 组成 ```javascript /**
    • @param {string} s
    • @return {boolean} */ var isValid = function(s) {

const map = new Map() map.set(‘(‘, ‘)’) map.set(‘[‘, ‘]’) map.set(‘{‘, ‘}’)

// 定义栈 let stack = [] // 判断字符串的长度,小于2,返回false if(s.length < 2) return false // 得到每一个括号

for(let i= 0; i< s.length;i++) { let c = s[i] // 判断左右括号的类型 // let type = ch(c)

  1. // 左括号入栈,右括号出栈
  2. if(map.has(c)) {
  3. stack.push(c)
  4. } else {
  5. // 特殊情况处理,第一个出现的右括号必须和相邻的左边括号是相反的一样的括号
  6. if(map.get(stack[stack.length -1]) !== c) {
  7. return false
  8. }
  9. stack.pop()
  10. }

} if(stack.length !== 0) return false

return true };

<a name="Ujtpa"></a>
## 3.两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。<br />你可以按任意顺序返回答案。

示例 1:<br />输入:nums = [2,7,11,15], target = 9<br />输出:[0,1]<br />解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:<br />输入:nums = [3,2,4], target = 6<br />输出:[1,2]

示例 3:<br />输入:nums = [3,3], target = 6<br />输出:[0,1]

提示:

- 2 <= nums.length <= 103
- -109 <= nums[i] <= 109
- -109 <= target <= 109
- 只会存在一个有效答案

思路:

- 新建一个字典作为婚姻介绍所
- nums里的值,逐个来介绍所找对象,没有合适的就登记着,有了就牵手成功
```javascript
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
      // 新建字典
    let map = new Map()
    for(let i=0;i<nums.length;i++) {
          // 逐个获取信息
        const n = 获取需要寻找的信息
        const n2 = target - n
        // 如果字典中有就直接返回
        if(map.has(n2)) {
            return [map.get(n2), i]
        } else {
              // 没有就先登记
            map.set(n, i)
        }
    }

};

4.无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3

示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,”pwke” 是一个子序列,不是子串。

示例 4:
输入: s = “”
输出: 0

提示:

  • 0 <= s.length <= 5 * 104
  • s 由英文字母、数字、符号和空格组成

思路:

  • 先找出所有不包含重复字符的子串
  • 找出长度最大的那个子串,返回其长度即可

解题:

  • 用双指针维护一个滑动窗口(记录起始和结束为止的下标),用来剪切子串
  • 不断移动右指针,遇到重复字符,就把左指针移动到重复字符的下一位
  • 过程中,记录所有窗口的长度,并返回最大值
    var lengthOfLongestSubstring = function (s) {
      let l = 0; // 定义左指针
      let res = 0; // 结果
      let map = new Map(); // 存放字符和对应下标
      for (let r = 0; r < s.length; r++) {
          // 如果出现了重复字符,则把左指针移到重复字符的下一位。注意同时满足重复字符的索引大于左指针。
          if (map.has(s[r]) && map.get(s[r]) >= l) {
              l = map.get(s[r]) + 1;
          }
          res = Math.max(res, r - l + 1); // 计算结果
          map.set(s[r], r); // 存下每个字符的下标
      }
      return res;
    };
    

    5.最小覆盖子串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。

注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例 1:
输入:s = “ADOBECODEBANC”, t = “ABC”
输出:”BANC”

示例 2:
输入:s = “a”, t = “a”
输出:”a”

提示:

  • 1 <= s.length, t.length <= 105
  • s 和 t 由英文字母组成

思路:

  • 先找出所有包含T的子串
  • 找出最长的那个子串,返回即可

解题:

  • 用双指针维护滑动窗口
  • 移动右指针,找到包含T的子串,移动左指针,尽量减少包含T的子串的长度
    /**
    * @param {string} s
    * @param {string} t
    * @return {string}
    */
    var minWindow = function(s, t) {
         // 左右指针
      let l = 0
      let r = 0
      // 定义需要的元素
      const need = new Map()
      for(let c of t) {
            // 设置需要的元素,key为数组中的值, value为需要的数量
          need.set(c, need.has(c) ? need.get(c) + 1 : 1)
      }
        // 定义需要的元素的长度
      let needType = need.size
      // 初始化返回结果
      let res = ''
      // 循环条件 - 右指针小于数组的长度
      while(r < s.length) {
            // 获取右指针的值
          const c = s[r]
          // 如果需要的元素map中有值
          if(need.has(c)) {
                // 则将需要的元素的个数减一
              need.set(c, need.get(c) - 1)
                // 同时将需要的元素长度减一
              if(need.get(c) === 0) needType -= 1
          }
            // 循环条件 - 需要的长度不为0
          while(needType === 0) {
                // 获取每次循环拿到的符合条件的子串
              const newRes = s.substring(l, r+1)
              // 将最长的子串赋值给res
              if(!res || newRes.length < res.length) res = newRes
                // 定义一个c2用来表示左指针的值
              const c2 = s[l]
              // 如果需要的元素中有左指针指向的值
              if(need.has(c2)) {
                    // 就给需要的单个元素的个数加1
                  need.set(c2, need.get(c2) + 1)
                    // 同时需要的所有元素的个数加1
                  if(need.get(c2) === 1) needType += 1
              }
                // 移动左指针
              l += 1
          }
            // 移动右指针
          r += 1
      }
        // 返回结果
      return res
    };