常用算法记录

二叉树遍历

https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/87526/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian-2/

递归解法

前序遍历

public static void preOrderRecur(TreeNode head) {
    if (head == null) {
        return;
    }
    System.out.print(head.value + " ");
    preOrderRecur(head.left);
    preOrderRecur(head.right);
}

作者:golandscape
链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/87526/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian-2/

  

中序遍历

public static void preOrderRecur(TreeNode head) {
    if (head == null) {
        return;
    }
    preOrderRecur(head.left);
    System.out.print(head.value + " ");
    preOrderRecur(head.right);
}

作者:golandscape
链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/87526/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian-2/

  

后序遍历

public static void postOrderRecur(TreeNode head) {
    if (head == null) {
        return;
    }
    postOrderRecur(head.left);
    postOrderRecur(head.right);
    System.out.print(head.value + " ");
}

作者:golandscape
链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/87526/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian-2/

  

迭代解法

本质上是在模拟递归,因为在递归的过程中使用了系统栈,所以在迭代的解法中常用 Stack 来模拟系统栈。

前序遍历

public static void preOrderIteration(TreeNode head) {
	if (head == null) {
		return;
	}
	Stack<TreeNode> stack = new Stack<>();
	stack.push(head);
	while (!stack.isEmpty()) {
		TreeNode node = stack.pop();
		System.out.print(node.value + " ");
		if (node.right != null) {
			stack.push(node.right);
		}
		if (node.left != null) {
			stack.push(node.left);
		}
	}
}

作者:golandscape
链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/87526/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian-2/

  

中序遍历

public static void inOrderIteration(TreeNode head) {
	if (head == null) {
		return;
	}
	TreeNode cur = head;
	Stack<TreeNode> stack = new Stack<>();
	while (!stack.isEmpty() || cur != null) {
		while (cur != null) {
			stack.push(cur);
			cur = cur.left;
		}
		TreeNode node = stack.pop();
		System.out.print(node.value + " ");
		if (node.right != null) {
			cur = node.right;
		}
	}
}

作者:golandscape
链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/87526/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian-2/

  

后顺遍历

public static void postOrderIteration(TreeNode head) {
		if (head == null) {
			return;
		}
		Stack<TreeNode> stack1 = new Stack<>();
		Stack<TreeNode> stack2 = new Stack<>();
		stack1.push(head);
		while (!stack1.isEmpty()) {
			TreeNode node = stack1.pop();
			stack2.push(node);
			if (node.left != null) {
				stack1.push(node.left);
			}
			if (node.right != null) {
				stack1.push(node.right);
			}
		}
		while (!stack2.isEmpty()) {
			System.out.print(stack2.pop().value + " ");
		}
	}

作者:golandscape
链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/87526/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian-2/

  

层序遍历

class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null) return 0;
        List<TreeNode> queue = new LinkedList<>() {{ add(root); }}, tmp;
        int res = 0;
        while(!queue.isEmpty()) {
            tmp = new LinkedList<>();
            for(TreeNode node : queue) {
                if(node.left != null) tmp.add(node.left);
                if(node.right != null) tmp.add(node.right);
            }
            queue = tmp;
            res++;
        }
        return res;
    }
}

作者:Krahets
链接:https://leetcode.cn/problems/er-cha-shu-de-shen-du-lcof/solutions/159058/mian-shi-ti-55-i-er-cha-shu-de-shen-du-xian-xu-bia/

  

排序算法

https://leetcode.cn/circle/article/Gwd1Z5/

https://leetcode.cn/circle/discuss/eBo9UB/#%E9%80%89%E6%8B%A9%E6%8E%92%E5%BA%8F

选择排序

public int[] selectionSortDouble(int[] arr) {
    if (arr.length < 2) return arr;
    int n = arr.length;
    for (int i = 0; i < n - 1 - i; i++) { // 每轮确定两个数字,因此上界也会动态变化
        int minIdx = i, maxIdx = i;
        for (int j = i + 1; j < n - i; j++) {
            if (arr[j] < arr[minIdx]) minIdx = j;
            if(arr[j] > arr[maxIdx]) maxIdx = j;
        }
        if(minIdx == maxIdx) break; // 若本轮最大值等于最小值,说明未排序部分所有元素相等,无需再排序
        swap(arr, i, minIdx); 
        if(maxIdx == i) maxIdx = minIdx; // 在交换 i 和 minIdx 时,有可能出现 i 即 maxIdx 的情况,此时需要修改 maxIdx 为 minIdx
        swap(arr, n - 1 - i, maxIdx); 
    }
    return arr;
}

