diff --git a/README.md b/README.md index ed79cc2..4d014cd 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ * [q54_螺旋矩阵](/src/数组操作/q54_螺旋矩阵) * [q73_矩阵置零](/src/数组操作/q73_矩阵置零) * [q78_子集](/src/数组操作/q78_子集) +* [q384_打乱数组](/src/数组操作/q384_打乱数组) * [q581_最短无序连续子数组](/src/数组操作/q581_最短无序连续子数组) * [q945_使数组唯一的最小增量](/src/数组操作/q945_使数组唯一的最小增量) diff --git a/Rocket.md b/Rocket.md index 93833b7..c6fa02b 100644 --- a/Rocket.md +++ b/Rocket.md @@ -552,6 +552,8 @@ AQS有两个队列,同步对列和条件队列。同步队列依赖一个双 3. SynchronousQueue:本身不带有空间来存储任何元素,使用上可以选择公平模式和非公平模式。 4. PriorityBlockingQueue:无界队列,基于数组,数据结构为二叉堆,数组第一个也是树的根节点总是最小值。 +举例 ArrayBlockingQueue 实现并发同步的原理:原理就是读操作和写操作都需要获取到 AQS 独占锁才能进行操作。如果队列为空,这个时候读操作的线程进入到读线程队列排队,等待写线程写入新的元素,然后唤醒读线程队列的第一个等待线程。如果队列已满,这个时候写操作的线程进入到写线程队列排队,等待读线程将队列元素移除腾出空间,然后唤醒写线程队列的第一个等待线程。 + ### 线程池的拒绝策略 1. ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 diff --git a/src/数组操作/q384_打乱数组/Solution.java b/src/数组操作/q384_打乱数组/Solution.java new file mode 100644 index 0000000..f7a5831 --- /dev/null +++ b/src/数组操作/q384_打乱数组/Solution.java @@ -0,0 +1,46 @@ +package 数组操作.q384_打乱数组; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +/** + * 洗牌算法 o(n) + */ +public class Solution { + private int[] array; + private int[] original; + + private Random rand = new Random(); + + private List getArrayCopy() { + List asList = new ArrayList<>(); + for (int i = 0; i < array.length; i++) { + asList.add(array[i]); + } + return asList; + } + + public Solution(int[] nums) { + array = nums; + original = nums.clone(); + } + + public int[] reset() { + array = original; + original = original.clone(); + return array; + } + + public int[] shuffle() { + List aux = getArrayCopy(); + + for (int i = 0; i < array.length; i++) { + int removeIdx = rand.nextInt(aux.size()); + array[i] = aux.get(removeIdx); + aux.remove(removeIdx); + } + + return array; + } +} \ No newline at end of file