优先队列 Priority Queue
与普通队列的区别
保证每次取出的元素是队列中优先级最高的。优先级别可自定义(可以是数值越小优先级别越高或数值越大优先级别越高)
本质
二叉堆的结构,堆在英文里叫 Binary Heap
利用一个数组结构来实现完全二叉树(数组中的各个元素有其他元素作为子节点或者父节点)
特性
数组里的第一个元素array[0]拥有最高的优先级
对于给定一个下标i,那么对于元素array[i]而言
父节点:对应的元素下标是(i-1)/2
左侧子节点:对应的元素下标是2i+1
右侧子节点:对应的元素下标是2i+2
数组中每个元素的优先级都必须要高于它俩侧子节点
最基本的操作有俩个:
向上筛选:当加入一个新元素,先放在最底端,然后跟父节点进行比较,新元素优先级高则交换,直到结束。时间复杂度 OlogK
向下筛选:当弹出头结点,先将头节点一直往下爬,和左子节点交换,到最底端后,弹出。时间复杂度OlogK
初始化一个优先队列的时间负责度是On
leecode347.前K个高频元素
实现:
循环用map集合存放元素和出现的次数
将map的entry存入PriorityQueue里面 ,比较器是元素的个数
让弹出前k个元素,存入数组中返回
//给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
//
//
//
// 示例 1:
//
// 输入: nums = [1,1,1,2,2,3], k = 2
//输出: [1,2]
class Solution {
public Map<Integer,Integer> map=new HashMap<>();
public int[] topKFrequent(int[] nums, int k) {
for (int num : nums) {
map.put(num,map.getOrDefault(num,0)+1);
}
PriorityQueue<Map.Entry<Integer,Integer>> queue=new PriorityQueue<>(( o1, o2)-> {
return o2.getValue()-o1.getValue();
});
queue.addAll(map.entrySet());
int[] result=new int[k];
for (int i = 0; i <k ; i++) {
result[i]=queue.poll().getKey();
}
return result;
}
}
图 Graph
基本知识点:
阶,度
树,森林,环
有向图,无向图,完全有向图,完全无向图
连通图,连通分量
图的存储与表达方式:邻接矩阵,邻接链表
围绕图的算法:
图的遍历:深度优先,广度优先
环的检测:有向图,无向图
拓扑排序
最短路径算法:
连通性相关算法:Kosaraju ,Tarjan,求解孤岛的数量,判断是否为树
图的着色,旅行商问题等
必须熟练掌握的知识点
图的存储和表达方式:邻接矩阵,邻接链表
图的遍历:深度优先,广度优先
二部图的检测,树的检测,环的检测:有向图,无向图
拓扑排序,联合查找算法,最短路径算法
leecode785.判断二分图
给定一个无向图graph,当这个图为二分图时返回true。
//
// 如果我们能将一个图的节点集合分割成两个独立的子集A和B,并使图中的每一条边的两个节点一个来自A集合,一个来自B集合,我们就将这个图称为二分图。
//
// graph将会以邻接表方式给出,graph[i]表示图中与节点i相连的所有节点。每个节点都是一个在0到graph.length-1之间的整数。这图中没有自
//环和平行边: graph[i] 中不存在i,并且graph[i]中没有重复的值。
//
//
//
//示例 1:
//输入: [[1,3], [0,2], [1,3], [0,2]]
//输出: true
//解释:
//无向图如下:
//0----1
//| |
//| |
//3----2
//我们可以将节点分成两组: {0, 2} 和 {1, 3}。
我还不会写
前缀树 Trie
- 也称为字典树 (这种数据结构被广泛地运用于字典查找当中)
- 字典查找
给定一系列构成字典的字符串,要求在字典当中找出所有以“ABC”开头的字符串
重要性质
每个节点至少包含俩个基本属性 - children:数组或者集合,罗列出每个分支当中包含的所有字符
- isEnd:布尔值,表示该节点是否为某字符串的结尾
根节点是空的
除了根节点,其他所有节点都有可能是单词的结尾,叶子节点一定都是单词的结尾
最基本的操作
创建方法
遍历一遍输入的字符串,对每个字符串的字符进行遍历
从前缀树的根节点开始,将每个字符加入到节点的children字符集当中
如果字符集已经包含了当前这个字符,跳过
如果当前字符是某一个字符串的最后一个,把当前字符的isEnd标记为真
搜索方法
从前缀树的根节点出发,逐个匹配输入的前缀字符
如果遇到了,继续往下一层搜索
如果没遇到,立即返回
leecode212.单词搜索||
//给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。
//
// 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
//
// 示例:
//
// 输入:
//words = ["oath","pea","eat","rain"] and board =
//[
// ['o','a','a','n'],
// ['e','t','a','e'],
// ['i','h','k','r'],
// ['i','f','l','v']
//]
//
//输出: ["eat","oath"]
//
// 说明:
//你可以假设所有输入都由小写字母 a-z 组成。
线段树 Segment Tree
一种按照二叉树的形式存储数据的结构,每个节点保存的都是数组里某一段的总和
=leecode315.计算右侧小于当前元素的个数
//给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 num
//s[i] 的元素的数量。
//
// 示例:
//
// 输入:nums = [5,2,6,1]
//输出:[2,1,1,0]
//解释:
//5 的右侧有 2 个更小的元素 (2 和 1)
//2 的右侧仅有 1 个更小的元素 (1)
//6 的右侧有 1 个更小的元素 (1)
//1 的右侧有 0 个更小的元素
树状数组 Fenwick Tree
- 也被称为 Binary Indexed Tree
例题
假设我们有一个数组array[0…n-1],里面有n个元素,现在我们要经常对这个数组做俩件事:
- 更新数组元素的数值
- 求数组前k个元素的总和(或者平均值)
方法一:线段树 time:O(logn)
方法二:树状数组 time:O(logn)
基本特征
利用数组来表示多叉树的结构,和优先队列有些类似
优先队列是用数组来表示完全二叉树,而树状数组是多叉树
树状数组的第一个节点是空节点
如果节点tree[y]是tree[x]的父节点,那么需要满足y=x-(x&(-x))
leecode308.二维区域和检索