一、哈希图
HASH(key)= key MOD p; 解决哈希冲突的方法有:线性探测、拉链法等。
第一题(1 两数之和)
- unordered_map<int, int>,定义哈希图
- nums.size(),计算 vector 长度
- hashtable.find() 搜索,hashtable.end() 搜索不到的返回;it 承担迭代结果
- hashtable[nums[i]] = i,哈希表赋值
第二题(49 字母异位词分组)
- .emplace_back(str) 等价于 mp[key].push_back(str);但 emplace_back 更高效(原地构造)。
- 现代 C++ 的理念就是:只要类型太复杂,就用 auto。让编译器推导。
- string key = str;用 key 来代替 str 否则原字符串会被改变
- 在迭代器里推荐 ++it
sort(key.begin(), key.end());可用于对字符串的排序,复杂度为 O(n log n),这是升序排序,此外还有:sort(v.begin(), v.end(), greater());降序排序;自定义比较器(return 后的内容可根据实际情况替换)。
第三题(128 最长连续序列)
- unordered_set st(nums.begin(), nums.end());构建了一个哈希集合,且自动去重
- const string& s,可用来避免昂贵的拷贝
一些哈希相关的函数:①count(x),判断元素是否存在(速度比.contains() 快得多)②find(x),同上,但可取得迭代器 ③size() 大小 ④empty() 判断空 ⑤insert() 插入
二、双指针
第四题(238 移动零)
- vector 的长度:nums.size()
- swap(nums[left], nums[right]);交换数组的两个元素
第五题(11 盛最多水的容器)
- r = height.size()- 1;
- --r;右指针是递减的
- 为何用题解方法消耗内存较大?
思路关键:每次移动对应高度较小的那一个指针
第六题(15 三数之和)
- 不重复意味着要排序
- ans.push_back({nums[first], nums[second], nums[third]}); {a, b, c} 是一个 initializer_list,它会自动构造成一个 vector, 然后传给 ans.push_back
- 主要思路就是,首先排序,然后固定 first,second 和 third 的变动是并列的
从下面开始用 Java 写了
第七题(42 接雨水)
- 思路:计算每一个 i 对应的 leftMax 和 rightMax,这决定了该位置能积攒多少水,动态规划
- for (int i = n-2; i >= 0; i--)rightMax 应该从右往左遍历 2,即递减
- leftMax[i] = Math.max(leftMax[i-1], height[i]);最大值比较包含 i 位置自身
- int[] a = new int[n];记得限定长度
- 数组 n.length
三、滑动窗口
第八题(3 无重复字符的最长子串)
- Set occ = new HashSet();定义哈希表
- 初始化 rk = -1,且在滑动过程中是一个单增的量,因为右指针扫过的地方已经确定无重复,只需向后扩张
- 字符串 s.length();s.charAt(i)
- occ.remove(s.charAt(i-1)); occ.add(s.charAt(rk + 1)); occ.contains(s.charAt(rk + 1))几个相关的哈希表的函数
- rk - i +1 这样比 occ.size() 效率高
新增使用 HashMap 的方法(上面是使用集合的做法)。