作者:yukiyama
链接:https://leetcode.cn/circle/discuss/eBo9UB/

  

简单插入排序

// 简单插入排序:内层用 for
public int[] insertionSortUseWhile(int[] arr) {
    if (arr.length < 2) return arr;
    for (int i = 1; i < arr.length; i++) {
        int target = arr[i], j = i - 1;
        for (; j >= 0; j--) {
            if(target < arr[j]) arr[j + 1] = arr[j];
            else break;
        }
        arr[j + 1] = target;
    }
    return arr;
}

作者:yukiyama
链接:https://leetcode.cn/circle/discuss/eBo9UB/

  

双轴快排

public int[] dualPivotQuickSort(int[] arr) {
    if (arr.length < 2) return arr;
    dualPivotQuickSort(arr, 0, arr.length - 1); // 后两个参数是下标值
    return arr;
}
/*
 *     区间1               区间2                         区间3
 * +------------------------------------------------------------+
 * |  < pivot1  | pivot1 <= && <= pivot2  |    ?    | > pivot2  |
 * +------------------------------------------------------------+
 *              ^                         ^         ^
 *              |                         |         |
 *            lower                     index      upper
 */
private void dualPivotQuickSort(int[] arr, int left, int right) {
    if(left < right) { // 排序对象是right大于left的区间(即大小大于等于2的区间)
        // 令左右两端元素中较小者居左,以left为初始pivot1,right为初始pivot2
        // 即arr[left]为选定的左轴值,arr[right]为选定的右轴值
        if(arr[left] > arr[right]) {
            swap(arr, left, right);
        }
        int index = left + 1; // 当前考察元素下标
        int lower = left + 1; // 用于推进到pivot1最终位置的动态下标,总有[left, lower)确定在区间1中
        int upper = right - 1; // 用于推进到pivot2最终位置的动态下标,总有(upper, right]确定在区间3中
        // [lower, index)确定在区间2中,[index, upper]为待考察区间。

        // upper以右(不含upper)的元素都是确定在区间3的元素,所以考察元素的右界是upper
        while(index <= upper) {
            // 若arr[index] < arr[left],即arr[index]小于左轴值,则arr[index]位于区间1
            if (arr[index] < arr[left]) {
                // 交换arr[index]和arr[lower],配合后一条lower++,保证arr[index]位于区间1
                swap(arr, index, lower); 
                // lower++,扩展区间1,lower位置向右一位靠近pivot1的最终位置
                lower++;
            }
            // 若arr[index] > arr[right],即arr[index]大于右轴值,则arr[index]位于区间3
            else if(arr[index] > arr[right]) {
                // 先扩展区间3,使得如下while结束后upper以右(不含upper)的元素都位于区间3
                // 区间3左扩不可使index == upper,否则之后的第二条upper--将导致upper为一个已经确定了区间归属的元素的位置(即index - 1)
                while(arr[upper] > arr[right] && index < upper) {
                    upper--;
                }
                // 交换arr[index]和arr[upper],配合后一条upper--,保证arr[index]位于区间3
                swap(arr, index, upper);
                upper--;
                // 上述交换后,index上的数字已经改变,只知道此时arr[index] ≤ arr[right],arr[index]有可能在区间1或区间2,
                // 若arr[index] < arr[left],即arr[index]小于左轴值,则arr[index]位于区间1
                if(arr[index] < arr[left]) {
                    // 交换arr[index]和arr[lower],配合后一条lower++,保证arr[index]位于区间1
                    swap(arr, index, lower);
                    // lower++,扩展区间1,lower位置向右一位靠近pivot1的最终位置
                    lower++;
                }
            }
            index++; // 考察下一个数字
        }
        // while(index <= upper)结束后最后一个确定在区间1的元素的下标是lower--,
        // 最后一个确定在区间3的元素下标是upper++。
        lower--;
        upper++;
        // 双轴归位。此时的lower,upper即分别为最终pivot1(初始时为left),最终pivot2(初始时为right)。
        swap(arr, left, lower);
        swap(arr, upper, right);
        // 对三个子区间分别执行双轴快排
        dualPivotQuickSort(arr, left, lower - 1); // 区间1
        dualPivotQuickSort(arr, lower + 1, upper - 1); // 区间2
        dualPivotQuickSort(arr, upper + 1, right); // 区间3
    }
}

作者:yukiyama
链接:https://leetcode.cn/circle/discuss/eBo9UB/

  

普通快排

package algorithm.chapter11;
import java.util.Arrays;

