排序
冒泡排序
算法思想
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
程序流程
- 最外层循环代表趟数,由于最后一趟定位两个数的次序,所以对于n个元素的数组来说,只需要 n-1 趟
- 第二层循环代表比较数字数,对于n个元素,最初只需要比较 n-1 次
- 第二次循环从1开始,是后者与前者比较
public void bubbleSort(int[] nums) {
for(int i = 0; i < nums.length - 1; i++) {
for(int j = 1; j < nums.length - i; j++) {
if(nums[j] < nums[j-1]) {
int tmp = nums[j-1];
nums[j-1] = nums[j];
nums[j] = tmp;
}
}
}
}
快速排序
算法思想
排序思想 快速排序是一种划分交换排序。它采用了一种分治的策略,通常称其为分治法。
- 先从数列中取出一个数作为基准数。
- 分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
- 再对左右区间重复第二步,直到各区间只有一个数。
程序流程
类似树的先序遍历
private void quicksort(int[] nums, int start, int end)
{
if(start >= end)
return;
int mid = start + (end - start) / 2;
int midval = nums[mid];
int p = start, q = end;
while(p <= q)
{
while(p <= q && nums[p] < midval)
++p;
while(p <= q && nums[q] > midval)
--q;
if(p <= q)
{
swap(nums[p], nums[q]);
++p;
--q;
}
}
quicksort(nums, start, q);
quicksort(nums, p, end);
}
插入排序
算法思想
- 对于一个数组 A[0,n] 的排序问题,假设认为数组在 A[0,n-1] 排序的问题已经解决了。
- 考虑 A[n]的值,从右向左扫描有序数组 A[0,n-1] ,直到第一个小于等于 A[n] 的元素,将 A[n] 插在这个元素的后面。
程序流程
private void insertSortion(int[] nums) {
if(nums.size() < 2) return;
for(int i = 1; i < nums.size(); i++) {
int num = nums[i];
// 防止插入的数是最小的
bool flag = false;
// for循环中,若插入值是最小的,没有给最小的值安排位置
for(int j = i - 1; j > -1; j--) {
if(nums[j] > num) {
nums[j+1] = nums[j];
} else {
nums[j+1] = num;
flag = true;
break;
}
}
if(!flag) {
nums[0] = num;
}
}
return;
}
拓扑排序
算法思想
- 从有向图中选一个无前驱(入度为0)的顶点输出
- 将此顶点和以它为起点的弧删除
- 重复步骤1和步骤2,直到不存在无前驱的顶点
- 若此时输出的顶点数小于有向图中的顶点数,则说明有向图中存在回路
- 否则输出的顶点的顺序即为一个拓扑序列。
程序流程
- 建立入度表
- 创建图谱(也就是连接关系) Map<Integer, Set>,需要注意第一个建立得到的set为null,所以要判断是否为null,为null则要新建一个,不为null就添加
- 找入度为0的数入队列
- 如果队列容量大于1,则拓扑序列不唯一
- 不断遍历查询节点,把与当前节点相连的节点的入度减1,并把入度为0的结点放入数组
public boolean sequenceReconstruction(int[] nums, int[][] sequences) {
// 1.建立图谱
// 构建入度表
int[] inDegree = new int[nums.length+1];
// 创建连接关系
Map<Integer, Set<Integer>> map = new HashMap<>();
for(int[] sequence: sequences) {
for (int i = 0; i < sequence.length-1; i++) {
int key = sequence[i];
Set<Integer> set = map.get(key);
if (set==null){
set = new HashSet<>();
map.put(key, set);
}
if(!set.contains(sequence[i+1])) {
inDegree[sequence[i+1]]++;
}
set.add(sequence[i+1]);
}
}
// 2.查入度为0的数,如果入度为0,进入队列
Queue<Integer> queue = new LinkedList<>();
for (int i = 1; i < inDegree.length; i++) {
if (inDegree[i]==0){
queue.add(i);
}
}
// 3.如果队列容量大于1,返回false
if (queue.size()>1) {
return false;
}
// 4。遍历下一个节点
while(!queue.isEmpty()) {
// 获得key
int front = queue.poll();
// 遍历下一个节点
Set<Integer> set = map.get(front);
if (set==null) break;
// 遍历节点,把入度为0的结点放入数组
for (Integer val : set) {
inDegree[val]--;
if (inDegree[val]==0) {
queue.add(val);
}
}
if (queue.size()>1) {
return false;
}
}
for (int i = 1; i < inDegree.length; i++) {
if (inDegree[i]!=0) {
return false;
}
}
return true;
}
归并排序
图论
深度优先搜索
广度优先搜索/层序遍历
public void findByBFS(TreeNode root) {
if(root==null) return;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()) {
int queueSize = queue.size();
while(queueSize-- > 0) {
// 得到树的根
TreeNode node = queue.poll();
if (node.left!=null)
queue.add(node.left);
if (node.right!=null)
queue.add(node.right);
System.out.print(node.val);
}
}
}