重要算法
排序
package review.sort;
import java.util.Arrays;
/**
* @Author: xiang
* @Date: 2021/7/5 14:20
*/
public class BaseSort {
public static void main(String[] args) {
int[] array = {4,3,5,8,1,5,6,10,14,3,21,100};
System.out.println(Arrays.toString(array));
quickSort(array,0, array.length-1);
System.out.println(Arrays.toString(array));
}
// 冒泡排序
public static void bubbleSort(int[] array){
if (array == null || array.length<2) return;
boolean change = false;
for (int i=array.length-1; i > 0;i--){
for (int j=0;j<i;j++){
if (array[j] > array[j+1]){
int tmp = array[j];
array[j] = array[j+1];
array[j+1] = tmp;
change = true;
}
}
if (!change) return;
}
}
//插入排序
public static void insertSort(int[] array){
if (array == null || array.length<2) return;
for (int i=0;i<array.length;i++){
int value = array[i];
int j=i-1;
for (;j>-1;j--){
if (array[j] > value)
array[j+1] = array[j];
else
break;
}
array[j+1] = value;
}
}
// 归并排序
public static void mergeSort(int[] array,int begin,int end){
if (begin >= end) return;
int mid = (begin+end)/2;
mergeSort(array,begin,mid);
mergeSort(array,mid+1,end);
merge(array,begin,mid,end);
}
private static void merge(int[] array, int begin, int mid, int end) {
int[] tmp = new int[end-begin+1];
int left = begin;
int right = mid+1;
int i=0;
while (left < mid+1 && right<end+1){
if (array[left] <= array[right])
tmp[i++] = array[left++];
else
tmp[i++] = array[right++];
}
if (left == mid+1)
System.arraycopy(array,right,tmp,i,end-right+1);
else
System.arraycopy(array,left,tmp,i,mid-left+1);
System.arraycopy(tmp,0,array,begin,end-begin+1);
}
// 快速排序
public static void quickSort(int[] array,int begin,int end){
if (end - begin < 1) return;
int i = partition(array,begin,end);
quickSort(array,begin,i);
quickSort(array,i+1,end);
}
private static int partition(int[] array,int begin,int end) {
int i = begin;
int j = begin;
while (j<=end){
// 分区点
int value = array[end]; //选取最后一个元素作为分区点
if (array[j] <= value){
int tmp = array[i];
array[i] = array[j];
array[j] = tmp;
i++;
}
j++;
}
return i==j ? i-2:i-1;
}
}
归并算法时间复杂度计算分析
二分查找
package review.search;
import java.util.Arrays;
/**
* @Author: xiang
* @Date: 2021/7/5 17:03
*/
public class BinarySearch {
public static void main(String[] args) {
int[] array = {4,3,5,8,1,5,6,3,3,10,14,3,21,100};
Arrays.sort(array);
System.out.println(Arrays.toString(array));
System.out.println(searchFist(array,3));
System.out.println(searchLast(array,3));
System.out.println(searchFirstLargest(array,3));
System.out.println(searchLastLeast(array,3));
}
/**
* 二分查找
* 未查找到返回-1
*
* 注:求什么 就在该条件下 if ( (mid == ?) || a[mid +/- 1] ? dest)
*/
// 查找元素第一个位置
public static int searchFist(int[] a,int dest){
int left = 0;
int right = a.length-1;
while (left<=right){
int mid = (left+right)>>1;
if (a[mid] < dest){
left = mid+1;
}else if (a[mid] > dest){
right = mid-1;
}else {
if ((mid == 0) || a[mid-1] != dest)
return mid;
else
right = mid-1;
}
}
return -1;
}
// 查找元素最后一个位置
public static int searchLast(int[] a,int dest){
int left = 0;
int right = a.length-1;
while (left<=right){
int mid = (left+right)>>1;
if (a[mid] < dest){
left = mid+1;
}else if (a[mid] > dest){
right = mid-1;
}else {
if ((mid == a.length-1) || (a[mid+1] != dest))
return mid;
else
left = mid+1;
}
}
return -1;
}
// 查找第一个大于等于给定值的元素
public static int searchFirstLargest(int[] a, int dest){
int left = 0;
int right = a.length-1;
while (left<=right){
int mid = (left+right)>>1;
if (a[mid] >= dest){
if ( (mid == 0) || a[mid-1] < dest)
return mid;
else
right = mid-1;
}else {
left = mid+1;
}
}
return -1;
}
// 查找最后一个小于等于给定值的元素
public static int searchLastLeast(int[] a, int dest){
int left = 0;
int right = a.length-1;
while (left <= right){
int mid = (left + right)>>1;
if (a[mid] <= dest){
if ((mid == a.length-1) || a[mid+1] > dest)
return mid;
else
left = mid+1;
}else {
right = mid-1;
}
}
return -1;
}
}
非递归遍历二叉树
记住:
for root != nil || len(stack) > 0 {
for root != nil {
......
stack = append(stack,root)
root = root.Left
}
......
}
前序遍历
func preorderTraversal(root *TreeNode) []int {
var res []int
stack := []*TreeNode{}
for root != nil || len(stack) > 0 {
for root != nil {
res = append(res,root.Val)
stack = append(stack,root)
root = root.Left
}
root = stack[len(stack)-1].Right
stack = stack[:len(stack)-1]
}
return res
}
中序遍历
func inorderTraversal(root *TreeNode) []int {
var res []int
stack := []*TreeNode{}
for root != nil || len(stack) > 0 {
for root != nil {
stack = append(stack, root)
root = root.Left
}
root = stack[len(stack)-1].Right
res = append(res, stack[len(stack)-1].Val)
stack = stack[:len(stack)-1]
}
return res
}
后续遍历(多一个变量:上一个被记录的节点)
func postorderTraversal(root *TreeNode) []int {
var res []int
stack := []*TreeNode{}
var pre *TreeNode //上一个被记录的元素
for root != nil || len(stack) > 0 {
for root != nil {
stack = append(stack,root)
root = root.Left
}
node := stack[len(stack)-1]
if node.Right != nil && node.Right != pre {
root = node.Right
}else{
res = append(res,node.Val)
pre = node //该节点已被记录
stack = stack[:len(stack)-1]
}
}
return res
}
// 层次遍历
public static void levelOrder(TreeNode<Integer> root){
if (root == null) return;
Queue<TreeNode<Integer>> deque = new LinkedList<>();
deque.add(root);
while (!deque.isEmpty()){
TreeNode<Integer> tmp = deque.poll();
System.out.print(tmp.date + " ");
if (tmp.left != null){
deque.add(tmp.left);
}
if (tmp.right != null){
deque.add(tmp.right);
}
}
}
}
Graph图
package review.graph;
import java.util.ArrayList;
/**
* @Author: xiang
* @Date: 2021/7/6 10:24
*
* 邻接表实现图
*/
public class Graph {
private ArrayList<ArrayList<Integer>> graph;
private int size; //图中有多少种元素(节点数)
private boolean direction; //是否为有向图
// 构造图
public Graph(int size,boolean direction) {
graph = new ArrayList<>(size);
for (int i=0;i<size;i++){
graph.add(new ArrayList<>());
}
this.size = size;
this.direction = direction;
}
// 获取邻接表中的一条数据
public ArrayList<Integer> getAround(int n){
return graph.get(n);
}
// 添加元素
public void add(int start,int end){
graph.get(start).add(end);
if (!direction) graph.get(end).add(start);
size++;
}
// 删除元素
public void delete(int start,int end){
graph.get(start).remove((Integer) end);
if (!direction) graph.get(end).remove((Integer) start);
size--;
}
// 图中元素个数
public int getSize() {
return size;
}
}
package review.graph;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
/**
* @Author: xiang
* @Date: 2021/7/6 10:43
*/
public class Traversal {
public static void main(String[] args) {
Graph graph = new Graph(6, false); //六个节点(从0~5的数字)
graph.add(0,1);
graph.add(0,2);
graph.add(1,3);
graph.add(1,2);
graph.add(2,3);
graph.add(2,4);
graph.add(3,4);
graph.add(3,5);
BFS(graph,1);
System.out.println();
DFS(graph,1);
}
// 广度优先搜索 (1.遍历标识 2.队列)
public static void BFS(Graph graph,int start){
// 1.标志未访问
boolean[] visited = new boolean[graph.getSize()];
// 2.广度搜索 ==> 队列 (类似二叉树的按层遍历)
Queue<Integer> queue = new LinkedList<>();
// 注意:在放入队列中后 应立即修改为已遍历
// 3.放入将查找的初始节点
queue.add(start);
visited[start] = true;
while (!queue.isEmpty()){
// 4.取出队首元素输出 并将其未遍历的邻接点加入队列中
Integer v = queue.poll();
System.out.print(v + " --> ");
for (Integer n: graph.getAround(v)){
if (!visited[n]){
queue.add(n);
visited[n] = true; //注意:加入队列就代表已遍历了!!!
}
}
}
}
// 深度优先搜索 (1.遍历标识 2.栈)
public static void DFS(Graph graph,int start){
// 1.标志未访问
boolean[] visited = new boolean[graph.getSize()];
// 2.深度优先搜索 ==> 栈
Deque<Integer> stack = new ArrayDeque<>();
// 3.将查找的初始节点放入栈中 (同样 入栈立即为已遍历)
stack.push(start);
visited[start] = true;
while (!stack.isEmpty()){
// 4.取出栈顶元素输出 并将其未遍历的邻接点压入栈中
Integer v = stack.pop();
System.out.print(v + " ==> ");
for (Integer n: graph.getAround(v)){
if (!visited[n]){
stack.push(n);
visited[n] = true; //注意:压入栈就代表已遍历了!!!
}
}
}
}
}
Java杂记(忽略)
- 先过滤掉特殊值 ⭐
- 重要数据结构及常用方法 ⭐⭐⭐⭐⭐
// 队列
Queue<Integer> queue = new LinkedList<>();
queue.add(1);
queue.poll();
queue.peek(); //返回队首元素但不弹出
queue.contains(1); //注意!!!
queue.size();
queue.clear();
queue.isEmpty();
// 栈
Deque<Integer> stack = new ArrayDeque<>();
stack.push(1);
stack.pop();
stack.peek(); //返回队首元素但不弹出
stack.contains(1); //注意!!!
stack.size();
stack.clear();
stack.isEmpty();
/**
* 注意:堆不能存重复元素
**/
// 小顶堆
PriorityQueue<Integer> heap = new PriorityQueue<>();
heap.add(1);
heap.poll();
heap.peek(); //返回队首元素但不弹出
heap.contains(1); //注意!!!
heap.size();
heap.clear();
heap.isEmpty();
// 大顶堆
PriorityQueue<Integer> heap = new PriorityQueue<>((x,y) -> y-x);
int[] intArray = arrayList.stream().mapToInt(Integer::intValue).toArray();
- 数组copy只记这个就行了System.arraycopy(stones,0,stones,0,length);
- 没有汉字的字符串利用数组下标计数。
- int max = Integer.MIN_VALUE;
- 拷贝返回一个新数组:
copyOfRange(T[] original, int from, int to)
【左闭右开】