数据结构
数组
数组的存放 int[][] array={{}{}} 存放地址
二分查找
元素是否唯一,不唯一则无法二分查找
- 取中值时要避免数据溢出,middle = left + (right - left)/2
- 一定要注意边界的处理
- 有关大于小于号判断,一定要找最贴切的一个符号。
- C++ int long 各种符号类型 重新复习;不同数据类型数学运算有啥结果
多次二分查找该如何使用:一定要读懂题目意思,找两个边界该用什么样的方法
移除元素(双指针法)
- 要先确定判断条件对应的状态以及特殊情况会产生的影响。
- 从前向后判断,还是从后向前判断。(884 比较含退格的字符串)
有序数组的平方
- 双指针
- 各种排序算法还未学习
长度最小的子数组
- 暴力解法
两个for循环 - 滑动窗口
结合hash表求解,76题未做(不懂hash表)
最小覆盖子串
螺旋数组
遵循同一个原则,避免漏掉
链表
基础理论
通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域,最后一个节点的指针域指向null。
单链表
单向指针
双链表
双链表:每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点。
循环链表
链表首尾相连,可以用来解决约瑟夫环问题。
链表节点定义
struct ListNode{
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL){} //节点的构造函数
};
//自定义初始化节点
ListNode* head = new ListNode(5);
//默认初始化节点
ListNode* head = new ListNode();
head->val = 5;
// delete list node
// 从内存中删除移除的节点,清理内存
//设置虚拟头结点,或直接从原list移除
// add list node
反转链表
1.(双指针法)
使用空间保存原始下一个指针
2. 递归法:定义一个递归函数,调换两者指针,指导一个指针为空停止递归
两两交换链表节点
双指针
先得到距离为n的两指针
再定位最末端与待删除的前一个节点。
链表相交
使链表末端对齐,即将长链表指针移至短链表头部;
依次判断两节点是否相等(节点,非数值)
环形链表
- 利用哈希表遍历所有节点
- 双指针,快指针 慢指针;从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点。
哈希表
哈希表是根据关键码的值而直接进行访问的数据结构。
一般哈希表都是用来快速判断一个元素是否出现集合里。使用哈希表的话, 只需要O(1)就可以做到。
哈希函数、哈希编码、哈希碰撞
哈希碰撞有两种解决方法, 拉链法和线性探测法
哈希碰撞
解决哈希编码后的数值大于哈希表大小问题
- 拉链法 将数据存在链表中
- 线性探测法
常见的三种哈希结构
哈希表总结
- 数组
- set (集合) :set;multiset;unordered_set(哈希表)
- map(映射):map是一种key value的存储结构,可以用key保存数值,用value在保存数值所在的下标。
std::unordered_map 底层实现为哈希表,std::map 和std::multimap 的底层实现是红黑树。
- 如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费
- set是一个集合,里面放的元素只能是一个key
字符串处理用数组vector
题1:有效字母异位词\赎金信(普通哈希)
数组处理(哈希值比较少),用set,map
题2:字母异位词分组(将每个字母出现的次数使用字符串表示,作为哈希表的键)unordered_map
题3:快乐数 unordered_set
哈希表的find搜索速度比for循环快很多,但占内存。
使用数组和set来做哈希法的局限
1. 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
2. set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。
三数之和、四数之和、N数之和:双指针法,注意去重
均是: for 循环、剪枝、去重、再指针