public class Solution {
public void quickSort(int[] arr, int left, int right) {
        if (left >= right) {
            return;
        }
        int l = left;
        int r = right;
        while (l < r) {
        //右面元素比left大,左面元素比left小
while (arr[r] >= arr[left] && l < r) { r--; } while (arr[l] <= arr[left] && l < r) { l++; } if (l < r) { int tmp = arr[l]; arr[l] = arr[r]; arr[r] = tmp; } }
      //比较一轮 就把left和l元素调换位置, 再左面部分和右面部分分别递归。
int tmp2 = arr[left]; arr[left] = arr[l]; arr[l] = tmp2; quickSort(arr, left, l - 1); quickSort(arr, l + 1, right); } }

 

 

堆排序

https://www.cnblogs.com/jiangym/p/17521231.html

链表

反转链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null){
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }
        
        return pre;
    }
}

环形链表

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head, slow = head;
        while (true) {
            if (fast == null || fast.next == null) return null;
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) break;
        }
        fast = head;
        while (slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }
        return fast;
    }
}

作者:Krahets
链接:https://leetcode.cn/problems/linked-list-cycle-ii/solutions/12616/linked-list-cycle-ii-kuai-man-zhi-zhen-shuang-zhi-/

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

题解

设两指针 fastslow 指向链表头部 headfast 每轮走 2&amp;amp;amp;amp;amp;amp;lt;span class="katex"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;span class="katex-mathml"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;span class="katex-html"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;span class="base"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;span class="strut"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;span class="mord"&amp;amp;amp;amp;amp;amp;gt;步,&amp;amp;amp;amp;amp;amp;lt;code&amp;amp;amp;amp;amp;amp;gt;slow&amp;amp;amp;amp;amp;amp;lt;/code&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;amp;nbsp;每轮走 1&amp;amp;amp;amp;amp;amp;lt;span class="math math-inline"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;span class="katex"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;span class="katex-mathml"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;span class="katex-html"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;span class="base"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;span class="strut"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;span class="mord"&amp;amp;amp;amp;amp;amp;gt;步;

双指针第一次相遇:

第一种结果: fast 指针走过链表末端,说明链表无环,直接返回 null

第二种结果: 当fast == slow时, 两指针在环中 第一次相遇 。

  指针 位置不变 ,将fast指针重新 指向链表头部节点 ;slowfast同时每轮向前走 1&amp;amp;amp;amp;amp;amp;lt;span class="katex"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;span class="katex-mathml"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;span class="katex-html"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;span class="base"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;span class="strut"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;span class="mord"&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;amp;nbsp;步;

返回slow指针指向的节点。

 

 

 

交替打印0-100(滴滴)

 1 public class PrintNum {
 2 
 3     public static void main(String[] args) {
 4         MyTask myTask = new MyTask();
 5 
 6         Thread thread = new Thread(()->{
 7             for(int i = 1; i <= 10; i+=2){
 8                 myTask.print(i);
 9 
10             }
11         },"线程A");
12         Thread thread2 = new Thread(()->{
13             for(int i = 2; i <= 10; i+=2){
14                 myTask.print(i);
15             }
16         },"线程B");
17         thread.start();
18         thread2.start();
19     }
20 }
21 
22 class MyTask{
23     public synchronized void print(int i){
24         notify();
25         System.out.println(Thread.currentThread().getName()+ "i = " + i);
26         try {
27             wait();
28         } catch (InterruptedException e) {
29             throw new RuntimeException(e);
30         }
31     }
32 }

 

 

火车站售票 1-100

 1 public class SalesTicket {
 2     public static void main(String[] args) {
 3         Ticket ticket = new Ticket();
 4         new Thread(ticket,"窗口1——").start();
 5         new Thread(ticket,"窗口2——").start();
 6         new Thread(ticket,"窗口3——").start();
 7 
 8     }
 9 
10 
11 }
12 class Ticket implements Runnable{
13     private static Integer ticket = 100;
14 
15     ReentrantLock reentrantLock = new ReentrantLock(true);
16     @Override
17     public void run() {
18         while(true){
19             reentrantLock.lock();
20             try{
21                 if(ticket > 0){
22                     Thread.sleep(100L);
23                     System.out.println("线程:"+Thread.currentThread().getName() + ":剩余车票:ticket = " + ticket);
24                     ticket--;
25                 }else{
26                     break;
27                 }
28             }catch (Exception e){
29                 System.out.println("error = " + e.getMessage());
30             }finally {
31                 reentrantLock.unlock();
32             }
33 
34         }
35     }
36 }

 

 

生产者消费者(美团)

todo

 

posted @ 2023-07-07 10:18  CodingOneTheWay  阅读(17)  评论(0编辑  收藏  举报
回到顶部