4.1 基础算法
4.1.1 冒泡排序
for(int i = 0; i < arr.length - 1; i++){
for(int j = 0; j < arr.length - 1 - i; j++){
if(arr[j] > arr[j + 1]){
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
4.1.2 二分查找
public static int binSearch(int[] array, int target){
int low = 0, high = array.length, mid = 0;
while(low <= high){
mid = low + (high - low) / 2;
if(array[mid] == target){
return mid;
}else if(target > array[mid]){
low = mid + 1;
}else{
high = mid - 1;
}
}
return -1;
}
4.1.3 插入排序
public static int[] insertSort(int[] arr){
// 取出未排序的第一个元素
for(int i = 1; i < arr.length; i++){
int value = arr[i]; // 取出未排序的第一个元素
int index = i - 1; // 已排序的最后一个位置
while(index >= 0 && value < arr[index]){
// 未排序的第一个元素小于已排序的元素(从后往前)
arr[index + 1] = arr[index]; // 原来排序的元素移动到后边
index--; // index指向已排序的元素,从后往前移动地插入
}
arr[index + 1] = value; // 将元素插入到刚好arr[x]的前边。
}
return arr;
}
public static int[] insertSort(int[] arr){
for(int i = 1; i < arr.length; i++){
int value = arr[i];
int index = i - 1;
while(index >= 0 && value < arr[index]){
arr[index + 1] = arr[index--];
}
arr[index + 1] = value;
}
return arr;
}
4.1.4 快速排序
public static void quickSort(int[] arr, int low, int high){
if(low < high){
int pivot = partition(arr,low,high);
quickSort(arr,low,pivot - 1);
quickSort(arr,pivot + 1, high);
}
}
private static int partition(int[] arr, int low, int high){
int pivot = arr[high];
while(low < high){
while(low < high && arr[low] < pivot){
low++;
}
arr[high] = arr[low];
while(low < high && arr[high] >= pivot){
high--;
}
arr[low] = arr[high];
}
arr[high] = pivot;
return high;
}
4.1.5 归并排序
package study.sort;
public class Merge {
//归并排序所需要的辅助数组
private static Comparable[] assist;
//对数组内的元素进行排序
public static void sort(Comparable[] a){
assist = new Comparable[a.length];
int lo = 0;
int hi = a.length - 1;
sort(a,lo,hi);
}
//对数组a中从索引lo到索引hi之间的元素进行排序
private static void sort(Comparable[] a,int lo,int hi){
//只有一个数据,不用排序了
if (hi <= lo){
return;
}
int mid = lo + (hi - lo) / 2;
//对lo到mid之间的元素进行排序
sort(a,lo,mid);
//对mid + 1到hi之间的元素进行排序
sort(a,mid + 1,hi);
//对lo到mid这组数据和mid到hi这组数据进行归并
merge(a,lo,mid,hi);
}
//从索引lo到所以mid为一个子组,从索引mid+1到索引hi为另一个子组,
// 把数组a中的这两个子组的数据合并成一个有序的大组(从索引lo到索引hi)
private static void merge(Comparable[] a,int lo,int mid,int hi){
//lo到mid这组数据和mid + 1到hi这组数据归并到辅助数组assist对应的索引处
int i = lo;//定义一个指针,指向assist数组中开始填充数据的索引
int p1 = lo;//定义一个指针,指向第一组数据的第一个元素
int p2 = mid + 1;//定义一个指针,指向第二组数据的第一个元素
//比较左边小组和右边小组中的元素大小,哪个小,就把哪个数据填充到assist数组中
while (p1 <= mid && p2 <= hi){
if (less(a[p1],a[p2])){
assist[i++] = a[p1++];
}else {
assist[i++] = a[p2++];
}
}
//上面的循环结束后,如果退出循环的条件是p1 > mid,则证明左边小组中的数据已经归并完毕,
// 如果退 出循环的条件是p2 > =hi,则证明右边小组的数据已经填充完毕;
// 所以需要把未填充完毕的数据继续填充到assist中,
// 下面两个循环,只会执行其中的一个
while (p1 <= mid){
assist[i++] = a[p1++];
}
while (p2 <= hi){
assist[i++] = a[p2++];
}
//那么现在,assist数组中,从lo到hi的元素是有序的,再把数据拷贝到a数组中对应的索引处
for (int index = lo; index <= hi ; index++) {
a[index] = assist[index];
}
}
//判断v是否小于w
private static boolean less(Comparable v, Comparable w) {
return v.compareTo(w) < 0;
}
//交换a数组中,索引i和索引j处的值
private static void exchange(Comparable[] a, int i, int j) {
Comparable temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
4.2 综合
4.2.1 LRU
class LRUCache {
private Map<Integer,Node> map;
private Node head, tail;
private Integer capacity;
public LRUCache(int capacity) {
this.capacity = capacity;
map = new HashMap();
head = new Node(-1,-1);
tail = new Node(-1,-1);
head.next = tail;
tail.pre = head;
}
public int get(int key) {
if(map.containsKey(key)){
Node temp = map.get(key);
cutNode(temp);
insertHead(temp);
return temp.val;
}
return -1;
}
public void put(int key, int value) {
Node temp = new Node(key,value);
if(map.containsKey(key)){
Node node = map.get(key);
cutNode(node);
}else if(map.size() >= capacity){
map.remove(cutNode(node).key);
}
map.put(key,temp);
insertHead(temp);
}
private class Node{
Node pre;
Node next;
int val;
int key;
Node(int key, int val){
this.key = key;
this.val = val;
}
}
private void cutNode(Node temp){
temp.pre.next = temp.next;
temp.next.pre = temp.pre;
temp.pre = null;
temp.next = null;
}
private void insertHead(Node temp){
temp.next = head.next;
head.next.pre = temp;
head.next = temp;
temp.pre = head;
}
}
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
4.2.2 判断一棵树是否是平衡二叉树
public class IsBBT{
}
4.2.3 反转一个链表
public class LinkedListReversal{
class ListNode{
ListNode next;
int val;
public ListNode(int val){
this.val = val;
}
}
public static ListNode reverse(ListNode head){
if(head == null) return head;
ListNode pre = null, cur = head;
while(cur != null){
ListNode temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
public static void printList(ListNode head){
while(head != null){
System.out.print(head.val + " ");
head = head.next;
}
System.out.println();
}
public static void main(String[] args){
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
printList(head);
ListNode reverse = reverse(head);
printList(reverse);
}
}
4.2.4 实现一个hash表
// table = ArrayList<Entry>();
// hash(key) Math.abs(key.hashCode()) % table.size
///
4.2.4 找出两个链表的交点
class ListNode{
ListNode next;
int val;
public ListNode(int val){
this.val = val;
}
}
public class LinedListIntersection{
public static ListNode find(ListNode l1, ListNode l2){
ListNode cur1 = l1, cur2 = l2;
while(cur1 != cur2){
cur1 = cur1 == null ? l2 : cur1.next;
cur2 = cur2 == null ? l1 : cur2.next;
}
return cur1;
}
}
4.2.5 监测单链表中是否有环
// 快慢指针
public class LinkedNode{
private int val;
private LinkedNode next;
public LinkedNode(int val){
this.val = val;
}
public static boolean isCircle(LinkedList head){
LinkedNode slow = head, fast = head;
while(slow != fast && fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
}
return fast != null;
}
}
4.2.6 实现一个图和DFS以及BFS
class Graph{
private Map<Integer, List<Integer>> graph;
public Graph() {
graph = new HashMap<>();
}
public void addEdge(int v, int w) {
graph.computeIfAbsent(v, k -> new ArrayList<>()).add(w);
graph.computeIfAbsent(w, k -> new ArrayList<>()).add(v);
}
public void DFS(int start) {
Set<Integer> visited = new HashSet<>();
dfsUtil(start,visited);
}
private void dfsUtil(int v, Set<Integer> visited) {
System.out.println("dfs: " + v);
visited.add(v);
List<Integer> neighbors = graph.get(v);
for (Integer neighbor : neighbors) {
if (!visited.contains(neighbor)) {
dfsUtil(neighbor, visited);
}
}
}
public void BFS(int start) {
Queue<Integer> queue = new LinkedList<>();
Set<Integer> visited = new HashSet<>();
queue.add(start);
visited.add(start);
while (!queue.isEmpty()) {
Integer temp = queue.poll();
System.out.println("BFS: " + temp);
List<Integer> neighbors = graph.get(temp);
for (Integer neighbor : neighbors) {
if(!visited.contains(neighbor)) {
visited.add(neighbor);
queue.add(neighbor);
}
}
}
}
}
4.2.7 给定一个数组,找出其中最大子数组和
class MaxSubArray{
public static int maxSubArray(int[] arr){
int max = Integer.MIN_VALUE;
int sum = 0;
for(int i = 0; i < arr.length; i++){
sum = sum < 0 ? arr[i] ? arr[i] + sum;
max = Math.max(max, sum);
}
return max;
}
}
4.2.8 实现二叉树的中、前、后序遍历
// 前序:根左右
// 中序:左根右
// 后序:左右根
4.2.9 找出一个字符串的最长回文串
class MaxABA{
public class find(String s){
int maxLen = 0, start = 0;
for(int i = 0; i < s.length(); ){
int l = i, r = i;
while(r + 1 < s.length() && s.charAt(r) == s.charAt(r + 1)){
r++;
}
i = r + 1;
while(l > 0 && r < s.length() - 1 && s.charAt(l-1) == s.charAt(r + 1)){
l--;
r++;
}
if(r - l + 1 > maxLen){
start = l;
maxLen = r - l + 1;
}
}
return s.substring(start, maxLen);
}
}
4.2.10 两数之和
public class TwoSum{
public static int[] twoSum(int[] arr, target){
Map<Integer,Integer> map = new HashMap();
for(int i = 0; i < arr.length; i++){
int temp = target - arr[i];
if(map.contains(temp)){
return new int[]{map.get(temp), i};
}
map.put(arr[i], i);
}
return new int[2];
}
}
4.2.11 基于数组的栈
public class ArrayStack{
private int capacity;
private int top;
private int array;
public ArrayStack(int cap){
this.capacity = cap;
top = -1;
array = new int[cap];
}
public int pop(){
if(isEmpty()){
throw new IllegalStateException("Stack is empty");
}
return array[top--];
}
public int peek(){
if(isEmpty()){
throw new IllegalStateException("Stack is empty");
}
return array[top];
}
public int push(int val){
if(isFull()){
throw new StackOverflowError("Stack is full");
}
return array[++top];
}
public boolean isEmpty(){
return top == -1;
}
pulbic boolean isFull(){
return top == capacity - 1;
}
public int size(){
return top + 1;
}
}
4.2.12 二叉树层序遍历
class TreeNode{
TreeNode left;
TreeNode right;
int val;
public TreeNode(int val){
this.val = val;
}
public static void OrderTraversal(TreeNode root){
if(root == null) return;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()){
TreeNode temp = queue.poll();
// sout(temp) 访问该节点
if(temp.left != null) queue.add(temp.left);
if(tmep.right != null) queue.add(temp.right);
}
}
}
4.2.13 排序数组中查找值,如果没有则返回应该插入的位置
public class BinSearch{
public static int find(int[] arr, int target){
int low = 0, high = arr.length - 1;
while(low <= high){
int mid = low + (high - low) / 2;
if(arr[mid] == target){
return mid;
}else if(arr[mid] < target){
low = mid + 1;
}else {
high = mid - 1;
}
}
return low;
}
}