commit 173a95b19f676fe93b52f7e9a5a3461b36da3ceb Author: 左程云 Date: Tue Apr 28 18:26:54 2020 +0800 first commit diff --git a/src/class01/Code01_SelectionSort.java b/src/class01/Code01_SelectionSort.java new file mode 100644 index 0000000..8bd4c27 --- /dev/null +++ b/src/class01/Code01_SelectionSort.java @@ -0,0 +1,116 @@ +package class01; + +import java.util.Arrays; + +public class Code01_SelectionSort { + + public static void selectionSort(int[] arr) { + if (arr == null || arr.length < 2) { + return; + } + // 0 ~ N-1 + // 1~n-1 + // 2 + for (int i = 0; i < arr.length - 1; i++) { // i ~ N-1 + // 最小值在哪个位置上 i~n-1 + int minIndex = i; + for (int j = i + 1; j < arr.length; j++) { // i ~ N-1 上找最小值的下标 + minIndex = arr[j] < arr[minIndex] ? j : minIndex; + } + swap(arr, i, minIndex); + } + } + + public static void swap(int[] arr, int i, int j) { + int tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + + // for test + public static void comparator(int[] arr) { + Arrays.sort(arr); + } + + // for test + public static int[] generateRandomArray(int maxSize, int maxValue) { + // Math.random() [0,1) + // Math.random() * N [0,N) + // (int)(Math.random() * N) [0, N-1] + int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; + for (int i = 0; i < arr.length; i++) { + // [-? , +?] + arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); + } + return arr; + } + + // for test + public static int[] copyArray(int[] arr) { + if (arr == null) { + return null; + } + int[] res = new int[arr.length]; + for (int i = 0; i < arr.length; i++) { + res[i] = arr[i]; + } + return res; + } + + // for test + public static boolean isEqual(int[] arr1, int[] arr2) { + if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { + return false; + } + if (arr1 == null && arr2 == null) { + return true; + } + if (arr1.length != arr2.length) { + return false; + } + for (int i = 0; i < arr1.length; i++) { + if (arr1[i] != arr2[i]) { + return false; + } + } + return true; + } + + // for test + public static void printArray(int[] arr) { + if (arr == null) { + return; + } + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + // for test + public static void main(String[] args) { + int testTime = 500000; + int maxSize = 100; + int maxValue = 100; + boolean succeed = true; + for (int i = 0; i < testTime; i++) { + int[] arr1 = generateRandomArray(maxSize, maxValue); + int[] arr2 = copyArray(arr1); + selectionSort(arr1); + comparator(arr2); + if (!isEqual(arr1, arr2)) { + succeed = false; + printArray(arr1); + printArray(arr2); + break; + } + } + System.out.println(succeed ? "Nice!" : "Fucking fucked!"); + + int[] arr = generateRandomArray(maxSize, maxValue); + printArray(arr); + selectionSort(arr); + printArray(arr); + } + +} diff --git a/src/class01/Code02_BubbleSort.java b/src/class01/Code02_BubbleSort.java new file mode 100644 index 0000000..14b6e47 --- /dev/null +++ b/src/class01/Code02_BubbleSort.java @@ -0,0 +1,110 @@ +package class01; + +import java.util.Arrays; + +public class Code02_BubbleSort { + + public static void bubbleSort(int[] arr) { + if (arr == null || arr.length < 2) { + return; + } + // 0 ~ N-1 + // 0 ~ N-2 + // 0 ~ N-3 + for (int e = arr.length - 1; e > 0; e--) { // 0 ~ e + for (int i = 0; i < e; i++) { + if (arr[i] > arr[i + 1]) { + swap(arr, i, i + 1); + } + } + } + } + + // 交换arr的i和j位置上的值 + public static void swap(int[] arr, int i, int j) { + arr[i] = arr[i] ^ arr[j]; + arr[j] = arr[i] ^ arr[j]; + arr[i] = arr[i] ^ arr[j]; + } + + // for test + public static void comparator(int[] arr) { + Arrays.sort(arr); + } + + // for test + public static int[] generateRandomArray(int maxSize, int maxValue) { + int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); + } + return arr; + } + + // for test + public static int[] copyArray(int[] arr) { + if (arr == null) { + return null; + } + int[] res = new int[arr.length]; + for (int i = 0; i < arr.length; i++) { + res[i] = arr[i]; + } + return res; + } + + // for test + public static boolean isEqual(int[] arr1, int[] arr2) { + if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { + return false; + } + if (arr1 == null && arr2 == null) { + return true; + } + if (arr1.length != arr2.length) { + return false; + } + for (int i = 0; i < arr1.length; i++) { + if (arr1[i] != arr2[i]) { + return false; + } + } + return true; + } + + // for test + public static void printArray(int[] arr) { + if (arr == null) { + return; + } + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + // for test + public static void main(String[] args) { + int testTime = 500000; + int maxSize = 100; + int maxValue = 100; + boolean succeed = true; + for (int i = 0; i < testTime; i++) { + int[] arr1 = generateRandomArray(maxSize, maxValue); + int[] arr2 = copyArray(arr1); + bubbleSort(arr1); + comparator(arr2); + if (!isEqual(arr1, arr2)) { + succeed = false; + break; + } + } + System.out.println(succeed ? "Nice!" : "Fucking fucked!"); + + int[] arr = generateRandomArray(maxSize, maxValue); + printArray(arr); + bubbleSort(arr); + printArray(arr); + } + +} diff --git a/src/class01/Code03_InsertionSort.java b/src/class01/Code03_InsertionSort.java new file mode 100644 index 0000000..79861c9 --- /dev/null +++ b/src/class01/Code03_InsertionSort.java @@ -0,0 +1,113 @@ +package class01; + +import java.util.Arrays; + +public class Code03_InsertionSort { + + public static void insertionSort(int[] arr) { + if (arr == null || arr.length < 2) { + return; + } + // 0~0 有序的 + // 0~i 想有序 + for (int i = 1; i < arr.length; i++) { // 0 ~ i 做到有序 + for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) { + swap(arr, j, j + 1); + } + } + } + + // i和j是一个位置的话,会出错 + public static void swap(int[] arr, int i, int j) { + arr[i] = arr[i] ^ arr[j]; + arr[j] = arr[i] ^ arr[j]; + arr[i] = arr[i] ^ arr[j]; + } + + // for test + public static void comparator(int[] arr) { + Arrays.sort(arr); + } + + // for test + public static int[] generateRandomArray(int maxSize, int maxValue) { + // Math.random() -> [0,1) 所有的小数,等概率返回一个 + // Math.random() * N -> [0,N) 所有小数,等概率返回一个 + // (int)(Math.random() * N) -> [0,N-1] 所有的整数,等概率返回一个 + int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; // 长度随机 + for (int i = 0; i < arr.length; i++) { + arr[i] = (int) ((maxValue + 1) * Math.random()) + - (int) (maxValue * Math.random()); + } + return arr; + } + + // for test + public static int[] copyArray(int[] arr) { + if (arr == null) { + return null; + } + int[] res = new int[arr.length]; + for (int i = 0; i < arr.length; i++) { + res[i] = arr[i]; + } + return res; + } + + // for test + public static boolean isEqual(int[] arr1, int[] arr2) { + if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { + return false; + } + if (arr1 == null && arr2 == null) { + return true; + } + if (arr1.length != arr2.length) { + return false; + } + for (int i = 0; i < arr1.length; i++) { + if (arr1[i] != arr2[i]) { + return false; + } + } + return true; + } + + // for test + public static void printArray(int[] arr) { + if (arr == null) { + return; + } + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + // for test + public static void main(String[] args) { + int testTime = 500000; + int maxSize = 100; // 随机数组的长度0~100 + int maxValue = 100;// 值:-100~100 + boolean succeed = true; + for (int i = 0; i < testTime; i++) { + int[] arr1 = generateRandomArray(maxSize, maxValue); + int[] arr2 = copyArray(arr1); + insertionSort(arr1); + comparator(arr2); + if (!isEqual(arr1, arr2)) { + // 打印arr1 + // 打印arr2 + succeed = false; + break; + } + } + System.out.println(succeed ? "Nice!" : "Fucking fucked!"); + + int[] arr = generateRandomArray(maxSize, maxValue); + printArray(arr); + insertionSort(arr); + printArray(arr); + } + +} diff --git a/src/class01/Code04_BSExist.java b/src/class01/Code04_BSExist.java new file mode 100644 index 0000000..9010182 --- /dev/null +++ b/src/class01/Code04_BSExist.java @@ -0,0 +1,30 @@ +package class01; + +public class Code04_BSExist { + + public static boolean exist(int[] sortedArr, int num) { + if (sortedArr == null || sortedArr.length == 0) { + return false; + } + int L = 0; + int R = sortedArr.length - 1; + int mid = 0; + // L..R + while (L < R) { + // mid = (L+R) / 2; + // L 10亿 R 18亿 + // mid = L + (R - L) / 2 + // N / 2 N >> 1 + mid = L + ((R - L) >> 1); // mid = (L + R) / 2 + if (sortedArr[mid] == num) { + return true; + } else if (sortedArr[mid] > num) { + R = mid - 1; + } else { + L = mid + 1; + } + } + return sortedArr[L] == num; + } + +} diff --git a/src/class01/Code05_BSNearLeft.java b/src/class01/Code05_BSNearLeft.java new file mode 100644 index 0000000..6737501 --- /dev/null +++ b/src/class01/Code05_BSNearLeft.java @@ -0,0 +1,75 @@ +package class01; + +import java.util.Arrays; + +public class Code05_BSNearLeft { + + // 在arr上,找满足>=value的最左位置 + public static int nearestIndex(int[] arr, int value) { + int L = 0; + int R = arr.length - 1; + int index = -1; // 记录最左的对号 + while (L <= R) { + int mid = L + ((R - L) >> 1); + if (arr[mid] >= value) { + index = mid; + R = mid - 1; + } else { + L = mid + 1; + } + } + return index; + } + + // for test + public static int test(int[] arr, int value) { + for (int i = 0; i < arr.length; i++) { + if (arr[i] >= value) { + return i; + } + } + return -1; + } + + // for test + public static int[] generateRandomArray(int maxSize, int maxValue) { + int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); + } + return arr; + } + + // for test + public static void printArray(int[] arr) { + if (arr == null) { + return; + } + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + public static void main(String[] args) { + int testTime = 500000; + int maxSize = 10; + int maxValue = 100; + boolean succeed = true; + for (int i = 0; i < testTime; i++) { + int[] arr = generateRandomArray(maxSize, maxValue); + Arrays.sort(arr); + int value = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); + if (test(arr, value) != nearestIndex(arr, value)) { + printArray(arr); + System.out.println(value); + System.out.println(test(arr, value)); + System.out.println(nearestIndex(arr, value)); + succeed = false; + break; + } + } + System.out.println(succeed ? "Nice!" : "Fucking fucked!"); + } + +} diff --git a/src/class01/Code05_BSNearRight.java b/src/class01/Code05_BSNearRight.java new file mode 100644 index 0000000..f3b6f25 --- /dev/null +++ b/src/class01/Code05_BSNearRight.java @@ -0,0 +1,75 @@ +package class01; + +import java.util.Arrays; + +public class Code05_BSNearRight { + + // 在arr上,找满足<=value的最右位置 + public static int nearestIndex(int[] arr, int value) { + int L = 0; + int R = arr.length - 1; + int index = -1; // 记录最右的对号 + while (L <= R) { + int mid = L + ((R - L) >> 1); + if (arr[mid] <= value) { + index = mid; + L = mid + 1; + } else { + R = mid - 1; + } + } + return index; + } + + // for test + public static int test(int[] arr, int value) { + for (int i = arr.length - 1; i >= 0; i--) { + if (arr[i] <= value) { + return i; + } + } + return -1; + } + + // for test + public static int[] generateRandomArray(int maxSize, int maxValue) { + int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); + } + return arr; + } + + // for test + public static void printArray(int[] arr) { + if (arr == null) { + return; + } + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + public static void main(String[] args) { + int testTime = 500000; + int maxSize = 10; + int maxValue = 100; + boolean succeed = true; + for (int i = 0; i < testTime; i++) { + int[] arr = generateRandomArray(maxSize, maxValue); + Arrays.sort(arr); + int value = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); + if (test(arr, value) != nearestIndex(arr, value)) { + printArray(arr); + System.out.println(value); + System.out.println(test(arr, value)); + System.out.println(nearestIndex(arr, value)); + succeed = false; + break; + } + } + System.out.println(succeed ? "Nice!" : "Fucking fucked!"); + } + +} diff --git a/src/class01/Code06_BSAwesome.java b/src/class01/Code06_BSAwesome.java new file mode 100644 index 0000000..bdca00d --- /dev/null +++ b/src/class01/Code06_BSAwesome.java @@ -0,0 +1,31 @@ +package class01; + +public class Code06_BSAwesome { + + public static int getLessIndex(int[] arr) { + if (arr == null || arr.length == 0) { + return -1; // no exist + } + if (arr.length == 1 || arr[0] < arr[1]) { + return 0; + } + if (arr[arr.length - 1] < arr[arr.length - 2]) { + return arr.length - 1; + } + int left = 1; + int right = arr.length - 2; + int mid = 0; + while (left < right) { + mid = (left + right) / 2; + if (arr[mid] > arr[mid - 1]) { + right = mid - 1; + } else if (arr[mid] > arr[mid + 1]) { + left = mid + 1; + } else { + return mid; + } + } + return left; + } + +} diff --git a/src/class01/Code07_EvenTimesOddTimes.java b/src/class01/Code07_EvenTimesOddTimes.java new file mode 100644 index 0000000..d9e9327 --- /dev/null +++ b/src/class01/Code07_EvenTimesOddTimes.java @@ -0,0 +1,81 @@ +package class01; + +public class Code07_EvenTimesOddTimes { + + // arr中,只有一种数,出现奇数次 + public static void printOddTimesNum1(int[] arr) { + int eor = 0; + for (int i = 0; i < arr.length; i++) { + eor ^= arr[i]; + } + System.out.println(eor); + } + + // arr中,有两种数,出现奇数次 + public static void printOddTimesNum2(int[] arr) { + int eor = 0; + for (int i = 0; i < arr.length; i++) { + eor ^= arr[i]; + } + // eor = a ^ b + // eor != 0 + // eor必然有一个位置上是1 + // 0110010000 + // 0000010000 + int rightOne = eor & (~eor + 1); // 提取出最右的1 + int onlyOne = 0; // eor' + for (int i = 0 ; i < arr.length;i++) { + // arr[1] = 111100011110000 + // rightOne= 000000000010000 + if ((arr[i] & rightOne) != 0) { + onlyOne ^= arr[i]; + } + } + System.out.println(onlyOne + " " + (eor ^ onlyOne)); + } + + + public static int bit1counts(int N) { + int count = 0; + + // 011011010000 + // 000000010000 1 + + // 011011000000 + // + + + + while(N != 0) { + int rightOne = N & ((~N) + 1); + count++; + N ^= rightOne; + // N -= rightOne + } + + + return count; + + } + + + public static void main(String[] args) { + int a = 5; + int b = 7; + + a = a ^ b; + b = a ^ b; + a = a ^ b; + + System.out.println(a); + System.out.println(b); + + int[] arr1 = { 3, 3, 2, 3, 1, 1, 1, 3, 1, 1, 1 }; + printOddTimesNum1(arr1); + + int[] arr2 = { 4, 3, 4, 2, 2, 2, 4, 1, 1, 1, 3, 3, 1, 1, 1, 4, 2, 2 }; + printOddTimesNum2(arr2); + + } + +} diff --git a/src/class01/Test.java b/src/class01/Test.java new file mode 100644 index 0000000..af227e6 --- /dev/null +++ b/src/class01/Test.java @@ -0,0 +1,45 @@ +package class01; + +public class Test { + + public static void main(String[] args) { + int a = 6; + int b = 6; + + + a = a ^ b; + b = a ^ b; + a = a ^ b; + + + System.out.println(a); + System.out.println(b); + + + + + int[] arr = {3,1,100}; + + System.out.println(arr[0]); + System.out.println(arr[2]); + + swap(arr, 0, 0); + + System.out.println(arr[0]); + System.out.println(arr[2]); + + + + } + + + public static void swap (int[] arr, int i, int j) { + // arr[0] = arr[0] ^ arr[0]; + arr[i] = arr[i] ^ arr[j]; + arr[j] = arr[i] ^ arr[j]; + arr[i] = arr[i] ^ arr[j]; + } + + + +} diff --git a/src/class02/Code01_ReverseList.java b/src/class02/Code01_ReverseList.java new file mode 100644 index 0000000..d44df68 --- /dev/null +++ b/src/class02/Code01_ReverseList.java @@ -0,0 +1,198 @@ +package class02; + +import java.util.ArrayList; + +public class Code01_ReverseList { + + public static class Node { + public int value; + public Node next; + + public Node(int data) { + value = data; + } + } + + public static class DoubleNode { + public int value; + public DoubleNode last; + public DoubleNode next; + + public DoubleNode(int data) { + value = data; + } + } + + public static Node reverseLinkedList(Node head) { + Node pre = null; + Node next = null; + while (head != null) { + next = head.next; + head.next = pre; + pre = head; + head = next; + } + return pre; + } + + public static DoubleNode reverseDoubleList(DoubleNode head) { + DoubleNode pre = null; + DoubleNode next = null; + while (head != null) { + next = head.next; + head.next = pre; + head.last = next; + pre = head; + head = next; + } + return pre; + } + + public static Node testReverseLinkedList(Node head) { + if (head == null) { + return null; + } + ArrayList list = new ArrayList<>(); + while (head != null) { + list.add(head); + head = head.next; + } + list.get(0).next = null; + int N = list.size(); + for (int i = 1; i < N; i++) { + list.get(i).next = list.get(i - 1); + } + return list.get(N - 1); + } + + public static DoubleNode testReverseDoubleList(DoubleNode head) { + if (head == null) { + return null; + } + ArrayList list = new ArrayList<>(); + while (head != null) { + list.add(head); + head = head.next; + } + list.get(0).next = null; + DoubleNode pre = list.get(0); + int N = list.size(); + for (int i = 1; i < N; i++) { + DoubleNode cur = list.get(i); + cur.last = null; + cur.next = pre; + pre.last = cur; + pre = cur; + } + return list.get(N - 1); + } + + public static Node generateRandomLinkedList(int len, int value) { + int size = (int) (Math.random() * (len + 1)); + if (size == 0) { + return null; + } + size--; + Node head = new Node((int) (Math.random() * (value + 1))); + Node pre = head; + while (size != 0) { + Node cur = new Node((int) (Math.random() * (value + 1))); + pre.next = cur; + pre = cur; + size--; + } + return head; + } + + public static DoubleNode generateRandomDoubleList(int len, int value) { + int size = (int) (Math.random() * (len + 1)); + if (size == 0) { + return null; + } + size--; + DoubleNode head = new DoubleNode((int) (Math.random() * (value + 1))); + DoubleNode pre = head; + while (size != 0) { + DoubleNode cur = new DoubleNode((int) (Math.random() * (value + 1))); + pre.next = cur; + cur.last = pre; + pre = cur; + size--; + } + return head; + } + + // 要求无环,有环别用这个函数 + public static boolean checkLinkedListEqual(Node head1, Node head2) { + while (head1 != null && head2 != null) { + if (head1.value != head2.value) { + return false; + } + head1 = head1.next; + head2 = head2.next; + } + return head1 == null && head2 == null; + } + + // 要求无环,有环别用这个函数 + public static boolean checkDoubleListEqual(DoubleNode head1, DoubleNode head2) { + boolean null1 = head1 == null; + boolean null2 = head2 == null; + if (null1 && null2) { + return true; + } + if (null1 ^ null2) { + return false; + } + if (head1.last != null || head2.last != null) { + return false; + } + DoubleNode end1 = null; + DoubleNode end2 = null; + while (head1 != null && head2 != null) { + if (head1.value != head2.value) { + return false; + } + end1 = head1; + end2 = head2; + head1 = head1.next; + head2 = head2.next; + } + if (head1 != null || head2 != null) { + return false; + } + while (end1 != null && end2 != null) { + if (end1.value != end2.value) { + return false; + } + end1 = end1.last; + end2 = end2.last; + } + return end1 == null && end2 == null; + } + + public static void main(String[] args) { + int len = 50; + int value = 100; + int testTime = 100000; + for (int i = 0; i < testTime; i++) { + Node node1 = generateRandomLinkedList(len, value); + Node reverse1 = reverseLinkedList(node1); + Node back1 = testReverseLinkedList(reverse1); + if (!checkLinkedListEqual(node1, back1)) { + System.out.println("oops!"); + break; + } + DoubleNode node2 = generateRandomDoubleList(len, value); + DoubleNode reverse2 = reverseDoubleList(node2); + DoubleNode back2 = testReverseDoubleList(reverse2); + if (!checkDoubleListEqual(node2, back2)) { + System.out.println("oops!"); + break; + } + } + System.out.println("finish!"); + + } + +} diff --git a/src/class02/Code02_DeleteGivenValue.java b/src/class02/Code02_DeleteGivenValue.java new file mode 100644 index 0000000..45f3008 --- /dev/null +++ b/src/class02/Code02_DeleteGivenValue.java @@ -0,0 +1,36 @@ +package class02; + +public class Code02_DeleteGivenValue { + + public static class Node { + public int value; + public Node next; + + public Node(int data) { + this.value = data; + } + } + + public static Node removeValue(Node head, int num) { + while (head != null) { + if (head.value != num) { + break; + } + head = head.next; + } + // head来到 第一个不需要删的位置 + Node pre = head; + Node cur = head; + // + while (cur != null) { + if (cur.value == num) { + pre.next = cur.next; + } else { + pre = cur; + } + cur = cur.next; + } + return head; + } + +} diff --git a/src/class02/Code03_DoubleEndsQueueToStackAndQueue.java b/src/class02/Code03_DoubleEndsQueueToStackAndQueue.java new file mode 100644 index 0000000..989096a --- /dev/null +++ b/src/class02/Code03_DoubleEndsQueueToStackAndQueue.java @@ -0,0 +1,183 @@ +package class02; + +import java.util.LinkedList; +import java.util.Queue; +import java.util.Stack; + +public class Code03_DoubleEndsQueueToStackAndQueue { + + public static class Node { + public T value; + public Node last; + public Node next; + + public Node(T data) { + value = data; + } + } + + public static class DoubleEndsQueue { + public Node head; + public Node tail; + + public void addFromHead(T value) { + Node cur = new Node(value); + if (head == null) { + head = cur; + tail = cur; + } else { + cur.next = head; + head.last = cur; + head = cur; + } + } + + public void addFromBottom(T value) { + Node cur = new Node(value); + if (head == null) { + head = cur; + tail = cur; + } else { + cur.last = tail; + tail.next = cur; + tail = cur; + } + } + + public T popFromHead() { + if (head == null) { + return null; + } + Node cur = head; + if (head == tail) { + head = null; + tail = null; + } else { + head = head.next; + cur.next = null; + head.last = null; + } + return cur.value; + } + + public T popFromBottom() { + if (head == null) { + return null; + } + Node cur = tail; + if (head == tail) { + head = null; + tail = null; + } else { + tail = tail.last; + tail.next = null; + cur.last = null; + } + return cur.value; + } + + public boolean isEmpty() { + return head == null; + } + + } + + public static class MyStack { + private DoubleEndsQueue queue; + + public MyStack() { + queue = new DoubleEndsQueue(); + } + + public void push(T value) { + queue.addFromHead(value); + } + + public T pop() { + return queue.popFromHead(); + } + + public boolean isEmpty() { + return queue.isEmpty(); + } + + } + + public static class MyQueue { + private DoubleEndsQueue queue; + + public MyQueue() { + queue = new DoubleEndsQueue(); + } + + public void push(T value) { + queue.addFromHead(value); + } + + public T poll() { + return queue.popFromBottom(); + } + + public boolean isEmpty() { + return queue.isEmpty(); + } + + } + + public static boolean isEqual(Integer o1, Integer o2) { + if (o1 == null && o2 != null) { + return false; + } + if (o1 != null && o2 == null) { + return false; + } + if (o1 == null && o2 == null) { + return true; + } + return o1.equals(o2); + } + + public static void main(String[] args) { + int oneTestDataNum = 100; + int value = 10000; + int testTimes = 100000; + for (int i = 0; i < testTimes; i++) { + MyStack myStack = new MyStack<>(); + MyQueue myQueue = new MyQueue<>(); + Stack stack = new Stack<>(); + Queue queue = new LinkedList<>(); + for (int j = 0; j < oneTestDataNum; j++) { + int nums = (int) (Math.random() * value); + if (stack.isEmpty()) { + myStack.push(nums); + stack.push(nums); + } else { + if (Math.random() < 0.5) { + myStack.push(nums); + stack.push(nums); + } else { + if (!isEqual(myStack.pop(), stack.pop())) { + System.out.println("oops!"); + } + } + } + int numq = (int) (Math.random() * value); + if (stack.isEmpty()) { + myQueue.push(numq); + queue.offer(numq); + } else { + if (Math.random() < 0.5) { + myQueue.push(numq); + queue.offer(numq); + } else { + if (!isEqual(myQueue.poll(), queue.poll())) { + System.out.println("oops!"); + } + } + } + } + } + System.out.println("finish!"); + } + +} diff --git a/src/class02/Code04_RingArray.java b/src/class02/Code04_RingArray.java new file mode 100644 index 0000000..b28c2b7 --- /dev/null +++ b/src/class02/Code04_RingArray.java @@ -0,0 +1,50 @@ +package class02; + +public class Code04_RingArray { + + public static class MyQueue { + private int[] arr; + private int pushi; + private int polli; + private int size; + private final int limit; + + public MyQueue(int limit) { + arr = new int[limit]; + pushi = 0; + polli = 0; + size = 0; + this.limit = limit; + } + + public void push(int value) { + if (size == limit) { + throw new RuntimeException("栈满了,不能再加了"); + } + size++; + arr[pushi] = value; + pushi = nextIndex(pushi); + } + + public int pop() { + if (size == 0) { + throw new RuntimeException("栈空了,不能再拿了"); + } + size--; + int ans = arr[polli]; + polli = nextIndex(polli); + return ans; + } + + public boolean isEmpty() { + return size == 0; + } + + // 如果现在的下标是i,返回下一个位置 + private int nextIndex(int i) { + return i < limit - 1 ? i + 1 : 0; + } + + } + +} diff --git a/src/class02/Code05_GetMinStack.java b/src/class02/Code05_GetMinStack.java new file mode 100644 index 0000000..0173d94 --- /dev/null +++ b/src/class02/Code05_GetMinStack.java @@ -0,0 +1,105 @@ +package class02; + +import java.util.Stack; + +public class Code05_GetMinStack { + + public static class MyStack1 { + private Stack stackData; + private Stack stackMin; + + public MyStack1() { + this.stackData = new Stack(); + this.stackMin = new Stack(); + } + + public void push(int newNum) { + if (this.stackMin.isEmpty()) { + this.stackMin.push(newNum); + } else if (newNum <= this.getmin()) { + this.stackMin.push(newNum); + } + this.stackData.push(newNum); + } + + public int pop() { + if (this.stackData.isEmpty()) { + throw new RuntimeException("Your stack is empty."); + } + int value = this.stackData.pop(); + if (value == this.getmin()) { + this.stackMin.pop(); + } + return value; + } + + public int getmin() { + if (this.stackMin.isEmpty()) { + throw new RuntimeException("Your stack is empty."); + } + return this.stackMin.peek(); + } + } + + public static class MyStack2 { + private Stack stackData; + private Stack stackMin; + + public MyStack2() { + this.stackData = new Stack(); + this.stackMin = new Stack(); + } + + public void push(int newNum) { + if (this.stackMin.isEmpty()) { + this.stackMin.push(newNum); + } else if (newNum < this.getmin()) { + this.stackMin.push(newNum); + } else { + int newMin = this.stackMin.peek(); + this.stackMin.push(newMin); + } + this.stackData.push(newNum); + } + + public int pop() { + if (this.stackData.isEmpty()) { + throw new RuntimeException("Your stack is empty."); + } + this.stackMin.pop(); + return this.stackData.pop(); + } + + public int getmin() { + if (this.stackMin.isEmpty()) { + throw new RuntimeException("Your stack is empty."); + } + return this.stackMin.peek(); + } + } + + public static void main(String[] args) { + MyStack1 stack1 = new MyStack1(); + stack1.push(3); + System.out.println(stack1.getmin()); + stack1.push(4); + System.out.println(stack1.getmin()); + stack1.push(1); + System.out.println(stack1.getmin()); + System.out.println(stack1.pop()); + System.out.println(stack1.getmin()); + + System.out.println("============="); + + MyStack1 stack2 = new MyStack1(); + stack2.push(3); + System.out.println(stack2.getmin()); + stack2.push(4); + System.out.println(stack2.getmin()); + stack2.push(1); + System.out.println(stack2.getmin()); + System.out.println(stack2.pop()); + System.out.println(stack2.getmin()); + } + +} diff --git a/src/class02/Code06_TwoStacksImplementQueue.java b/src/class02/Code06_TwoStacksImplementQueue.java new file mode 100644 index 0000000..9144770 --- /dev/null +++ b/src/class02/Code06_TwoStacksImplementQueue.java @@ -0,0 +1,60 @@ +package class02; + +import java.util.Stack; + +public class Code06_TwoStacksImplementQueue { + + public static class TwoStacksQueue { + public Stack stackPush; + public Stack stackPop; + + public TwoStacksQueue() { + stackPush = new Stack(); + stackPop = new Stack(); + } + + // push栈向pop栈倒入数据 + private void pushToPop() { + if (stackPop.empty()) { + while (!stackPush.empty()) { + stackPop.push(stackPush.pop()); + } + } + } + + public void add(int pushInt) { + stackPush.push(pushInt); + pushToPop(); + } + + public int poll() { + if (stackPop.empty() && stackPush.empty()) { + throw new RuntimeException("Queue is empty!"); + } + pushToPop(); + return stackPop.pop(); + } + + public int peek() { + if (stackPop.empty() && stackPush.empty()) { + throw new RuntimeException("Queue is empty!"); + } + pushToPop(); + return stackPop.peek(); + } + } + + public static void main(String[] args) { + TwoStacksQueue test = new TwoStacksQueue(); + test.add(1); + test.add(2); + test.add(3); + System.out.println(test.peek()); + System.out.println(test.poll()); + System.out.println(test.peek()); + System.out.println(test.poll()); + System.out.println(test.peek()); + System.out.println(test.poll()); + } + +} diff --git a/src/class02/Code07_TwoQueueImplementStack.java b/src/class02/Code07_TwoQueueImplementStack.java new file mode 100644 index 0000000..49a87c1 --- /dev/null +++ b/src/class02/Code07_TwoQueueImplementStack.java @@ -0,0 +1,90 @@ +package class02; + +import java.util.LinkedList; +import java.util.Queue; +import java.util.Stack; + +public class Code07_TwoQueueImplementStack { + + public static class TwoQueueStack { + public Queue queue; + public Queue help; + + public TwoQueueStack() { + queue = new LinkedList<>(); + help = new LinkedList<>(); + } + + public void push(T value) { + queue.offer(value); + } + + public T poll() { + while (queue.size() > 1) { + help.offer(queue.poll()); + } + T ans = queue.poll(); + Queue tmp = queue; + queue = help; + help = tmp; + return ans; + } + + public T peek() { + while (queue.size() > 1) { + help.offer(queue.poll()); + } + T ans = queue.poll(); + help.offer(ans); + Queue tmp = queue; + queue = help; + help = tmp; + return ans; + } + + public boolean isEmpty() { + return queue.isEmpty(); + } + + } + + public static void main(String[] args) { + System.out.println("test begin"); + TwoQueueStack myStack = new TwoQueueStack<>(); + Stack test = new Stack<>(); + int testTime = 1000000; + int max = 1000000; + for (int i = 0; i < testTime; i++) { + if (myStack.isEmpty()) { + if (!test.isEmpty()) { + System.out.println("Oops"); + } + int num = (int) (Math.random() * max); + myStack.push(num); + test.push(num); + } else { + if (Math.random() < 0.25) { + int num = (int) (Math.random() * max); + myStack.push(num); + test.push(num); + } else if (Math.random() < 0.5) { + if (!myStack.peek().equals(test.peek())) { + System.out.println("Oops"); + } + } else if (Math.random() < 0.75) { + if (!myStack.poll().equals(test.pop())) { + System.out.println("Oops"); + } + } else { + if (myStack.isEmpty() != test.isEmpty()) { + System.out.println("Oops"); + } + } + } + } + + System.out.println("test finish!"); + + } + +} diff --git a/src/class02/Code08_GetMax.java b/src/class02/Code08_GetMax.java new file mode 100644 index 0000000..cd7141f --- /dev/null +++ b/src/class02/Code08_GetMax.java @@ -0,0 +1,21 @@ +package class02; + +public class Code08_GetMax { + + // 求arr中的最大值 + public static int getMax(int[] arr) { + return process(arr, 0, arr.length - 1); + } + + // arr[L..R]范围上求最大值 L ... R N + public static int process(int[] arr, int L, int R) { + if (L == R) { // arr[L..R]范围上只有一个数,直接返回,base case + return arr[L]; + } + int mid = L + ((R - L) >> 1); // 中点 1 + int leftMax = process(arr, L, mid); + int rightMax = process(arr, mid + 1, R); + return Math.max(leftMax, rightMax); + } + +} diff --git a/src/class02/HashMapAndSortedMap.java b/src/class02/HashMapAndSortedMap.java new file mode 100644 index 0000000..717b81b --- /dev/null +++ b/src/class02/HashMapAndSortedMap.java @@ -0,0 +1,112 @@ +package class02; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.TreeMap; + +public class HashMapAndSortedMap { + + + public static class Node{ + public int value; + public Node(int v) { + value = v; + } + } + + public static void main(String[] args) { + // UnSortedMap + HashMap map = new HashMap<>(); + map.put(1000000, "我是1000000"); + map.put(2, "我是2"); + map.put(3, "我是3"); + map.put(4, "我是4"); + map.put(5, "我是5"); + map.put(6, "我是6"); + map.put(1000000, "我是1000001"); + + System.out.println(map.containsKey(1)); + System.out.println(map.containsKey(10)); + + System.out.println(map.get(4)); + System.out.println(map.get(10)); + + map.put(4, "他是4"); + System.out.println(map.get(4)); + + map.remove(4); + System.out.println(map.get(4)); + + + + // key + HashSet set = new HashSet<>(); + set.add("abc"); + set.contains("abc"); + set.remove("abc"); + + // 哈希表,增、删、改、查,在使用时,O(1) + + + System.out.println("====================="); + + + int a = 100000; + int b = 100000; + System.out.println(a == b); + + Integer c = 100000; + Integer d = 100000; + System.out.println(c.equals(d)); + + Integer e = 127; // - 128 ~ 127 + Integer f = 127; + System.out.println(e == f); + + + + HashMap map2 = new HashMap<>(); + Node node1 = new Node(1); + Node node2 = node1; + map2.put(node1, "我是node1"); + map2.put(node2, "我是node1"); + System.out.println(map2.size()); + + System.out.println("======================"); + + TreeMap treeMap = new TreeMap<>(); + + treeMap.put(3, "我是3"); + treeMap.put(4, "我是4"); + treeMap.put(8, "我是8"); + treeMap.put(5, "我是5"); + treeMap.put(7, "我是7"); + treeMap.put(1, "我是1"); + treeMap.put(2, "我是2"); + + System.out.println(treeMap.containsKey(1)); + System.out.println(treeMap.containsKey(10)); + + System.out.println(treeMap.get(4)); + System.out.println(treeMap.get(10)); + + treeMap.put(4, "他是4"); + System.out.println(treeMap.get(4)); + + treeMap.remove(4); + System.out.println(treeMap.get(4)); + + System.out.println(treeMap.firstKey()); + System.out.println(treeMap.lastKey()); + // <= 4 + System.out.println(treeMap.floorKey(4)); + // >= 4 + System.out.println(treeMap.ceilingKey(4)); + + // O(logN) + + } + + + +} diff --git a/src/class03/Code01_MergeSort.java b/src/class03/Code01_MergeSort.java new file mode 100644 index 0000000..50c1664 --- /dev/null +++ b/src/class03/Code01_MergeSort.java @@ -0,0 +1,147 @@ +package class03; + +public class Code01_MergeSort { + + + + // 递归方法实现 + public static void mergeSort1(int[] arr) { + if (arr == null || arr.length < 2) { + return; + } + process(arr, 0, arr.length - 1); + } + + // arr[L...R]范围上,变成有序的 + // L...R N T(N) = 2*T(N/2) + O(N) -> + public static void process(int[] arr, int L, int R) { + if (L == R) { // base case + return; + } + int mid = L + ((R - L) >> 1); + process(arr, L, mid); + process(arr, mid + 1, R); + merge(arr, L, mid, R); + } + + public static void merge(int[] arr, int L, int M, int R) { + int[] help = new int[R - L + 1]; + int i = 0; + int p1 = L; + int p2 = M + 1; + while (p1 <= M && p2 <= R) { + help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++]; + } + // 要么p1越界了,要么p2越界了 + while (p1 <= M) { + help[i++] = arr[p1++]; + } + while (p2 <= R) { + help[i++] = arr[p2++]; + } + for (i = 0; i < help.length; i++) { + arr[L + i] = help[i]; + } + } + + // 非递归方法实现 + public static void mergeSort2(int[] arr) { + if (arr == null || arr.length < 2) { + return; + } + int N = arr.length; + int mergeSize = 1;// 当前有序的,左组长度 + while (mergeSize < N) { // log N + int L = 0; + // 0.... + while (L < N) { + // L...M 左组(mergeSize) + int M = L + mergeSize - 1; + if (M >= N) { + break; + } + // L...M M+1...R(mergeSize) + int R = Math.min(M + mergeSize, N - 1); + merge(arr, L, M, R); + L = R + 1; + } + if (mergeSize > N / 2) { + break; + } + mergeSize <<= 1; + } + } + + // for test + public static int[] generateRandomArray(int maxSize, int maxValue) { + int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); + } + return arr; + } + + // for test + public static int[] copyArray(int[] arr) { + if (arr == null) { + return null; + } + int[] res = new int[arr.length]; + for (int i = 0; i < arr.length; i++) { + res[i] = arr[i]; + } + return res; + } + + // for test + public static boolean isEqual(int[] arr1, int[] arr2) { + if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { + return false; + } + if (arr1 == null && arr2 == null) { + return true; + } + if (arr1.length != arr2.length) { + return false; + } + for (int i = 0; i < arr1.length; i++) { + if (arr1[i] != arr2[i]) { + return false; + } + } + return true; + } + + // for test + public static void printArray(int[] arr) { + if (arr == null) { + return; + } + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + // for test + public static void main(String[] args) { + int testTime = 500000; + int maxSize = 100; + int maxValue = 100; + boolean succeed = true; + for (int i = 0; i < testTime; i++) { + int[] arr1 = generateRandomArray(maxSize, maxValue); + int[] arr2 = copyArray(arr1); + mergeSort1(arr1); + mergeSort2(arr2); + if (!isEqual(arr1, arr2)) { + succeed = false; + printArray(arr1); + printArray(arr2); + break; + } + } + System.out.println(succeed ? "Nice!" : "Oops!"); + } + +} diff --git a/src/class03/Code02_SmallSum.java b/src/class03/Code02_SmallSum.java new file mode 100644 index 0000000..bddae7d --- /dev/null +++ b/src/class03/Code02_SmallSum.java @@ -0,0 +1,137 @@ +package class03; + +public class Code02_SmallSum { + + public static int smallSum(int[] arr) { + if (arr == null || arr.length < 2) { + return 0; + } + return process(arr, 0, arr.length - 1); + } + + // arr[L..R]既要排好序,也要求小和返回 + // 所有merge时,产生的小和,累加 + // 左 排序 merge + // 右 排序 merge + // merge + public static int process(int[] arr, int l, int r) { + if (l == r) { + return 0; + } + // l < r + int mid = l + ((r - l) >> 1); + return + process(arr, l, mid) + + + process(arr, mid + 1, r) + + + merge(arr, l, mid, r); + } + + public static int merge(int[] arr, int L, int m, int r) { + int[] help = new int[r - L + 1]; + int i = 0; + int p1 = L; + int p2 = m + 1; + int res = 0; + while (p1 <= m && p2 <= r) { + res += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0; + help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++]; + } + while (p1 <= m) { + help[i++] = arr[p1++]; + } + while (p2 <= r) { + help[i++] = arr[p2++]; + } + for (i = 0; i < help.length; i++) { + arr[L + i] = help[i]; + } + return res; + } + + // for test + public static int comparator(int[] arr) { + if (arr == null || arr.length < 2) { + return 0; + } + int res = 0; + for (int i = 1; i < arr.length; i++) { + for (int j = 0; j < i; j++) { + res += arr[j] < arr[i] ? arr[j] : 0; + } + } + return res; + } + + // for test + public static int[] generateRandomArray(int maxSize, int maxValue) { + int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); + } + return arr; + } + + // for test + public static int[] copyArray(int[] arr) { + if (arr == null) { + return null; + } + int[] res = new int[arr.length]; + for (int i = 0; i < arr.length; i++) { + res[i] = arr[i]; + } + return res; + } + + // for test + public static boolean isEqual(int[] arr1, int[] arr2) { + if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { + return false; + } + if (arr1 == null && arr2 == null) { + return true; + } + if (arr1.length != arr2.length) { + return false; + } + for (int i = 0; i < arr1.length; i++) { + if (arr1[i] != arr2[i]) { + return false; + } + } + return true; + } + + // for test + public static void printArray(int[] arr) { + if (arr == null) { + return; + } + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + // for test + public static void main(String[] args) { + int testTime = 500000; + int maxSize = 100; + int maxValue = 100; + boolean succeed = true; + for (int i = 0; i < testTime; i++) { + int[] arr1 = generateRandomArray(maxSize, maxValue); + int[] arr2 = copyArray(arr1); + if (smallSum(arr1) != comparator(arr2)) { + succeed = false; + printArray(arr1); + printArray(arr2); + break; + } + } + System.out.println(succeed ? "Nice!" : "Fucking fucked!"); + } + +} diff --git a/src/class03/Code03_PartitionAndQuickSort.java b/src/class03/Code03_PartitionAndQuickSort.java new file mode 100644 index 0000000..ae8fa78 --- /dev/null +++ b/src/class03/Code03_PartitionAndQuickSort.java @@ -0,0 +1,178 @@ +package class03; + +public class Code03_PartitionAndQuickSort { + + public static void swap(int[] arr, int i, int j) { + int tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + + public static int partition(int[] arr, int L, int R) { + if (L > R) { + return -1; + } + if (L == R) { + return L; + } + int lessEqual = L - 1; + int index = L; + while (index < R) { + if (arr[index] <= arr[R]) { + swap(arr, index, ++lessEqual); + } + index++; + } + swap(arr, ++lessEqual, R); + return lessEqual; + } + + // arr[L...R] 玩荷兰国旗问题的划分,以arr[R]做划分值 + // arr[R] + public static int[] netherlandsFlag(int[] arr, int L, int R) { + if (L > R) { + return new int[] { -1, -1 }; + } + if (L == R) { + return new int[] { L, R }; + } + int less = L - 1; // < 区 右边界 + int more = R; // > 区 左边界 + int index = L; + while (index < more) { + if (arr[index] == arr[R]) { + index++; + } else if (arr[index] < arr[R]) { + swap(arr, index++, ++less); + } else { // > + swap(arr, index, --more); + } + } + swap(arr, more, R); + return new int[] { less + 1, more }; + } + + public static void quickSort1(int[] arr) { + if (arr == null || arr.length < 2) { + return; + } + process1(arr, 0, arr.length - 1); + } + + public static void process1(int[] arr, int L, int R) { + if (L >= R) { + return; + } + // L..R partition arr[R] [ <=arr[R] arr[R] >arr[R] ] + int M = partition(arr, L, R); + process1(arr, L, M - 1); + process1(arr, M + 1, R); + } + + public static void quickSort2(int[] arr) { + if (arr == null || arr.length < 2) { + return; + } + process2(arr, 0, arr.length - 1); + } + + public static void process2(int[] arr, int L, int R) { + if (L >= R) { + return; + } + int[] equalArea = netherlandsFlag(arr, L, R); + process2(arr, L, equalArea[0] - 1); + process2(arr, equalArea[1] + 1, R); + } + + public static void quickSort3(int[] arr) { + if (arr == null || arr.length < 2) { + return; + } + process3(arr, 0, arr.length - 1); + } + + public static void process3(int[] arr, int L, int R) { + if (L >= R) { + return; + } + swap(arr, L + (int) (Math.random() * (R - L + 1)), R); + int[] equalArea = netherlandsFlag(arr, L, R); + process3(arr, L, equalArea[0] - 1); + process3(arr, equalArea[1] + 1, R); + } + + // for test + public static int[] generateRandomArray(int maxSize, int maxValue) { + int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); + } + return arr; + } + + // for test + public static int[] copyArray(int[] arr) { + if (arr == null) { + return null; + } + int[] res = new int[arr.length]; + for (int i = 0; i < arr.length; i++) { + res[i] = arr[i]; + } + return res; + } + + // for test + public static boolean isEqual(int[] arr1, int[] arr2) { + if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { + return false; + } + if (arr1 == null && arr2 == null) { + return true; + } + if (arr1.length != arr2.length) { + return false; + } + for (int i = 0; i < arr1.length; i++) { + if (arr1[i] != arr2[i]) { + return false; + } + } + return true; + } + + // for test + public static void printArray(int[] arr) { + if (arr == null) { + return; + } + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + // for test + public static void main(String[] args) { + int testTime = 500000; + int maxSize = 100; + int maxValue = 100; + boolean succeed = true; + for (int i = 0; i < testTime; i++) { + int[] arr1 = generateRandomArray(maxSize, maxValue); + int[] arr2 = copyArray(arr1); + int[] arr3 = copyArray(arr1); + quickSort1(arr1); + quickSort2(arr2); + quickSort3(arr3); + if (!isEqual(arr1, arr2) || !isEqual(arr2, arr3)) { + succeed = false; + break; + } + } + System.out.println(succeed ? "Nice!" : "Oops!"); + + } + +} diff --git a/src/class04/Code01_Comparator.java b/src/class04/Code01_Comparator.java new file mode 100644 index 0000000..09c7035 --- /dev/null +++ b/src/class04/Code01_Comparator.java @@ -0,0 +1,213 @@ +package class04; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.PriorityQueue; +import java.util.TreeSet; + +public class Code01_Comparator { + + public static class Student { + public String name; + public int id; + public int age; + + public Student(String name, int id, int age) { + this.name = name; + this.id = id; + this.age = age; + } + } + + public static class IdAscendingComparator + + implements Comparator { + + // 返回负数的时候,第一个参数排在前面 + // 返回正数的时候,第二个参数排在前面 + // 返回0的时候,谁在前面无所谓 + @Override + public int compare(Student o1, Student o2) { + return o1.id - o2.id; + } + + } + + public static class IdDescendingComparator implements Comparator { + + @Override + public int compare(Student o1, Student o2) { + return o2.id - o1.id; + } + + } + + public static class AgeAscendingComparator implements Comparator { + + @Override + public int compare(Student o1, Student o2) { + return o1.age - o2.age; + } + + } + + public static class AgeDescendingComparator implements Comparator { + + @Override + public int compare(Student o1, Student o2) { + return o2.age - o1.age; + } + + } + + + public static class AgeShengIdSheng implements Comparator { + + @Override + public int compare(Student o1, Student o2) { + return o1.age != o2.age ? (o1.age - o2.age) + : (o1.id - o2.id); + } + + } + + + // 先按照id排序,id小的,放前面; + // id一样,age大的,前面; + public static class IdInAgeDe implements Comparator { + + @Override + public int compare(Student o1, Student o2) { + return o1.id != o2.id ? o1.id - o2.id : ( o2.age - o1.age ); + } + + } + + + public static void printStudents(Student[] students) { + for (Student student : students) { + System.out.println("Name : " + student.name + ", Id : " + student.id + ", Age : " + student.age); + } + } + + public static void printArray(Integer[] arr) { + if (arr == null) { + return; + } + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + public static class MyComp implements Comparator { + + @Override + public int compare(Integer o1, Integer o2) { + return o2 - o1; + } + + } + + + public static class AComp implements Comparator{ + + // 如果返回负数,认为第一个参数应该拍在前面 + // 如果返回正数,认为第二个参数应该拍在前面 + // 如果返回0,认为谁放前面都行 + @Override + public int compare(Integer arg0, Integer arg1) { + + return arg1 - arg0; + +// return 0; + } + + } + + + public static void main(String[] args) { + + Integer[] arr = {5,4,3,2,7,9,1,0}; + + Arrays.sort(arr, new AComp()); + + for(int i = 0 ;i < arr.length;i++) { + System.out.println(arr[i]); + } + + System.out.println("==========================="); + + Student student1 = new Student("A", 2, 20); + Student student2 = new Student("B", 3, 21); + Student student3 = new Student("C", 1, 22); + + Student[] students = new Student[] { student1, student2, student3 }; + System.out.println("第一条打印"); + + + Arrays.sort(students, new IdAscendingComparator()); + + + printStudents(students); + System.out.println("==========================="); + + + + Arrays.sort(students, new IdDescendingComparator()); + printStudents(students); + System.out.println("==========================="); + + Arrays.sort(students, new AgeAscendingComparator()); + printStudents(students); + System.out.println("==========================="); +//// +//// Arrays.sort(students, new AgeDescendingComparator()); +//// printStudents(students); +//// System.out.println("==========================="); +// +// Arrays.sort(students, new AgeShengIdSheng()); +// printStudents(students); +// +// System.out.println("==========================="); +// System.out.println("==========================="); +// System.out.println("==========================="); +// +// PriorityQueue maxHeapBasedAge = new PriorityQueue<>(new AgeDescendingComparator()); +// maxHeapBasedAge.add(student1); +// maxHeapBasedAge.add(student2); +// maxHeapBasedAge.add(student3); +// while (!maxHeapBasedAge.isEmpty()) { +// Student student = maxHeapBasedAge.poll(); +// System.out.println("Name : " + student.name + ", Id : " + student.id + ", Age : " + student.age); +// } +// System.out.println("==========================="); + + PriorityQueue minHeapBasedId + = new PriorityQueue<>(new AgeAscendingComparator()); + minHeapBasedId.add(student1); + minHeapBasedId.add(student2); + minHeapBasedId.add(student3); + while (!minHeapBasedId.isEmpty()) { + Student student = minHeapBasedId.poll(); + System.out.println("Name : " + student.name + ", Id : " + student.id + ", Age : " + student.age); + } + System.out.println("==========================="); + System.out.println("==========================="); + System.out.println("==========================="); + + TreeSet treeAgeDescending = new TreeSet<>(new AgeAscendingComparator()); + treeAgeDescending.add(student1); + treeAgeDescending.add(student2); + treeAgeDescending.add(student3); + + Student studentFirst = treeAgeDescending.first(); + System.out.println("Name : " + studentFirst.name + ", Id : " + studentFirst.id + ", Age : " + studentFirst.age); + + Student studentLast = treeAgeDescending.last(); + System.out.println("Name : " + studentLast.name + ", Id : " + studentLast.id + ", Age : " + studentLast.age); + System.out.println("==========================="); + + } + +} diff --git a/src/class04/Code02_Heap01.java b/src/class04/Code02_Heap01.java new file mode 100644 index 0000000..715289e --- /dev/null +++ b/src/class04/Code02_Heap01.java @@ -0,0 +1,160 @@ +package class04; + +public class Code02_Heap01 { + + public static class MyMaxHeap { + private int[] heap; + private final int limit; + private int heapSize; + + public MyMaxHeap(int limit) { + heap = new int[limit]; + this.limit = limit; + heapSize = 0; + } + + public boolean isEmpty() { + return heapSize == 0; + } + + public boolean isFull() { + return heapSize == limit; + } + + public void push(int value) { + if (heapSize == limit) { + throw new RuntimeException("heap is full"); + } + heap[heapSize] = value; + // value heapSize + heapInsert(heap, heapSize++); + } + + // 用户此时,让你返回最大值,并且在大根堆中,把最大值删掉 + // 剩下的数,依然保持大根堆组织 + public int pop() { + int ans = heap[0]; + swap(heap, 0, --heapSize); + heapify(heap, 0, heapSize); + return ans; + } + + private void heapInsert(int[] arr, int index) { + // arr[index] + // arr[index] 不比 arr[index父]大了 , 停 + // index = 0; + while (arr[index] > arr[(index - 1) / 2]) { + swap(arr, index, (index - 1) / 2); + index = (index - 1) / 2; + } + } + + // 从index位置,往下看,不断的下沉, + // 停:我的孩子都不再比我大;已经没孩子了 + private void heapify(int[] arr, int index, int heapSize) { + int left = index * 2 + 1; + while (left < heapSize) { + // 左右两个孩子中,谁大,谁把自己的下标给largest + // 右 -> 1) 有右孩子 && 2)右孩子的值比左孩子大才行 + // 否则,左 + int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left; + largest = arr[largest] > arr[index] ? largest : index; + if (largest == index) { + break; + } + swap(arr, largest, index); + index = largest; + left = index * 2 + 1; + } + } + + private void swap(int[] arr, int i, int j) { + int tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + + } + + public static class RightMaxHeap { + private int[] arr; + private final int limit; + private int size; + + public RightMaxHeap(int limit) { + arr = new int[limit]; + this.limit = limit; + size = 0; + } + + public boolean isEmpty() { + return size == 0; + } + + public boolean isFull() { + return size == limit; + } + + public void push(int value) { + if (size == limit) { + throw new RuntimeException("heap is full"); + } + arr[size++] = value; + } + + public int pop() { + int maxIndex = 0; + for (int i = 1; i < size; i++) { + if (arr[i] > arr[maxIndex]) { + maxIndex = i; + } + } + int ans = arr[maxIndex]; + arr[maxIndex] = arr[--size]; + return ans; + } + + } + + public static void main(String[] args) { + int value = 1000; + int limit = 100; + int testTimes = 1000000; + for (int i = 0; i < testTimes; i++) { + int curLimit = (int) (Math.random() * limit) + 1; + MyMaxHeap my = new MyMaxHeap(curLimit); + RightMaxHeap test = new RightMaxHeap(curLimit); + int curOpTimes = (int) (Math.random() * limit); + for (int j = 0; j < curOpTimes; j++) { + if (my.isEmpty() != test.isEmpty()) { + System.out.println("Oops!"); + } + if (my.isFull() != test.isFull()) { + System.out.println("Oops!"); + } + if (my.isEmpty()) { + int curValue = (int) (Math.random() * value); + my.push(curValue); + test.push(curValue); + } else if (my.isFull()) { + if (my.pop() != test.pop()) { + System.out.println("Oops!"); + } + } else { + if (Math.random() < 0.5) { + int curValue = (int) (Math.random() * value); + my.push(curValue); + test.push(curValue); + } else { + if (my.pop() != test.pop()) { + System.out.println("Oops!"); + } + } + } + } + } + System.out.println("finish!"); + + } + +} diff --git a/src/class04/Code03_Heap02.java b/src/class04/Code03_Heap02.java new file mode 100644 index 0000000..aa0fba5 --- /dev/null +++ b/src/class04/Code03_Heap02.java @@ -0,0 +1,256 @@ +package class04; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.PriorityQueue; + +public class Code03_Heap02 { + + // 堆 + public static class MyHeap { + private ArrayList heap; + private HashMap indexMap; + private int heapSize; + private Comparator comparator; + + public MyHeap(Comparator com) { + heap = new ArrayList<>(); + indexMap = new HashMap<>(); + heapSize = 0; + comparator = com; + } + + public boolean isEmpty() { + return heapSize == 0; + } + + public int size() { + return heapSize; + } + + public boolean contains(T key) { + return indexMap.containsKey(key); + } + + public void push(T value) { + heap.add(value); + indexMap.put(value, heapSize); + heapInsert(heapSize++); + } + + public T pop() { + T ans = heap.get(0); + int end = heapSize - 1; + swap(0, end); + heap.remove(end); + indexMap.remove(ans); + heapify(0, --heapSize); + return ans; + } + + public void resign(T value) { + int valueIndex = indexMap.get(value); + heapInsert(valueIndex); + heapify(valueIndex, heapSize); + } + + private void heapInsert(int index) { + while (comparator.compare(heap.get(index), heap.get((index - 1) / 2)) < 0) { + swap(index, (index - 1) / 2); + index = (index - 1) / 2; + } + } + + private void heapify(int index, int heapSize) { + int left = index * 2 + 1; + while (left < heapSize) { + int largest = left + 1 < heapSize && (comparator.compare(heap.get(left + 1), heap.get(left)) < 0) + ? left + 1 + : left; + largest = comparator.compare(heap.get(largest), heap.get(index)) < 0 ? largest : index; + if (largest == index) { + break; + } + swap(largest, index); + index = largest; + left = index * 2 + 1; + } + } + + private void swap(int i, int j) { + T o1 = heap.get(i); + T o2 = heap.get(j); + heap.set(i, o2); + heap.set(j, o1); + indexMap.put(o1, j); + indexMap.put(o2, i); + } + + } + + public static class Student { + public int classNo; + public int age; + public int id; + + public Student(int c, int a, int i) { + classNo = c; + age = a; + id = i; + } + + } + + public static class StudentComparator implements Comparator { + + @Override + public int compare(Student o1, Student o2) { + return o1.age - o2.age; + } + + } + + public static void main(String[] args) { + Student s1 = null; + Student s2 = null; + Student s3 = null; + Student s4 = null; + Student s5 = null; + Student s6 = null; + + s1 = new Student(2, 50, 11111); + s2 = new Student(1, 60, 22222); + s3 = new Student(6, 10, 33333); + s4 = new Student(3, 20, 44444); + s5 = new Student(7, 72, 55555); + s6 = new Student(1, 14, 66666); + + PriorityQueue heap = new PriorityQueue<>(new StudentComparator()); + heap.add(s1); + heap.add(s2); + heap.add(s3); + heap.add(s4); + heap.add(s5); + heap.add(s6); + while (!heap.isEmpty()) { + Student cur = heap.poll(); + System.out.println(cur.classNo + "," + cur.age + "," + cur.id); + } + + System.out.println("==============="); + + MyHeap myHeap = new MyHeap<>(new StudentComparator()); + myHeap.push(s1); + myHeap.push(s2); + myHeap.push(s3); + myHeap.push(s4); + myHeap.push(s5); + myHeap.push(s6); + while (!myHeap.isEmpty()) { + Student cur = myHeap.pop(); + System.out.println(cur.classNo + "," + cur.age + "," + cur.id); + } + + System.out.println("==============="); + + s1 = new Student(2, 50, 11111); + s2 = new Student(1, 60, 22222); + s3 = new Student(6, 10, 33333); + s4 = new Student(3, 20, 44444); + s5 = new Student(7, 72, 55555); + s6 = new Student(1, 14, 66666); + + heap = new PriorityQueue<>(new StudentComparator()); + + heap.add(s1); + heap.add(s2); + heap.add(s3); + heap.add(s4); + heap.add(s5); + heap.add(s6); + + s2.age = 6; + s4.age = 12; + s5.age = 10; + s6.age = 84; + + while (!heap.isEmpty()) { + Student cur = heap.poll(); + System.out.println(cur.classNo + "," + cur.age + "," + cur.id); + } + + System.out.println("==============="); + + s1 = new Student(2, 50, 11111); + s2 = new Student(1, 60, 22222); + s3 = new Student(6, 10, 33333); + s4 = new Student(3, 20, 44444); + s5 = new Student(7, 72, 55555); + s6 = new Student(1, 14, 66666); + + myHeap = new MyHeap<>(new StudentComparator()); + + myHeap.push(s1); + myHeap.push(s2); + myHeap.push(s3); + myHeap.push(s4); + myHeap.push(s5); + myHeap.push(s6); + + s2.age = 6; + myHeap.resign(s2); + s4.age = 12; + myHeap.resign(s4); + s5.age = 10; + myHeap.resign(s5); + s6.age = 84; + myHeap.resign(s6); + + while (!myHeap.isEmpty()) { + Student cur = myHeap.pop(); + System.out.println(cur.classNo + "," + cur.age + "," + cur.id); + } + + + + // 对数器 + System.out.println("test begin"); + int maxValue = 100000; + int pushTime = 1000000; + int resignTime = 100; + MyHeap test = new MyHeap<>(new StudentComparator()); + ArrayList list = new ArrayList<>(); + for(int i = 0 ; i < pushTime; i++) { + Student cur = new Student(1,(int) (Math.random() * maxValue), 1000); + list.add(cur); + test.push(cur); + } + for(int i = 0 ; i < resignTime; i++) { + int index = (int)(Math.random() * pushTime); + list.get(index).age = (int) (Math.random() * maxValue); + test.resign(list.get(index)); + } + int preAge = Integer.MIN_VALUE; + while(test.isEmpty()) { + Student cur = test.pop(); + if(cur.age < preAge) { + System.out.println("Oops!"); + } + preAge = cur.age; + } + System.out.println("test finish"); + + + + + + + + + + + + } + +} diff --git a/src/class04/Code04_HeapSort.java b/src/class04/Code04_HeapSort.java new file mode 100644 index 0000000..1b65638 --- /dev/null +++ b/src/class04/Code04_HeapSort.java @@ -0,0 +1,157 @@ +package class04; + +import java.util.Arrays; +import java.util.PriorityQueue; + +public class Code04_HeapSort { + + // 堆排序额外空间复杂度O(1) + public static void heapSort(int[] arr) { + if (arr == null || arr.length < 2) { + return; + } + // O(N*logN) +// for (int i = 0; i < arr.length; i++) { // O(N) +// heapInsert(arr, i); // O(logN) +// } + for (int i = arr.length - 1; i >= 0; i--) { + heapify(arr, i, arr.length); + } + int heapSize = arr.length; + swap(arr, 0, --heapSize); + // O(N*logN) + while (heapSize > 0) { // O(N) + heapify(arr, 0, heapSize); // O(logN) + swap(arr, 0, --heapSize); // O(1) + } + } + + // arr[index]刚来的数,往上 + public static void heapInsert(int[] arr, int index) { + while (arr[index] > arr[(index - 1) / 2]) { + swap(arr, index, (index - 1) / 2); + index = (index - 1) / 2; + } + } + + // arr[index]位置的数,能否往下移动 + public static void heapify(int[] arr, int index, int heapSize) { + int left = index * 2 + 1; // 左孩子的下标 + while (left < heapSize) { // 下方还有孩子的时候 + // 两个孩子中,谁的值大,把下标给largest + // 1)只有左孩子,left -> largest + // 2) 同时有左孩子和右孩子,右孩子的值<= 左孩子的值,left -> largest + // 3) 同时有左孩子和右孩子并且右孩子的值> 左孩子的值, right -> largest + int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left; + // 父和较大的孩子之间,谁的值大,把下标给largest + largest = arr[largest] > arr[index] ? largest : index; + if (largest == index) { + break; + } + swap(arr, largest, index); + index = largest; + left = index * 2 + 1; + } + } + + public static void swap(int[] arr, int i, int j) { + int tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + + // for test + public static void comparator(int[] arr) { + Arrays.sort(arr); + } + + // for test + public static int[] generateRandomArray(int maxSize, int maxValue) { + int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); + } + return arr; + } + + // for test + public static int[] copyArray(int[] arr) { + if (arr == null) { + return null; + } + int[] res = new int[arr.length]; + for (int i = 0; i < arr.length; i++) { + res[i] = arr[i]; + } + return res; + } + + // for test + public static boolean isEqual(int[] arr1, int[] arr2) { + if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { + return false; + } + if (arr1 == null && arr2 == null) { + return true; + } + if (arr1.length != arr2.length) { + return false; + } + for (int i = 0; i < arr1.length; i++) { + if (arr1[i] != arr2[i]) { + return false; + } + } + return true; + } + + // for test + public static void printArray(int[] arr) { + if (arr == null) { + return; + } + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + // for test + public static void main(String[] args) { + + // 默认小根堆 + PriorityQueue heap = new PriorityQueue<>(); + heap.add(6); + heap.add(8); + heap.add(0); + heap.add(2); + heap.add(9); + heap.add(1); + + while (!heap.isEmpty()) { + System.out.println(heap.poll()); + } + + int testTime = 500000; + int maxSize = 100; + int maxValue = 100; + boolean succeed = true; + for (int i = 0; i < testTime; i++) { + int[] arr1 = generateRandomArray(maxSize, maxValue); + int[] arr2 = copyArray(arr1); + heapSort(arr1); + comparator(arr2); + if (!isEqual(arr1, arr2)) { + succeed = false; + break; + } + } + System.out.println(succeed ? "Nice!" : "Fucking fucked!"); + + int[] arr = generateRandomArray(maxSize, maxValue); + printArray(arr); + heapSort(arr); + printArray(arr); + } + +} diff --git a/src/class04/Code05_SortArrayDistanceLessK.java b/src/class04/Code05_SortArrayDistanceLessK.java new file mode 100644 index 0000000..ae986b0 --- /dev/null +++ b/src/class04/Code05_SortArrayDistanceLessK.java @@ -0,0 +1,127 @@ +package class04; + +import java.util.Arrays; +import java.util.PriorityQueue; + +public class Code05_SortArrayDistanceLessK { + + public static void sortedArrDistanceLessK(int[] arr, int k) { + if (k == 0) { + return; + } + // 默认小根堆 + PriorityQueue heap = new PriorityQueue<>(); + int index = 0; + // 0...K-1 + for (; index <= Math.min(arr.length - 1, k - 1); index++) { + heap.add(arr[index]); + } + int i = 0; + for (; index < arr.length; i++, index++) { + heap.add(arr[index]); + arr[i] = heap.poll(); + } + while (!heap.isEmpty()) { + arr[i++] = heap.poll(); + } + } + + // for test + public static void comparator(int[] arr, int k) { + Arrays.sort(arr); + } + + // for test + public static int[] randomArrayNoMoveMoreK(int maxSize, int maxValue, int K) { + int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); + } + // 先排个序 + Arrays.sort(arr); + // 然后开始随意交换,但是保证每个数距离不超过K + // swap[i] == true, 表示i位置已经参与过交换 + // swap[i] == false, 表示i位置没有参与过交换 + boolean[] isSwap = new boolean[arr.length]; + for (int i = 0; i < arr.length; i++) { + int j = Math.min(i + (int) (Math.random() * (K + 1)), arr.length - 1); + if (!isSwap[i] && !isSwap[j]) { + isSwap[i] = true; + isSwap[j] = true; + int tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + } + return arr; + } + + // for test + public static int[] copyArray(int[] arr) { + if (arr == null) { + return null; + } + int[] res = new int[arr.length]; + for (int i = 0; i < arr.length; i++) { + res[i] = arr[i]; + } + return res; + } + + // for test + public static boolean isEqual(int[] arr1, int[] arr2) { + if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { + return false; + } + if (arr1 == null && arr2 == null) { + return true; + } + if (arr1.length != arr2.length) { + return false; + } + for (int i = 0; i < arr1.length; i++) { + if (arr1[i] != arr2[i]) { + return false; + } + } + return true; + } + + // for test + public static void printArray(int[] arr) { + if (arr == null) { + return; + } + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + // for test + public static void main(String[] args) { + System.out.println("test begin"); + int testTime = 500000; + int maxSize = 100; + int maxValue = 100; + boolean succeed = true; + for (int i = 0; i < testTime; i++) { + int k = (int) (Math.random() * maxSize) + 1; + int[] arr = randomArrayNoMoveMoreK(maxSize, maxValue, k); + int[] arr1 = copyArray(arr); + int[] arr2 = copyArray(arr); + sortedArrDistanceLessK(arr1, k); + comparator(arr2, k); + if (!isEqual(arr1, arr2)) { + succeed = false; + System.out.println("K : " + k); + printArray(arr); + printArray(arr1); + printArray(arr2); + break; + } + } + System.out.println(succeed ? "Nice!" : "Fucking fucked!"); + } + +} \ No newline at end of file diff --git a/src/class04/Test.java b/src/class04/Test.java new file mode 100644 index 0000000..ce841f9 --- /dev/null +++ b/src/class04/Test.java @@ -0,0 +1,43 @@ +package class04; + +import java.util.Comparator; +import java.util.PriorityQueue; + + +public class Test { + + // 负数,o1 放在上面的情况 + public static class MyComp implements Comparator{ + + @Override + public int compare(Integer o1, Integer o2) { + return o2 - o1; + } + + } + + + + public static void main(String[] args) { + System.out.println("hello"); + // 大根堆 + PriorityQueue heap = new PriorityQueue<>(new MyComp()); + + heap.add(5); + heap.add(7); + heap.add(3); + heap.add(0); + heap.add(2); + heap.add(5); + + while(!heap.isEmpty()) { + System.out.println(heap.poll()); + } + + + + + + } + +} diff --git a/src/class05/Code01_TrieTree.java b/src/class05/Code01_TrieTree.java new file mode 100644 index 0000000..fddcf13 --- /dev/null +++ b/src/class05/Code01_TrieTree.java @@ -0,0 +1,298 @@ +package class05; + +import java.util.HashMap; + +// 该程序的对数器跑不过,你能发现bug在哪吗? +public class Code01_TrieTree { + + public static class Node1 { + public int pass; + public int end; + public Node1[] nexts; + + public Node1() { + pass = 0; + end = 0; + nexts = new Node1[26]; + } + } + + public static class Trie1 { + private Node1 root; + + public Trie1() { + root = new Node1(); + } + + public void insert(String word) { + if (word == null) { + return; + } + char[] chs = word.toCharArray(); + Node1 node = root; + node.pass++; + int index = 0; + for (int i = 0; i < chs.length; i++) { // 从左往右遍历字符 + index = chs[i] - 'a'; // 由字符,对应成走向哪条路 + if (node.nexts[index] == null) { + node.nexts[index] = new Node1(); + } + node = node.nexts[index]; + node.pass++; + } + node.end++; + } + + public void delete(String word) { + if (search(word) != 0) { + char[] chs = word.toCharArray(); + Node1 node = root; + node.pass--; + int index = 0; + for (int i = 0; i < chs.length; i++) { + index = chs[i] - 'a'; + if (--node.nexts[index].pass == 0) { + node.nexts[index] = null; + return; + } + node = node.nexts[index]; + } + node.end--; + } + } + + // word这个单词之前加入过几次 + public int search(String word) { + if (word == null) { + return 0; + } + char[] chs = word.toCharArray(); + Node1 node = root; + int index = 0; + for (int i = 0; i < chs.length; i++) { + index = chs[i] - 'a'; + if (node.nexts[index] == null) { + return 0; + } + node = node.nexts[index]; + } + return node.end; + } + + // 所有加入的字符串中,有几个是以pre这个字符串作为前缀的 + public int prefixNumber(String pre) { + if (pre == null) { + return 0; + } + char[] chs = pre.toCharArray(); + Node1 node = root; + int index = 0; + for (int i = 0; i < chs.length; i++) { + index = chs[i] - 'a'; + if (node.nexts[index] == null) { + return 0; + } + node = node.nexts[index]; + } + return node.pass; + } + } + + public static class Node2 { + public int pass; + public int end; + public HashMap nexts; + + public Node2() { + pass = 0; + end = 0; + nexts = new HashMap<>(); + } + } + + public static class Trie2 { + private Node2 root; + + public Trie2() { + root = new Node2(); + } + + public void insert(String word) { + if (word == null) { + return; + } + char[] chs = word.toCharArray(); + Node2 node = root; + node.pass++; + int index = 0; + for (int i = 0; i < chs.length; i++) { + index = (int) chs[i]; + if (!node.nexts.containsKey(index)) { + node.nexts.put(index, new Node2()); + } + node = node.nexts.get(index); + node.pass++; + } + node.end++; + } + + public void delete(String word) { + if (search(word) != 0) { + char[] chs = word.toCharArray(); + Node2 node = root; + node.pass--; + int index = 0; + for (int i = 0; i < chs.length; i++) { + index = (int) chs[i]; + if (--node.nexts.get(index).pass == 0) { + node.nexts.remove(index); + return; + } + node = node.nexts.get(index); + } + node.end--; + } + } + + // word这个单词之前加入过几次 + public int search(String word) { + if (word == null) { + return 0; + } + char[] chs = word.toCharArray(); + Node2 node = root; + int index = 0; + for (int i = 0; i < chs.length; i++) { + index = (int) chs[i]; + if (!node.nexts.containsKey(index)) { + return 0; + } + node = node.nexts.get(index); + } + return node.end; + } + + // 所有加入的字符串中,有几个是以pre这个字符串作为前缀的 + public int prefixNumber(String pre) { + if (pre == null) { + return 0; + } + char[] chs = pre.toCharArray(); + Node2 node = root; + int index = 0; + for (int i = 0; i < chs.length; i++) { + index = (int) chs[i]; + if (!node.nexts.containsKey(index)) { + return 0; + } + node = node.nexts.get(index); + } + return node.pass; + } + } + + public static class Right { + + private HashMap box; + + public Right() { + box = new HashMap<>(); + } + + public void insert(String word) { + if (!box.containsKey(word)) { + box.put(word, 1); + } else { + box.put(word, box.get(word) + 1); + } + } + + public void delete(String word) { + if (box.containsKey(word)) { + if (box.get(word) == 1) { + box.remove(word); + } else { + box.put(word, box.get(word) - 1); + } + } + } + + public int search(String word) { + if (!box.containsKey(word)) { + return 0; + } else { + return box.get(word); + } + } + + public int prefixNumber(String pre) { + int count = 0; + for (String cur : box.keySet()) { + if (cur.startsWith(pre)) { + count++; + } + } + return count; + } + } + + // for test + public static String generateRandomString(int strLen) { + char[] ans = new char[(int) (Math.random() * strLen) + 1]; + for (int i = 0; i < ans.length; i++) { + int value = (int) (Math.random() * 6); + ans[i] = (char) (97 + value); + } + return String.valueOf(ans); + } + + // for test + public static String[] generateRandomStringArray(int arrLen, int strLen) { + String[] ans = new String[(int) (Math.random() * arrLen) + 1]; + for (int i = 0; i < ans.length; i++) { + ans[i] = generateRandomString(strLen); + } + return ans; + } + + public static void main(String[] args) { + int arrLen = 100; + int strLen = 20; + int testTimes = 100000; + for (int i = 0; i < testTimes; i++) { + String[] arr = generateRandomStringArray(arrLen, strLen); + Trie1 trie1 = new Trie1(); + Trie2 trie2 = new Trie2(); + Right right = new Right(); + for (int j = 0; j < arr.length; j++) { + double decide = Math.random(); + if (decide < 0.25) { + trie1.insert(arr[j]); + trie2.insert(arr[j]); + right.insert(arr[j]); + } else if (decide < 0.5) { + trie1.delete(arr[j]); + trie2.delete(arr[j]); + right.delete(arr[j]); + } else if (decide < 0.75) { + int ans1 = trie1.search(arr[j]); + int ans2 = trie2.search(arr[j]); + int ans3 = right.search(arr[j]); + if (ans1 != ans2 || ans2 != ans3) { + System.out.println("Oops!"); + } + } else { + int ans1 = trie1.prefixNumber(arr[j]); + int ans2 = trie2.prefixNumber(arr[j]); + int ans3 = right.prefixNumber(arr[j]); + if (ans1 != ans2 || ans2 != ans3) { + System.out.println("Oops!"); + } + } + } + } + System.out.println("finish!"); + + } + +} diff --git a/src/class05/Code02_TrieTree.java b/src/class05/Code02_TrieTree.java new file mode 100644 index 0000000..a96cc5f --- /dev/null +++ b/src/class05/Code02_TrieTree.java @@ -0,0 +1,305 @@ +package class05; + +import java.util.HashMap; + +// 该程序完全正确 +public class Code02_TrieTree { + + public static class Node1 { + public int pass; + public int end; + public Node1[] nexts; + + public Node1() { + pass = 0; + end = 0; + // 0 a + // 1 b + // 2 c + // .. .. + // 25 z + // nexts[i] == null i方向的路不存在 + // nexts[i] != null i方向的路存在 + nexts = new Node1[26]; + } + } + + public static class Trie1 { + private Node1 root; + + public Trie1() { + root = new Node1(); + } + + public void insert(String word) { + if (word == null) { + return; + } + char[] str = word.toCharArray(); + Node1 node = root; + node.pass++; + int path = 0; + for (int i = 0; i < str.length; i++) { // 从左往右遍历字符 + path = str[i] - 'a'; // 由字符,对应成走向哪条路 + if (node.nexts[path] == null) { + node.nexts[path] = new Node1(); + } + node = node.nexts[path]; + node.pass++; + } + node.end++; + } + + public void delete(String word) { + if (search(word) != 0) { + char[] chs = word.toCharArray(); + Node1 node = root; + node.pass--; + int path = 0; + for (int i = 0; i < chs.length; i++) { + path = chs[i] - 'a'; + if (--node.nexts[path].pass == 0) { + node.nexts[path] = null; + return; + } + node = node.nexts[path]; + } + node.end--; + } + } + + // word这个单词之前加入过几次 + public int search(String word) { + if (word == null) { + return 0; + } + char[] chs = word.toCharArray(); + Node1 node = root; + int index = 0; + for (int i = 0; i < chs.length; i++) { + index = chs[i] - 'a'; + if (node.nexts[index] == null) { + return 0; + } + node = node.nexts[index]; + } + return node.end; + } + + // 所有加入的字符串中,有几个是以pre这个字符串作为前缀的 + public int prefixNumber(String pre) { + if (pre == null) { + return 0; + } + char[] chs = pre.toCharArray(); + Node1 node = root; + int index = 0; + for (int i = 0; i < chs.length; i++) { + index = chs[i] - 'a'; + if (node.nexts[index] == null) { + return 0; + } + node = node.nexts[index]; + } + return node.pass; + } + } + + public static class Node2 { + public int pass; + public int end; + public HashMap nexts; + + public Node2() { + pass = 0; + end = 0; + nexts = new HashMap<>(); + } + } + + public static class Trie2 { + private Node2 root; + + public Trie2() { + root = new Node2(); + } + + public void insert(String word) { + if (word == null) { + return; + } + char[] chs = word.toCharArray(); + Node2 node = root; + node.pass++; + int index = 0; + for (int i = 0; i < chs.length; i++) { + index = (int) chs[i]; + if (!node.nexts.containsKey(index)) { + node.nexts.put(index, new Node2()); + } + node = node.nexts.get(index); + node.pass++; + } + node.end++; + } + + public void delete(String word) { + if (search(word) != 0) { + char[] chs = word.toCharArray(); + Node2 node = root; + node.pass--; + int index = 0; + for (int i = 0; i < chs.length; i++) { + index = (int) chs[i]; + if (--node.nexts.get(index).pass == 0) { + node.nexts.remove(index); + return; + } + node = node.nexts.get(index); + } + node.end--; + } + } + + // word这个单词之前加入过几次 + public int search(String word) { + if (word == null) { + return 0; + } + char[] chs = word.toCharArray(); + Node2 node = root; + int index = 0; + for (int i = 0; i < chs.length; i++) { + index = (int) chs[i]; + if (!node.nexts.containsKey(index)) { + return 0; + } + node = node.nexts.get(index); + } + return node.end; + } + + // 所有加入的字符串中,有几个是以pre这个字符串作为前缀的 + public int prefixNumber(String pre) { + if (pre == null) { + return 0; + } + char[] chs = pre.toCharArray(); + Node2 node = root; + int index = 0; + for (int i = 0; i < chs.length; i++) { + index = (int) chs[i]; + if (!node.nexts.containsKey(index)) { + return 0; + } + node = node.nexts.get(index); + } + return node.pass; + } + } + + public static class Right { + + private HashMap box; + + public Right() { + box = new HashMap<>(); + } + + public void insert(String word) { + if (!box.containsKey(word)) { + box.put(word, 1); + } else { + box.put(word, box.get(word) + 1); + } + } + + public void delete(String word) { + if (box.containsKey(word)) { + if (box.get(word) == 1) { + box.remove(word); + } else { + box.put(word, box.get(word) - 1); + } + } + } + + public int search(String word) { + if (!box.containsKey(word)) { + return 0; + } else { + return box.get(word); + } + } + + public int prefixNumber(String pre) { + int count = 0; + for (String cur : box.keySet()) { + if (cur.startsWith(pre)) { + count += box.get(cur); + } + } + return count; + } + } + + // for test + public static String generateRandomString(int strLen) { + char[] ans = new char[(int) (Math.random() * strLen) + 1]; + for (int i = 0; i < ans.length; i++) { + int value = (int) (Math.random() * 6); + ans[i] = (char) (97 + value); + } + return String.valueOf(ans); + } + + // for test + public static String[] generateRandomStringArray(int arrLen, int strLen) { + String[] ans = new String[(int) (Math.random() * arrLen) + 1]; + for (int i = 0; i < ans.length; i++) { + ans[i] = generateRandomString(strLen); + } + return ans; + } + + public static void main(String[] args) { + int arrLen = 100; + int strLen = 20; + int testTimes = 100000; + for (int i = 0; i < testTimes; i++) { + String[] arr = generateRandomStringArray(arrLen, strLen); + Trie1 trie1 = new Trie1(); + Trie2 trie2 = new Trie2(); + Right right = new Right(); + for (int j = 0; j < arr.length; j++) { + double decide = Math.random(); + if (decide < 0.25) { + trie1.insert(arr[j]); + trie2.insert(arr[j]); + right.insert(arr[j]); + } else if (decide < 0.5) { + trie1.delete(arr[j]); + trie2.delete(arr[j]); + right.delete(arr[j]); + } else if (decide < 0.75) { + int ans1 = trie1.search(arr[j]); + int ans2 = trie2.search(arr[j]); + int ans3 = right.search(arr[j]); + if (ans1 != ans2 || ans2 != ans3) { + System.out.println("Oops!"); + } + } else { + int ans1 = trie1.prefixNumber(arr[j]); + int ans2 = trie2.prefixNumber(arr[j]); + int ans3 = right.prefixNumber(arr[j]); + if (ans1 != ans2 || ans2 != ans3) { + System.out.println("Oops!"); + } + } + } + } + System.out.println("finish!"); + + } + +} diff --git a/src/class05/Code03_CountSort.java b/src/class05/Code03_CountSort.java new file mode 100644 index 0000000..0f64d1c --- /dev/null +++ b/src/class05/Code03_CountSort.java @@ -0,0 +1,111 @@ +package class05; + +import java.util.Arrays; + +public class Code03_CountSort { + + // only for 0~200 value + public static void countSort(int[] arr) { + if (arr == null || arr.length < 2) { + return; + } + int max = Integer.MIN_VALUE; + for (int i = 0; i < arr.length; i++) { + max = Math.max(max, arr[i]); + } + int[] bucket = new int[max + 1]; + for (int i = 0; i < arr.length; i++) { + bucket[arr[i]]++; + } + int i = 0; + for (int j = 0; j < bucket.length; j++) { + while (bucket[j]-- > 0) { + arr[i++] = j; + } + } + } + + // for test + public static void comparator(int[] arr) { + Arrays.sort(arr); + } + + // for test + public static int[] generateRandomArray(int maxSize, int maxValue) { + int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (int) ((maxValue + 1) * Math.random()); + } + return arr; + } + + // for test + public static int[] copyArray(int[] arr) { + if (arr == null) { + return null; + } + int[] res = new int[arr.length]; + for (int i = 0; i < arr.length; i++) { + res[i] = arr[i]; + } + return res; + } + + // for test + public static boolean isEqual(int[] arr1, int[] arr2) { + if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { + return false; + } + if (arr1 == null && arr2 == null) { + return true; + } + if (arr1.length != arr2.length) { + return false; + } + for (int i = 0; i < arr1.length; i++) { + if (arr1[i] != arr2[i]) { + return false; + } + } + return true; + } + + // for test + public static void printArray(int[] arr) { + if (arr == null) { + return; + } + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + // for test + public static void main(String[] args) { + int testTime = 500000; + int maxSize = 100; + int maxValue = 150; + boolean succeed = true; + for (int i = 0; i < testTime; i++) { + int[] arr1 = generateRandomArray(maxSize, maxValue); + int[] arr2 = copyArray(arr1); + countSort(arr1); + comparator(arr2); + if (!isEqual(arr1, arr2)) { + succeed = false; + printArray(arr1); + printArray(arr2); + break; + } + } + System.out.println(succeed ? "Nice!" : "Fucking fucked!"); + + int[] arr = generateRandomArray(maxSize, maxValue); + printArray(arr); + countSort(arr); + printArray(arr); + + } + +} diff --git a/src/class05/Code04_RadixSort.java b/src/class05/Code04_RadixSort.java new file mode 100644 index 0000000..325d97b --- /dev/null +++ b/src/class05/Code04_RadixSort.java @@ -0,0 +1,153 @@ +package class05; + +import java.util.Arrays; + +public class Code04_RadixSort { + + // only for no-negative value + public static void radixSort(int[] arr) { + if (arr == null || arr.length < 2) { + return; + } + radixSort(arr, 0, arr.length - 1, maxbits(arr)); + } + + public static int maxbits(int[] arr) { + int max = Integer.MIN_VALUE; + for (int i = 0; i < arr.length; i++) { + max = Math.max(max, arr[i]); + } + int res = 0; + while (max != 0) { + res++; + max /= 10; + } + return res; + } + + // arr[l..r]排序 , digit + // l..r 3 56 17 100 3 + public static void radixSort(int[] arr, int L, int R, int digit) { + final int radix = 10; + int i = 0, j = 0; + // 有多少个数准备多少个辅助空间 + int[] help = new int[R - L + 1]; + for (int d = 1; d <= digit; d++) { // 有多少位就进出几次 + // 10个空间 + // count[0] 当前位(d位)是0的数字有多少个 + // count[1] 当前位(d位)是(0和1)的数字有多少个 + // count[2] 当前位(d位)是(0、1和2)的数字有多少个 + // count[i] 当前位(d位)是(0~i)的数字有多少个 + int[] count = new int[radix]; // count[0..9] + for (i = L; i <= R; i++) { + // 103 1 3 + // 209 1 9 + j = getDigit(arr[i], d); + count[j]++; + } + for (i = 1; i < radix; i++) { + count[i] = count[i] + count[i - 1]; + } + for (i = R; i >= L; i--) { + j = getDigit(arr[i], d); + help[count[j] - 1] = arr[i]; + count[j]--; + } + for (i = L, j = 0; i <= R; i++, j++) { + arr[i] = help[j]; + } + } + + + + + } + + public static int getDigit(int x, int d) { + return ((x / ((int) Math.pow(10, d - 1))) % 10); + } + + // for test + public static void comparator(int[] arr) { + Arrays.sort(arr); + } + + // for test + public static int[] generateRandomArray(int maxSize, int maxValue) { + int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (int) ((maxValue + 1) * Math.random()); + } + return arr; + } + + // for test + public static int[] copyArray(int[] arr) { + if (arr == null) { + return null; + } + int[] res = new int[arr.length]; + for (int i = 0; i < arr.length; i++) { + res[i] = arr[i]; + } + return res; + } + + // for test + public static boolean isEqual(int[] arr1, int[] arr2) { + if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { + return false; + } + if (arr1 == null && arr2 == null) { + return true; + } + if (arr1.length != arr2.length) { + return false; + } + for (int i = 0; i < arr1.length; i++) { + if (arr1[i] != arr2[i]) { + return false; + } + } + return true; + } + + // for test + public static void printArray(int[] arr) { + if (arr == null) { + return; + } + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + // for test + public static void main(String[] args) { + int testTime = 500000; + int maxSize = 100; + int maxValue = 100000; + boolean succeed = true; + for (int i = 0; i < testTime; i++) { + int[] arr1 = generateRandomArray(maxSize, maxValue); + int[] arr2 = copyArray(arr1); + radixSort(arr1); + comparator(arr2); + if (!isEqual(arr1, arr2)) { + succeed = false; + printArray(arr1); + printArray(arr2); + break; + } + } + System.out.println(succeed ? "Nice!" : "Fucking fucked!"); + + int[] arr = generateRandomArray(maxSize, maxValue); + printArray(arr); + radixSort(arr); + printArray(arr); + + } + +} diff --git a/src/class06/Code01_LinkedListMid.java b/src/class06/Code01_LinkedListMid.java new file mode 100644 index 0000000..04cc571 --- /dev/null +++ b/src/class06/Code01_LinkedListMid.java @@ -0,0 +1,162 @@ +package class06; + +import java.util.ArrayList; + +public class Code01_LinkedListMid { + + public static class Node { + public int value; + public Node next; + + public Node(int v) { + value = v; + } + } + + // head 头 + public static Node midOrUpMidNode(Node head) { + if (head == null || head.next == null || head.next.next == null) { + return head; + } + // 链表有3个点或以上 + Node slow = head.next; + Node fast = head.next.next; + while (fast.next != null && fast.next.next != null) { + slow = slow.next; + fast = fast.next.next; + } + return slow; + } + + public static Node midOrDownMidNode(Node head) { + if (head == null || head.next == null) { + return head; + } + Node slow = head.next; + Node fast = head.next; + while (fast.next != null && fast.next.next != null) { + slow = slow.next; + fast = fast.next.next; + } + return slow; + } + + public static Node midOrUpMidPreNode(Node head) { + if (head == null || head.next == null || head.next.next == null) { + return null; + } + Node slow = head; + Node fast = head.next.next; + while (fast.next != null && fast.next.next != null) { + slow = slow.next; + fast = fast.next.next; + } + return slow; + } + + public static Node midOrDownMidPreNode(Node head) { + if (head == null || head.next == null) { + return null; + } + if (head.next.next == null) { + return head; + } + Node slow = head; + Node fast = head.next; + while (fast.next != null && fast.next.next != null) { + slow = slow.next; + fast = fast.next.next; + } + return slow; + } + + public static Node right1(Node head) { + if (head == null) { + return null; + } + Node cur = head; + ArrayList arr = new ArrayList<>(); + while (cur != null) { + arr.add(cur); + cur = cur.next; + } + return arr.get((arr.size() - 1) / 2); + } + + public static Node right2(Node head) { + if (head == null) { + return null; + } + Node cur = head; + ArrayList arr = new ArrayList<>(); + while (cur != null) { + arr.add(cur); + cur = cur.next; + } + return arr.get(arr.size() / 2); + } + + public static Node right3(Node head) { + if (head == null || head.next == null || head.next.next == null) { + return null; + } + Node cur = head; + ArrayList arr = new ArrayList<>(); + while (cur != null) { + arr.add(cur); + cur = cur.next; + } + return arr.get((arr.size() - 3) / 2); + } + + public static Node right4(Node head) { + if (head == null || head.next == null) { + return null; + } + Node cur = head; + ArrayList arr = new ArrayList<>(); + while (cur != null) { + arr.add(cur); + cur = cur.next; + } + return arr.get((arr.size() - 2) / 2); + } + + public static void main(String[] args) { + Node test = null; + test = new Node(0); + test.next = new Node(1); + test.next.next = new Node(2); + test.next.next.next = new Node(3); + test.next.next.next.next = new Node(4); + test.next.next.next.next.next = new Node(5); + test.next.next.next.next.next.next = new Node(6); + test.next.next.next.next.next.next.next = new Node(7); + test.next.next.next.next.next.next.next.next = new Node(8); + + Node ans1 = null; + Node ans2 = null; + + ans1 = midOrUpMidNode(test); + ans2 = right1(test); + System.out.println(ans1 != null ? ans1.value : "无"); + System.out.println(ans2 != null ? ans2.value : "无"); + + ans1 = midOrDownMidNode(test); + ans2 = right2(test); + System.out.println(ans1 != null ? ans1.value : "无"); + System.out.println(ans2 != null ? ans2.value : "无"); + + ans1 = midOrUpMidPreNode(test); + ans2 = right3(test); + System.out.println(ans1 != null ? ans1.value : "无"); + System.out.println(ans2 != null ? ans2.value : "无"); + + ans1 = midOrDownMidPreNode(test); + ans2 = right4(test); + System.out.println(ans1 != null ? ans1.value : "无"); + System.out.println(ans2 != null ? ans2.value : "无"); + + } + +} diff --git a/src/class06/Code02_IsPalindromeList.java b/src/class06/Code02_IsPalindromeList.java new file mode 100644 index 0000000..090409d --- /dev/null +++ b/src/class06/Code02_IsPalindromeList.java @@ -0,0 +1,204 @@ +package class06; + +import java.util.Stack; + +public class Code02_IsPalindromeList { + + public static class Node { + public int value; + public Node next; + + public Node(int data) { + this.value = data; + } + } + + // need n extra space + public static boolean isPalindrome1(Node head) { + Stack stack = new Stack(); + Node cur = head; + while (cur != null) { + stack.push(cur); + cur = cur.next; + } + while (head != null) { + if (head.value != stack.pop().value) { + return false; + } + head = head.next; + } + return true; + } + + // need n/2 extra space + public static boolean isPalindrome2(Node head) { + if (head == null || head.next == null) { + return true; + } + Node right = head.next; + Node cur = head; + while (cur.next != null && cur.next.next != null) { + right = right.next; + cur = cur.next.next; + } + Stack stack = new Stack(); + while (right != null) { + stack.push(right); + right = right.next; + } + while (!stack.isEmpty()) { + if (head.value != stack.pop().value) { + return false; + } + head = head.next; + } + return true; + } + + // need O(1) extra space + public static boolean isPalindrome3(Node head) { + if (head == null || head.next == null) { + return true; + } + Node n1 = head; + Node n2 = head; + while (n2.next != null && n2.next.next != null) { // find mid node + n1 = n1.next; // n1 -> mid + n2 = n2.next.next; // n2 -> end + } + // n1 中点 + + + n2 = n1.next; // n2 -> right part first node + n1.next = null; // mid.next -> null + Node n3 = null; + while (n2 != null) { // right part convert + n3 = n2.next; // n3 -> save next node + n2.next = n1; // next of right node convert + n1 = n2; // n1 move + n2 = n3; // n2 move + } + n3 = n1; // n3 -> save last node + n2 = head;// n2 -> left first node + boolean res = true; + while (n1 != null && n2 != null) { // check palindrome + if (n1.value != n2.value) { + res = false; + break; + } + n1 = n1.next; // left to mid + n2 = n2.next; // right to mid + } + n1 = n3.next; + n3.next = null; + while (n1 != null) { // recover list + n2 = n1.next; + n1.next = n3; + n3 = n1; + n1 = n2; + } + return res; + } + + public static void printLinkedList(Node node) { + System.out.print("Linked List: "); + while (node != null) { + System.out.print(node.value + " "); + node = node.next; + } + System.out.println(); + } + + public static void main(String[] args) { + + Node head = null; + printLinkedList(head); + System.out.print(isPalindrome1(head) + " | "); + System.out.print(isPalindrome2(head) + " | "); + System.out.println(isPalindrome3(head) + " | "); + printLinkedList(head); + System.out.println("========================="); + + head = new Node(1); + printLinkedList(head); + System.out.print(isPalindrome1(head) + " | "); + System.out.print(isPalindrome2(head) + " | "); + System.out.println(isPalindrome3(head) + " | "); + printLinkedList(head); + System.out.println("========================="); + + head = new Node(1); + head.next = new Node(2); + printLinkedList(head); + System.out.print(isPalindrome1(head) + " | "); + System.out.print(isPalindrome2(head) + " | "); + System.out.println(isPalindrome3(head) + " | "); + printLinkedList(head); + System.out.println("========================="); + + head = new Node(1); + head.next = new Node(1); + printLinkedList(head); + System.out.print(isPalindrome1(head) + " | "); + System.out.print(isPalindrome2(head) + " | "); + System.out.println(isPalindrome3(head) + " | "); + printLinkedList(head); + System.out.println("========================="); + + head = new Node(1); + head.next = new Node(2); + head.next.next = new Node(3); + printLinkedList(head); + System.out.print(isPalindrome1(head) + " | "); + System.out.print(isPalindrome2(head) + " | "); + System.out.println(isPalindrome3(head) + " | "); + printLinkedList(head); + System.out.println("========================="); + + head = new Node(1); + head.next = new Node(2); + head.next.next = new Node(1); + printLinkedList(head); + System.out.print(isPalindrome1(head) + " | "); + System.out.print(isPalindrome2(head) + " | "); + System.out.println(isPalindrome3(head) + " | "); + printLinkedList(head); + System.out.println("========================="); + + head = new Node(1); + head.next = new Node(2); + head.next.next = new Node(3); + head.next.next.next = new Node(1); + printLinkedList(head); + System.out.print(isPalindrome1(head) + " | "); + System.out.print(isPalindrome2(head) + " | "); + System.out.println(isPalindrome3(head) + " | "); + printLinkedList(head); + System.out.println("========================="); + + head = new Node(1); + head.next = new Node(2); + head.next.next = new Node(2); + head.next.next.next = new Node(1); + printLinkedList(head); + System.out.print(isPalindrome1(head) + " | "); + System.out.print(isPalindrome2(head) + " | "); + System.out.println(isPalindrome3(head) + " | "); + printLinkedList(head); + System.out.println("========================="); + + head = new Node(1); + head.next = new Node(2); + head.next.next = new Node(3); + head.next.next.next = new Node(2); + head.next.next.next.next = new Node(1); + printLinkedList(head); + System.out.print(isPalindrome1(head) + " | "); + System.out.print(isPalindrome2(head) + " | "); + System.out.println(isPalindrome3(head) + " | "); + printLinkedList(head); + System.out.println("========================="); + + } + +} diff --git a/src/class06/Code03_SmallerEqualBigger.java b/src/class06/Code03_SmallerEqualBigger.java new file mode 100644 index 0000000..d234365 --- /dev/null +++ b/src/class06/Code03_SmallerEqualBigger.java @@ -0,0 +1,136 @@ +package class06; + +public class Code03_SmallerEqualBigger { + + public static class Node { + public int value; + public Node next; + + public Node(int data) { + this.value = data; + } + } + + public static Node listPartition1(Node head, int pivot) { + if (head == null) { + return head; + } + Node cur = head; + int i = 0; + while (cur != null) { + i++; + cur = cur.next; + } + Node[] nodeArr = new Node[i]; + i = 0; + cur = head; + for (i = 0; i != nodeArr.length; i++) { + nodeArr[i] = cur; + cur = cur.next; + } + arrPartition(nodeArr, pivot); + for (i = 1; i != nodeArr.length; i++) { + nodeArr[i - 1].next = nodeArr[i]; + } + nodeArr[i - 1].next = null; + return nodeArr[0]; + } + + public static void arrPartition(Node[] nodeArr, int pivot) { + int small = -1; + int big = nodeArr.length; + int index = 0; + while (index != big) { + if (nodeArr[index].value < pivot) { + swap(nodeArr, ++small, index++); + } else if (nodeArr[index].value == pivot) { + index++; + } else { + swap(nodeArr, --big, index); + } + } + } + + public static void swap(Node[] nodeArr, int a, int b) { + Node tmp = nodeArr[a]; + nodeArr[a] = nodeArr[b]; + nodeArr[b] = tmp; + } + + public static Node listPartition2(Node head, int pivot) { + Node sH = null; // small head + Node sT = null; // small tail + Node eH = null; // equal head + Node eT = null; // equal tail + Node mH = null; // big head + Node mT = null; // big tail + Node next = null; // save next node + // every node distributed to three lists + while (head != null) { + next = head.next; + head.next = null; + if (head.value < pivot) { + if (sH == null) { + sH = head; + sT = head; + } else { + sT.next = head; + sT = head; + } + } else if (head.value == pivot) { + if (eH == null) { + eH = head; + eT = head; + } else { + eT.next = head; + eT = head; + } + } else { + if (mH == null) { + mH = head; + mT = head; + } else { + mT.next = head; + mT = head; + } + } + head = next; + } + // 小于区域的尾巴,连等于区域的头,等于区域的尾巴连大于区域的头 + if (sT != null) { // 如果有小于区域 + sT.next = eH; + eT = eT == null ? sT : eT; // 下一步,谁去连大于区域的头,谁就变成eT + } + // 上面的if,不管跑了没有,et + // all reconnect + if (eT != null) { // 如果小于区域和等于区域,不是都没有 + eT.next = mH; + } + return sH != null ? sH : (eH != null ? eH : mH); + } + + public static void printLinkedList(Node node) { + System.out.print("Linked List: "); + while (node != null) { + System.out.print(node.value + " "); + node = node.next; + } + System.out.println(); + } + + public static void main(String[] args) { + Node head1 = new Node(7); + head1.next = new Node(9); + head1.next.next = new Node(1); + head1.next.next.next = new Node(8); + head1.next.next.next.next = new Node(5); + head1.next.next.next.next.next = new Node(2); + head1.next.next.next.next.next.next = new Node(5); + printLinkedList(head1); + // head1 = listPartition1(head1, 4); + head1 = listPartition2(head1, 5); + printLinkedList(head1); + + } + +} diff --git a/src/class06/Code04_CopyListWithRandom.java b/src/class06/Code04_CopyListWithRandom.java new file mode 100644 index 0000000..be21b71 --- /dev/null +++ b/src/class06/Code04_CopyListWithRandom.java @@ -0,0 +1,130 @@ +package class06; + +import java.util.HashMap; + +public class Code04_CopyListWithRandom { + + public static class Node { + public int value; + public Node next; + public Node rand; + + public Node(int data) { + this.value = data; + } + } + + public static Node copyListWithRand1(Node head) { + HashMap map = new HashMap(); + Node cur = head; + while (cur != null) { + map.put(cur, new Node(cur.value)); + cur = cur.next; + } + cur = head; + while (cur != null) { + // cur 老 + // map.get(cur) 新 + map.get(cur).next = map.get(cur.next); + map.get(cur).rand = map.get(cur.rand); + cur = cur.next; + } + return map.get(head); + } + + public static Node copyListWithRand2(Node head) { + if (head == null) { + return null; + } + Node cur = head; + Node next = null; + // copy node and link to every node + // 1 -> 2 + // 1 -> 1' -> 2 + while (cur != null) { + // cur 老 next 老的下一个 + next = cur.next; + cur.next = new Node(cur.value); + cur.next.next = next; + cur = next; + } + cur = head; + Node curCopy = null; + // set copy node rand + // 1 -> 1' -> 2 -> 2' + while (cur != null) { + // cur 老 + // cur.next 新 copy + next = cur.next.next; + curCopy = cur.next; + curCopy.rand = cur.rand != null ? cur.rand.next : null; + cur = next; + } + // head head.next + Node res = head.next; + cur = head; + // split + while (cur != null) { + next = cur.next.next; + curCopy = cur.next; + cur.next = next; + curCopy.next = next != null ? next.next : null; + cur = next; + } + return res; + } + + public static void printRandLinkedList(Node head) { + Node cur = head; + System.out.print("order: "); + while (cur != null) { + System.out.print(cur.value + " "); + cur = cur.next; + } + System.out.println(); + cur = head; + System.out.print("rand: "); + while (cur != null) { + System.out.print(cur.rand == null ? "- " : cur.rand.value + " "); + cur = cur.next; + } + System.out.println(); + } + + public static void main(String[] args) { + Node head = null; + Node res1 = null; + Node res2 = null; + printRandLinkedList(head); + res1 = copyListWithRand1(head); + printRandLinkedList(res1); + res2 = copyListWithRand2(head); + printRandLinkedList(res2); + printRandLinkedList(head); + System.out.println("========================="); + + head = new Node(1); + head.next = new Node(2); + head.next.next = new Node(3); + head.next.next.next = new Node(4); + head.next.next.next.next = new Node(5); + head.next.next.next.next.next = new Node(6); + + head.rand = head.next.next.next.next.next; // 1 -> 6 + head.next.rand = head.next.next.next.next.next; // 2 -> 6 + head.next.next.rand = head.next.next.next.next; // 3 -> 5 + head.next.next.next.rand = head.next.next; // 4 -> 3 + head.next.next.next.next.rand = null; // 5 -> null + head.next.next.next.next.next.rand = head.next.next.next; // 6 -> 4 + + printRandLinkedList(head); + res1 = copyListWithRand1(head); + printRandLinkedList(res1); + res2 = copyListWithRand2(head); + printRandLinkedList(res2); + printRandLinkedList(head); + System.out.println("========================="); + + } + +} diff --git a/src/class06/Code05_FindFirstIntersectNode.java b/src/class06/Code05_FindFirstIntersectNode.java new file mode 100644 index 0000000..40eb34e --- /dev/null +++ b/src/class06/Code05_FindFirstIntersectNode.java @@ -0,0 +1,169 @@ +package class06; + +public class Code05_FindFirstIntersectNode { + + public static class Node { + public int value; + public Node next; + + public Node(int data) { + this.value = data; + } + } + + public static Node getIntersectNode(Node head1, Node head2) { + if (head1 == null || head2 == null) { + return null; + } + Node loop1 = getLoopNode(head1); + Node loop2 = getLoopNode(head2); + if (loop1 == null && loop2 == null) { + return noLoop(head1, head2); + } + if (loop1 != null && loop2 != null) { + return bothLoop(head1, loop1, head2, loop2); + } + return null; + } + + // 找到链表第一个入环节点,如果无环,返回null + public static Node getLoopNode(Node head) { + if (head == null || head.next == null || head.next.next == null) { + return null; + } + // n1 慢 n2 快 + Node n1 = head.next; // n1 -> slow + Node n2 = head.next.next; // n2 -> fast + while (n1 != n2) { + if (n2.next == null || n2.next.next == null) { + return null; + } + n2 = n2.next.next; + n1 = n1.next; + } + n2 = head; // n2 -> walk again from head + while (n1 != n2) { + n1 = n1.next; + n2 = n2.next; + } + return n1; + } + + // 如果两个链表都无环,返回第一个相交节点,如果不想交,返回null + public static Node noLoop(Node head1, Node head2) { + if (head1 == null || head2 == null) { + return null; + } + Node cur1 = head1; + Node cur2 = head2; + int n = 0; + while (cur1.next != null) { + n++; + cur1 = cur1.next; + } + while (cur2.next != null) { + n--; + cur2 = cur2.next; + } + if (cur1 != cur2) { + return null; + } + // n : 链表1长度减去链表2长度的值 + cur1 = n > 0 ? head1 : head2; // 谁长,谁的头变成cur1 + cur2 = cur1 == head1 ? head2 : head1; // 谁短,谁的头变成cur2 + n = Math.abs(n); + while (n != 0) { + n--; + cur1 = cur1.next; + } + while (cur1 != cur2) { + cur1 = cur1.next; + cur2 = cur2.next; + } + return cur1; + } + + // 两个有环链表,返回第一个相交节点,如果不想交返回null + public static Node bothLoop(Node head1, Node loop1, Node head2, Node loop2) { + Node cur1 = null; + Node cur2 = null; + if (loop1 == loop2) { + cur1 = head1; + cur2 = head2; + int n = 0; + while (cur1 != loop1) { + n++; + cur1 = cur1.next; + } + while (cur2 != loop2) { + n--; + cur2 = cur2.next; + } + cur1 = n > 0 ? head1 : head2; + cur2 = cur1 == head1 ? head2 : head1; + n = Math.abs(n); + while (n != 0) { + n--; + cur1 = cur1.next; + } + while (cur1 != cur2) { + cur1 = cur1.next; + cur2 = cur2.next; + } + return cur1; + } else { + cur1 = loop1.next; + while (cur1 != loop1) { + if (cur1 == loop2) { + return loop1; + } + cur1 = cur1.next; + } + return null; + } + } + + public static void main(String[] args) { + // 1->2->3->4->5->6->7->null + Node head1 = new Node(1); + head1.next = new Node(2); + head1.next.next = new Node(3); + head1.next.next.next = new Node(4); + head1.next.next.next.next = new Node(5); + head1.next.next.next.next.next = new Node(6); + head1.next.next.next.next.next.next = new Node(7); + + // 0->9->8->6->7->null + Node head2 = new Node(0); + head2.next = new Node(9); + head2.next.next = new Node(8); + head2.next.next.next = head1.next.next.next.next.next; // 8->6 + System.out.println(getIntersectNode(head1, head2).value); + + // 1->2->3->4->5->6->7->4... + head1 = new Node(1); + head1.next = new Node(2); + head1.next.next = new Node(3); + head1.next.next.next = new Node(4); + head1.next.next.next.next = new Node(5); + head1.next.next.next.next.next = new Node(6); + head1.next.next.next.next.next.next = new Node(7); + head1.next.next.next.next.next.next = head1.next.next.next; // 7->4 + + // 0->9->8->2... + head2 = new Node(0); + head2.next = new Node(9); + head2.next.next = new Node(8); + head2.next.next.next = head1.next; // 8->2 + System.out.println(getIntersectNode(head1, head2).value); + + // 0->9->8->6->4->5->6.. + head2 = new Node(0); + head2.next = new Node(9); + head2.next.next = new Node(8); + head2.next.next.next = head1.next.next.next.next.next; // 8->6 + System.out.println(getIntersectNode(head1, head2).value); + + } + +} diff --git a/src/class06/Test.java b/src/class06/Test.java new file mode 100644 index 0000000..831e8d6 --- /dev/null +++ b/src/class06/Test.java @@ -0,0 +1,26 @@ +package class06; + +public class Test { + + public static class Node{ + public int value; + public Node next; + public Node(int v) { + value = v; + } + } + + public static void main(String[] args) { + Node a = new Node(1); + Node b = new Node(2); + Node c = new Node(3); + + a.next = b; + b.next = c; + + c = null; + + } + + +} diff --git a/src/class07/Code01_RecursiveTraversalBT.java b/src/class07/Code01_RecursiveTraversalBT.java new file mode 100644 index 0000000..56e9bec --- /dev/null +++ b/src/class07/Code01_RecursiveTraversalBT.java @@ -0,0 +1,72 @@ +package class07; + +public class Code01_RecursiveTraversalBT { + + public static class Node { + public int value; + public Node left; + public Node right; + + public Node(int v) { + value = v; + } + } + + public static void f(Node head) { + if (head == null) { + return; + } + // 1 + f(head.left); + // 2 + f(head.right); + // 3 + } + + // 先序打印所有节点 + public static void pre(Node head) { + if (head == null) { + return; + } + System.out.println(head.value); + pre(head.left); + pre(head.right); + } + + public static void in(Node head) { + if (head == null) { + return; + } + in(head.left); + System.out.println(head.value); + in(head.right); + } + + public static void pos(Node head) { + if (head == null) { + return; + } + pos(head.left); + pos(head.right); + System.out.println(head.value); + } + + public static void main(String[] args) { + Node head = new Node(1); + head.left = new Node(2); + head.right = new Node(3); + head.left.left = new Node(4); + head.left.right = new Node(5); + head.right.left = new Node(6); + head.right.right = new Node(7); + + pre(head); + System.out.println("========"); + in(head); + System.out.println("========"); + pos(head); + System.out.println("========"); + + } + +} diff --git a/src/class07/Code02_UnRecursiveTraversalBT.java b/src/class07/Code02_UnRecursiveTraversalBT.java new file mode 100644 index 0000000..ddff515 --- /dev/null +++ b/src/class07/Code02_UnRecursiveTraversalBT.java @@ -0,0 +1,117 @@ +package class07; + +import java.util.Stack; + +public class Code02_UnRecursiveTraversalBT { + + public static class Node { + public int value; + public Node left; + public Node right; + + public Node(int v) { + value = v; + } + } + + public static void pre(Node head) { + System.out.print("pre-order: "); + if (head != null) { + Stack stack = new Stack(); + stack.add(head); + while (!stack.isEmpty()) { + head = stack.pop(); + System.out.print(head.value + " "); + if (head.right != null) { + stack.push(head.right); + } + if (head.left != null) { + stack.push(head.left); + } + } + } + System.out.println(); + } + + public static void in(Node head) { + System.out.print("in-order: "); + if (head != null) { + Stack stack = new Stack(); + while (!stack.isEmpty() || head != null) { + if (head != null) { + stack.push(head); + head = head.left; + } else { + head = stack.pop(); + System.out.print(head.value + " "); + head = head.right; + } + } + } + System.out.println(); + } + + public static void pos1(Node head) { + System.out.print("pos-order: "); + if (head != null) { + Stack s1 = new Stack(); + Stack s2 = new Stack(); + s1.push(head); + while (!s1.isEmpty()) { + head = s1.pop(); + s2.push(head); + if (head.left != null) { + s1.push(head.left); + } + if (head.right != null) { + s1.push(head.right); + } + } + while (!s2.isEmpty()) { + System.out.print(s2.pop().value + " "); + } + } + System.out.println(); + } + + public static void pos2(Node h) { + System.out.print("pos-order: "); + if (h != null) { + Stack stack = new Stack(); + stack.push(h); + Node c = null; + while (!stack.isEmpty()) { + c = stack.peek(); + if (c.left != null && h != c.left && h != c.right) { + stack.push(c.left); + } else if (c.right != null && h != c.right) { + stack.push(c.right); + } else { + System.out.print(stack.pop().value + " "); + h = c; + } + } + } + System.out.println(); + } + + public static void main(String[] args) { + Node head = new Node(1); + head.left = new Node(2); + head.right = new Node(3); + head.left.left = new Node(4); + head.left.right = new Node(5); + head.right.left = new Node(6); + head.right.right = new Node(7); + + pre(head); + System.out.println("========"); + in(head); + System.out.println("========"); + pos1(head); + System.out.println("========"); + pos2(head); + System.out.println("========"); + } + +} diff --git a/src/class07/Code03_LevelTraversalBT.java b/src/class07/Code03_LevelTraversalBT.java new file mode 100644 index 0000000..34bd6b9 --- /dev/null +++ b/src/class07/Code03_LevelTraversalBT.java @@ -0,0 +1,49 @@ +package class07; + +import java.util.LinkedList; +import java.util.Queue; + +public class Code03_LevelTraversalBT { + + public static class Node { + public int value; + public Node left; + public Node right; + + public Node(int v) { + value = v; + } + } + + public static void level(Node head) { + if (head == null) { + return; + } + Queue queue = new LinkedList<>(); + queue.add(head); + while (!queue.isEmpty()) { + Node cur = queue.poll(); + System.out.println(cur.value); + if (cur.left != null) { + queue.add(cur.left); + } + if (cur.right != null) { + queue.add(cur.right); + } + } + } + + public static void main(String[] args) { + Node head = new Node(1); + head.left = new Node(2); + head.right = new Node(3); + head.left.left = new Node(4); + head.left.right = new Node(5); + head.right.left = new Node(6); + head.right.right = new Node(7); + + level(head); + System.out.println("========"); + } + +} diff --git a/src/class07/Code04_SerializeAndReconstructTree.java b/src/class07/Code04_SerializeAndReconstructTree.java new file mode 100644 index 0000000..7837bd0 --- /dev/null +++ b/src/class07/Code04_SerializeAndReconstructTree.java @@ -0,0 +1,159 @@ +package class07; + +import java.util.LinkedList; +import java.util.Queue; + +public class Code04_SerializeAndReconstructTree { + + public static class Node { + public int value; + public Node left; + public Node right; + + public Node(int data) { + this.value = data; + } + } + + public static Queue preSerial(Node head) { + Queue ans = new LinkedList<>(); + pres(head, ans); + return ans; + } + + public static void pres(Node head, Queue ans) { + if (head == null) { + ans.add(null); + } else { + ans.add(String.valueOf(head.value)); + pres(head.left, ans); + pres(head.right, ans); + } + } + + public static Node buildByPreQueue(Queue prelist) { + if (prelist == null || prelist.size() == 0) { + return null; + } + return preb(prelist); + } + + public static Node preb(Queue prelist) { + String value = prelist.poll(); + if (value == null) { + return null; + } + Node head = new Node(Integer.valueOf(value)); + head.left = preb(prelist); + head.right = preb(prelist); + return head; + } + + public static Queue levelSerial(Node head) { + Queue ans = new LinkedList<>(); + if (head == null) { + ans.add(null); + } else { + ans.add(String.valueOf(head.value)); + Queue queue = new LinkedList(); + queue.add(head); + while (!queue.isEmpty()) { + head = queue.poll(); + if (head.left != null) { + ans.add(String.valueOf(head.left.value)); + queue.add(head.left); + } else { + ans.add(null); + } + if (head.right != null) { + ans.add(String.valueOf(head.right.value)); + queue.add(head.right); + } else { + ans.add(null); + } + } + } + return ans; + } + + public static Node buildByLevelQueue(Queue levelList) { + if (levelList == null || levelList.size() == 0) { + return null; + } + Node head = generateNode(levelList.poll()); + Queue queue = new LinkedList(); + if (head != null) { + queue.add(head); + } + Node node = null; + while (!queue.isEmpty()) { + node = queue.poll(); + node.left = generateNode(levelList.poll()); + node.right = generateNode(levelList.poll()); + if (node.left != null) { + queue.add(node.left); + } + if (node.right != null) { + queue.add(node.right); + } + } + return head; + } + + public static Node generateNode(String val) { + if (val == null) { + return null; + } + return new Node(Integer.valueOf(val)); + } + + // for test + public static Node generateRandomBST(int maxLevel, int maxValue) { + return generate(1, maxLevel, maxValue); + } + + // for test + public static Node generate(int level, int maxLevel, int maxValue) { + if (level > maxLevel || Math.random() < 0.5) { + return null; + } + Node head = new Node((int) (Math.random() * maxValue)); + head.left = generate(level + 1, maxLevel, maxValue); + head.right = generate(level + 1, maxLevel, maxValue); + return head; + } + + // for test + public static boolean isSameValueStructure(Node head1, Node head2) { + if (head1 == null && head2 != null) { + return false; + } + if (head1 != null && head2 == null) { + return false; + } + if (head1 == null && head2 == null) { + return true; + } + if (head1.value != head2.value) { + return false; + } + return isSameValueStructure(head1.left, head2.left) && isSameValueStructure(head1.right, head2.right); + } + + public static void main(String[] args) { + int maxLevel = 5; + int maxValue = 100; + int testTimes = 1000000; + for (int i = 0; i < testTimes; i++) { + Node head = generateRandomBST(maxLevel, maxValue); + Queue pre = preSerial(head); + Queue level = levelSerial(head); + Node preBuild = buildByPreQueue(pre); + Node levelBuild = buildByLevelQueue(level); + if (!isSameValueStructure(preBuild, levelBuild)) { + System.out.println("Oops!"); + } + } + System.out.println("finish!"); + } +} diff --git a/src/class07/Code05_PrintBinaryTree.java b/src/class07/Code05_PrintBinaryTree.java new file mode 100644 index 0000000..57adbca --- /dev/null +++ b/src/class07/Code05_PrintBinaryTree.java @@ -0,0 +1,74 @@ +package class07; + +public class Code05_PrintBinaryTree { + + public static class Node { + public int value; + public Node left; + public Node right; + + public Node(int data) { + this.value = data; + } + } + + public static void printTree(Node head) { + System.out.println("Binary Tree:"); + printInOrder(head, 0, "H", 17); + System.out.println(); + } + + public static void printInOrder(Node head, int height, String to, int len) { + if (head == null) { + return; + } + printInOrder(head.right, height + 1, "v", len); + String val = to + head.value + to; + int lenM = val.length(); + int lenL = (len - lenM) / 2; + int lenR = len - lenM - lenL; + val = getSpace(lenL) + val + getSpace(lenR); + System.out.println(getSpace(height * len) + val); + printInOrder(head.left, height + 1, "^", len); + } + + public static String getSpace(int num) { + String space = " "; + StringBuffer buf = new StringBuffer(""); + for (int i = 0; i < num; i++) { + buf.append(space); + } + return buf.toString(); + } + + public static void main(String[] args) { + Node head = new Node(1); + head.left = new Node(-222222222); + head.right = new Node(3); + head.left.left = new Node(Integer.MIN_VALUE); + head.right.left = new Node(55555555); + head.right.right = new Node(66); + head.left.left.right = new Node(777); + printTree(head); + + head = new Node(1); + head.left = new Node(2); + head.right = new Node(3); + head.left.left = new Node(4); + head.right.left = new Node(5); + head.right.right = new Node(6); + head.left.left.right = new Node(7); + printTree(head); + + head = new Node(1); + head.left = new Node(1); + head.right = new Node(1); + head.left.left = new Node(1); + head.right.left = new Node(1); + head.right.right = new Node(1); + head.left.left.right = new Node(1); + printTree(head); + + } + +} diff --git a/src/class07/Code06_TreeMaxWidth.java b/src/class07/Code06_TreeMaxWidth.java new file mode 100644 index 0000000..de2c7d6 --- /dev/null +++ b/src/class07/Code06_TreeMaxWidth.java @@ -0,0 +1,114 @@ +package class07; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Queue; + +public class Code06_TreeMaxWidth { + + public static class Node { + public int value; + public Node left; + public Node right; + + public Node(int data) { + this.value = data; + } + } + + public static int maxWidthUseMap(Node head) { + if (head == null) { + return 0; + } + Queue queue = new LinkedList<>(); + queue.add(head); + // key 在 哪一层,value + HashMap levelMap = new HashMap<>(); + levelMap.put(head, 1); + int curLevel = 1; // 当前你正在统计哪一层的宽度 + int curLevelNodes = 0; // 当前层curLevel层,宽度目前是多少 + int max = 0; + while (!queue.isEmpty()) { + Node cur = queue.poll(); + int curNodeLevel = levelMap.get(cur); + if (cur.left != null) { + levelMap.put(cur.left, curNodeLevel + 1); + queue.add(cur.left); + } + if (cur.right != null) { + levelMap.put(cur.right, curNodeLevel + 1); + queue.add(cur.right); + } + if (curNodeLevel == curLevel) { + curLevelNodes++; + } else { + max = Math.max(max, curLevelNodes); + curLevel++; + curLevelNodes = 1; + } + } + max = Math.max(max, curLevelNodes); + return max; + } + + public static int maxWidthNoMap(Node head) { + if (head == null) { + return 0; + } + Queue queue = new LinkedList<>(); + queue.add(head); + Node curEnd = head; // 当前层,最右节点是谁 + Node nextEnd = null; // 下一层,最右节点是谁 + int max = 0; + int curLevelNodes = 0; // 当前层的节点数 + while (!queue.isEmpty()) { + Node cur = queue.poll(); + if (cur.left != null) { + queue.add(cur.left); + nextEnd = cur.left; + } + if (cur.right != null) { + queue.add(cur.right); + nextEnd = cur.right; + } + curLevelNodes++; + if (cur == curEnd) { + max = Math.max(max, curLevelNodes); + curLevelNodes = 0; + curEnd = nextEnd; + } + } + return max; + } + + // for test + public static Node generateRandomBST(int maxLevel, int maxValue) { + return generate(1, maxLevel, maxValue); + } + + // for test + public static Node generate(int level, int maxLevel, int maxValue) { + if (level > maxLevel || Math.random() < 0.5) { + return null; + } + Node head = new Node((int) (Math.random() * maxValue)); + head.left = generate(level + 1, maxLevel, maxValue); + head.right = generate(level + 1, maxLevel, maxValue); + return head; + } + + public static void main(String[] args) { + int maxLevel = 10; + int maxValue = 100; + int testTimes = 1000000; + for (int i = 0; i < testTimes; i++) { + Node head = generateRandomBST(maxLevel, maxValue); + if (maxWidthUseMap(head) != maxWidthNoMap(head)) { + System.out.println("Oops!"); + } + } + System.out.println("finish!"); + + } + +} diff --git a/src/class07/Code07_SuccessorNode.java b/src/class07/Code07_SuccessorNode.java new file mode 100644 index 0000000..ba365e3 --- /dev/null +++ b/src/class07/Code07_SuccessorNode.java @@ -0,0 +1,86 @@ +package class07; + +public class Code07_SuccessorNode { + + public static class Node { + public int value; + public Node left; + public Node right; + public Node parent; + + public Node(int data) { + this.value = data; + } + } + + public static Node getSuccessorNode(Node node) { + if (node == null) { + return node; + } + if (node.right != null) { + return getLeftMost(node.right); + } else { // 无右子树 + Node parent = node.parent; + while (parent != null && parent.right == node) { // 当前节点是其父亲节点右孩子 + node = parent; + parent = node.parent; + } + return parent; + } + } + + public static Node getLeftMost(Node node) { + if (node == null) { + return node; + } + while (node.left != null) { + node = node.left; + } + return node; + } + + public static void main(String[] args) { + Node head = new Node(6); + head.parent = null; + head.left = new Node(3); + head.left.parent = head; + head.left.left = new Node(1); + head.left.left.parent = head.left; + head.left.left.right = new Node(2); + head.left.left.right.parent = head.left.left; + head.left.right = new Node(4); + head.left.right.parent = head.left; + head.left.right.right = new Node(5); + head.left.right.right.parent = head.left.right; + head.right = new Node(9); + head.right.parent = head; + head.right.left = new Node(8); + head.right.left.parent = head.right; + head.right.left.left = new Node(7); + head.right.left.left.parent = head.right.left; + head.right.right = new Node(10); + head.right.right.parent = head.right; + + Node test = head.left.left; + System.out.println(test.value + " next: " + getSuccessorNode(test).value); + test = head.left.left.right; + System.out.println(test.value + " next: " + getSuccessorNode(test).value); + test = head.left; + System.out.println(test.value + " next: " + getSuccessorNode(test).value); + test = head.left.right; + System.out.println(test.value + " next: " + getSuccessorNode(test).value); + test = head.left.right.right; + System.out.println(test.value + " next: " + getSuccessorNode(test).value); + test = head; + System.out.println(test.value + " next: " + getSuccessorNode(test).value); + test = head.right.left.left; + System.out.println(test.value + " next: " + getSuccessorNode(test).value); + test = head.right.left; + System.out.println(test.value + " next: " + getSuccessorNode(test).value); + test = head.right; + System.out.println(test.value + " next: " + getSuccessorNode(test).value); + test = head.right.right; // 10's next is null + System.out.println(test.value + " next: " + getSuccessorNode(test)); + } + +} diff --git a/src/class07/Code08_PaperFolding.java b/src/class07/Code08_PaperFolding.java new file mode 100644 index 0000000..230b47d --- /dev/null +++ b/src/class07/Code08_PaperFolding.java @@ -0,0 +1,24 @@ +package class07; + +public class Code08_PaperFolding { + + public static void printAllFolds(int N) { + printProcess(1, N, true); + } + + // 递归过程,来到了某一个节点, + // i是节点的层数,N一共的层数,down == true 凹 down == false 凸 + public static void printProcess(int i, int N, boolean down) { + if (i > N) { + return; + } + printProcess(i + 1, N, true); + System.out.println(down ? "凹 " : "凸 "); + printProcess(i + 1, N, false); + } + + public static void main(String[] args) { + int N = 3; + printAllFolds(N); + } +} diff --git a/src/class08/Code01_IsBalanced.java b/src/class08/Code01_IsBalanced.java new file mode 100644 index 0000000..38238c4 --- /dev/null +++ b/src/class08/Code01_IsBalanced.java @@ -0,0 +1,92 @@ +package class08; + +public class Code01_IsBalanced { + + public static class Node { + public int value; + public Node left; + public Node right; + + public Node(int data) { + this.value = data; + } + } + + public static boolean isBalanced1(Node head) { + boolean[] ans = new boolean[1]; + ans[0] = true; + process1(head, ans); + return ans[0]; + } + + public static int process1(Node head, boolean[] ans) { + if (!ans[0] || head == null) { + return -1; + } + int leftHeight = process1(head.left, ans); + int rightHeight = process1(head.right, ans); + if (Math.abs(leftHeight - rightHeight) > 1) { + ans[0] = false; + } + return Math.max(leftHeight, rightHeight) + 1; + } + + public static boolean isBalanced2(Node head) { + return process2(head).isBalaced; + } + + // 左、右要求一样,Info 信息返回的结构体 + public static class Info { + public boolean isBalaced; + public int height; + + public Info(boolean b, int h) { + isBalaced = b; + height = h; + } + } + + public static Info process2(Node X) { + if (X == null) { + return new Info(true, 0); + } + Info leftInfo = process2(X.left); + Info rightInfo = process2(X.right); + int height = Math.max(leftInfo.height, rightInfo.height) + 1; + boolean isBalanced = true; + if (!leftInfo.isBalaced || !rightInfo.isBalaced || Math.abs(leftInfo.height - rightInfo.height) > 1) { + isBalanced = false; + } + return new Info(isBalanced, height); + } + + // for test + public static Node generateRandomBST(int maxLevel, int maxValue) { + return generate(1, maxLevel, maxValue); + } + + // for test + public static Node generate(int level, int maxLevel, int maxValue) { + if (level > maxLevel || Math.random() < 0.5) { + return null; + } + Node head = new Node((int) (Math.random() * maxValue)); + head.left = generate(level + 1, maxLevel, maxValue); + head.right = generate(level + 1, maxLevel, maxValue); + return head; + } + + public static void main(String[] args) { + int maxLevel = 5; + int maxValue = 100; + int testTimes = 1000000; + for (int i = 0; i < testTimes; i++) { + Node head = generateRandomBST(maxLevel, maxValue); + if (isBalanced1(head) != isBalanced2(head)) { + System.out.println("Oops!"); + } + } + System.out.println("finish!"); + } + +} diff --git a/src/class08/Code02_IsFull.java b/src/class08/Code02_IsFull.java new file mode 100644 index 0000000..1512def --- /dev/null +++ b/src/class08/Code02_IsFull.java @@ -0,0 +1,96 @@ +package class08; + +public class Code02_IsFull { + + public static class Node { + public int value; + public Node left; + public Node right; + + public Node(int data) { + this.value = data; + } + } + + public static boolean isFull1(Node head) { + if (head == null) { + return true; + } + int height = h(head); + int nodes = n(head); + return (1 << height) - 1 == nodes; + } + + public static int h(Node head) { + if (head == null) { + return 0; + } + return Math.max(h(head.left), h(head.right)) + 1; + } + + public static int n(Node head) { + if (head == null) { + return 0; + } + return n(head.left) + n(head.right) + 1; + } + + public static boolean isFull2(Node head) { + if (head == null) { + return true; + } + Info all = process(head); + return (1 << all.height) - 1 == all.nodes; + } + + public static class Info { + public int height; + public int nodes; + + public Info(int h, int n) { + height = h; + nodes = n; + } + } + + public static Info process(Node head) { + if (head == null) { + return new Info(0, 0); + } + Info leftInfo = process(head.left); + Info rightInfo = process(head.right); + int height = Math.max(leftInfo.height, rightInfo.height) + 1; + int nodes = leftInfo.nodes + rightInfo.nodes + 1; + return new Info(height, nodes); + } + + // for test + public static Node generateRandomBST(int maxLevel, int maxValue) { + return generate(1, maxLevel, maxValue); + } + + // for test + public static Node generate(int level, int maxLevel, int maxValue) { + if (level > maxLevel || Math.random() < 0.5) { + return null; + } + Node head = new Node((int) (Math.random() * maxValue)); + head.left = generate(level + 1, maxLevel, maxValue); + head.right = generate(level + 1, maxLevel, maxValue); + return head; + } + + public static void main(String[] args) { + int maxLevel = 5; + int maxValue = 100; + int testTimes = 1000000; + for (int i = 0; i < testTimes; i++) { + Node head = generateRandomBST(maxLevel, maxValue); + if (isFull1(head) != isFull2(head)) { + System.out.println("Oops!"); + } + } + System.out.println("finish!"); + } + +} diff --git a/src/class08/Code03_IsBST.java b/src/class08/Code03_IsBST.java new file mode 100644 index 0000000..a6a7922 --- /dev/null +++ b/src/class08/Code03_IsBST.java @@ -0,0 +1,115 @@ +package class08; + +import java.util.ArrayList; + +public class Code03_IsBST { + + public static class Node { + public int value; + public Node left; + public Node right; + + public Node(int data) { + this.value = data; + } + } + + public static boolean isBST1(Node head) { + if (head == null) { + return true; + } + ArrayList arr = new ArrayList<>(); + in(head, arr); + for (int i = 1; i < arr.size(); i++) { + if (arr.get(i).value <= arr.get(i - 1).value) { + return false; + } + } + return true; + } + + public static void in(Node head, ArrayList arr) { + if (head == null) { + return; + } + in(head.left, arr); + arr.add(head); + in(head.right, arr); + } + + public static boolean isBST2(Node head) { + if (head == null) { + return true; + } + return process(head).isBST; + } + + public static class Info { + boolean isBST; + public int min; + public int max; + + public Info(boolean is, int mi, int ma) { + isBST = is; + min = mi; + max = ma; + } + } + + public static Info process(Node head) { + if (head == null) { + return null; + } + Info leftInfo = process(head.left); + Info rightInfo = process(head.right); + int min = head.value; + int max = head.value; + if (leftInfo != null) { + min = Math.min(min, leftInfo.min); + max = Math.max(max, leftInfo.max); + } + if (rightInfo != null) { + min = Math.min(min, rightInfo.min); + max = Math.max(max, rightInfo.max); + } + boolean isBST = false; + if ( + (leftInfo == null ? true : (leftInfo.isBST && leftInfo.max < head.value)) + && + (rightInfo == null ? true : (rightInfo.isBST && rightInfo.min > head.value)) + ) { + isBST = true; + } + return new Info(isBST, min, max); + } + + // for test + public static Node generateRandomBST(int maxLevel, int maxValue) { + return generate(1, maxLevel, maxValue); + } + + // for test + public static Node generate(int level, int maxLevel, int maxValue) { + if (level > maxLevel || Math.random() < 0.5) { + return null; + } + Node head = new Node((int) (Math.random() * maxValue)); + head.left = generate(level + 1, maxLevel, maxValue); + head.right = generate(level + 1, maxLevel, maxValue); + return head; + } + + public static void main(String[] args) { + int maxLevel = 4; + int maxValue = 100; + int testTimes = 1000000; + for (int i = 0; i < testTimes; i++) { + Node head = generateRandomBST(maxLevel, maxValue); + if (isBST1(head) != isBST2(head)) { + System.out.println("Oops!"); + } + } + System.out.println("finish!"); + } + +} diff --git a/src/class08/Code04_MaxSubBSTSize.java b/src/class08/Code04_MaxSubBSTSize.java new file mode 100644 index 0000000..2f4116c --- /dev/null +++ b/src/class08/Code04_MaxSubBSTSize.java @@ -0,0 +1,229 @@ +package class08; + +import java.util.ArrayList; + +public class Code04_MaxSubBSTSize { + + public static class Node { + public int value; + public Node left; + public Node right; + + public Node(int data) { + this.value = data; + } + } + + public static int getBSTSize(Node head) { + if (head == null) { + return 0; + } + ArrayList arr = new ArrayList<>(); + in(head, arr); + for (int i = 1; i < arr.size(); i++) { + if (arr.get(i).value <= arr.get(i - 1).value) { + return 0; + } + } + return arr.size(); + } + + public static void in(Node head, ArrayList arr) { + if (head == null) { + return; + } + in(head.left, arr); + arr.add(head); + in(head.right, arr); + } + + public static int maxSubBSTSize1(Node head) { + if (head == null) { + return 0; + } + int h = getBSTSize(head); + if (h != 0) { + return h; + } + return Math.max(maxSubBSTSize1(head.left), maxSubBSTSize1(head.right)); + } + + public static int maxSubBSTSize2(Node head) { + if (head == null) { + return 0; + } + return process(head).maxSubBSTSize; + } + + + +// public static Info process(Node head) { +// if (head == null) { +// return null; +// } +// Info leftInfo = process(head.left); +// Info rightInfo = process(head.right); +// int min = head.value; +// int max = head.value; +// int maxSubBSTSize = 0; +// if (leftInfo != null) { +// min = Math.min(min, leftInfo.min); +// max = Math.max(max, leftInfo.max); +// maxSubBSTSize = Math.max(maxSubBSTSize, leftInfo.maxSubBSTSize); +// } +// if (rightInfo != null) { +// min = Math.min(min, rightInfo.min); +// max = Math.max(max, rightInfo.max); +// maxSubBSTSize = Math.max(maxSubBSTSize, rightInfo.maxSubBSTSize); +// } +// boolean isBST = false; +// if ((leftInfo == null ? true : (leftInfo.isAllBST && leftInfo.max < head.value)) +// && (rightInfo == null ? true : (rightInfo.isAllBST && rightInfo.min > head.value))) { +// isBST = true; +// maxSubBSTSize = (leftInfo == null ? 0 : leftInfo.maxSubBSTSize) +// + (rightInfo == null ? 0 : rightInfo.maxSubBSTSize) + 1; +// } +// return new Info(isBST, maxSubBSTSize, min, max); +// } + + + + + + + + + + // 任何子树 + public static class Info { + public boolean isAllBST; + public int maxSubBSTSize; + public int min; + public int max; + + public Info(boolean is, int size, int mi, int ma) { + isAllBST = is; + maxSubBSTSize = size; + min = mi; + max = ma; + } + } + + + + + public static Info process(Node X) { + if(X == null) { + return null; + } + Info leftInfo = process(X.left); + Info rightInfo = process(X.right); + + + + int min = X.value; + int max = X.value; + + if(leftInfo != null) { + min = Math.min(min, leftInfo.min); + max = Math.max(max, leftInfo.max); + } + if(rightInfo != null) { + min = Math.min(min, rightInfo.min); + max = Math.max(max, rightInfo.max); + } + + + + + + + + int maxSubBSTSize = 0; + if(leftInfo != null) { + maxSubBSTSize = leftInfo.maxSubBSTSize; + } + if(rightInfo !=null) { + maxSubBSTSize = Math.max(maxSubBSTSize, rightInfo.maxSubBSTSize); + } + boolean isAllBST = false; + + + if( + // 左树整体需要是搜索二叉树 + ( leftInfo == null ? true : leftInfo.isAllBST ) + && + ( rightInfo == null ? true : rightInfo.isAllBST ) + && + // 左树最大值 X.value) + + + ) { + + maxSubBSTSize = + (leftInfo == null ? 0 : leftInfo.maxSubBSTSize) + + + (rightInfo == null ? 0 : rightInfo.maxSubBSTSize) + + + 1; + isAllBST = true; + + + } + + + + + + + + + + + + + + + + + + return new Info(isAllBST, maxSubBSTSize, min, max); + } + + + + + + // for test + public static Node generateRandomBST(int maxLevel, int maxValue) { + return generate(1, maxLevel, maxValue); + } + + // for test + public static Node generate(int level, int maxLevel, int maxValue) { + if (level > maxLevel || Math.random() < 0.5) { + return null; + } + Node head = new Node((int) (Math.random() * maxValue)); + head.left = generate(level + 1, maxLevel, maxValue); + head.right = generate(level + 1, maxLevel, maxValue); + return head; + } + + public static void main(String[] args) { + int maxLevel = 4; + int maxValue = 100; + int testTimes = 1000000; + for (int i = 0; i < testTimes; i++) { + Node head = generateRandomBST(maxLevel, maxValue); + if (maxSubBSTSize1(head) != maxSubBSTSize2(head)) { + System.out.println("Oops!"); + } + } + System.out.println("finish!"); + } + +} diff --git a/src/class08/Code05_MaxSubBSTHead.java b/src/class08/Code05_MaxSubBSTHead.java new file mode 100644 index 0000000..70c01bb --- /dev/null +++ b/src/class08/Code05_MaxSubBSTHead.java @@ -0,0 +1,135 @@ +package class08; + +import java.util.ArrayList; + +public class Code05_MaxSubBSTHead { + + public static class Node { + public int value; + public Node left; + public Node right; + + public Node(int data) { + this.value = data; + } + } + + public static int getBSTSize(Node head) { + if (head == null) { + return 0; + } + ArrayList arr = new ArrayList<>(); + in(head, arr); + for (int i = 1; i < arr.size(); i++) { + if (arr.get(i).value <= arr.get(i - 1).value) { + return 0; + } + } + return arr.size(); + } + + public static void in(Node head, ArrayList arr) { + if (head == null) { + return; + } + in(head.left, arr); + arr.add(head); + in(head.right, arr); + } + + public static Node maxSubBSTHead1(Node head) { + if (head == null) { + return null; + } + if (getBSTSize(head) != 0) { + return head; + } + Node leftAns = maxSubBSTHead1(head.left); + Node rightAns = maxSubBSTHead1(head.right); + return getBSTSize(leftAns) >= getBSTSize(rightAns) ? leftAns : rightAns; + } + + public static Node maxSubBSTHead2(Node head) { + if (head == null) { + return null; + } + return process(head).maxSubBSTHead; + } + + public static class Info { + public Node maxSubBSTHead; + public int maxSubBSTSize; + public int min; + public int max; + + public Info(Node h, int size, int mi, int ma) { + maxSubBSTHead = h; + maxSubBSTSize = size; + min = mi; + max = ma; + } + } + + public static Info process(Node head) { + if (head == null) { + return null; + } + Info leftInfo = process(head.left); + Info rightInfo = process(head.right); + int min = head.value; + int max = head.value; + Node maxSubBSTHead = null; + int maxSubBSTSize = 0; + if (leftInfo != null) { + min = Math.min(min, leftInfo.min); + max = Math.max(max, leftInfo.max); + maxSubBSTHead = leftInfo.maxSubBSTHead; + maxSubBSTSize = leftInfo.maxSubBSTSize; + } + if (rightInfo != null) { + min = Math.min(min, rightInfo.min); + max = Math.max(max, rightInfo.max); + if (rightInfo.maxSubBSTSize > maxSubBSTSize) { + maxSubBSTHead = rightInfo.maxSubBSTHead; + maxSubBSTSize = rightInfo.maxSubBSTSize; + } + } + if ((leftInfo == null ? true : (leftInfo.maxSubBSTHead == head.left && leftInfo.max < head.value)) + && (rightInfo == null ? true : (rightInfo.maxSubBSTHead == head.right && rightInfo.min > head.value))) { + maxSubBSTHead = head; + maxSubBSTSize = (leftInfo == null ? 0 : leftInfo.maxSubBSTSize) + + (rightInfo == null ? 0 : rightInfo.maxSubBSTSize) + 1; + } + return new Info(maxSubBSTHead, maxSubBSTSize, min, max); + } + + // for test + public static Node generateRandomBST(int maxLevel, int maxValue) { + return generate(1, maxLevel, maxValue); + } + + // for test + public static Node generate(int level, int maxLevel, int maxValue) { + if (level > maxLevel || Math.random() < 0.5) { + return null; + } + Node head = new Node((int) (Math.random() * maxValue)); + head.left = generate(level + 1, maxLevel, maxValue); + head.right = generate(level + 1, maxLevel, maxValue); + return head; + } + + public static void main(String[] args) { + int maxLevel = 4; + int maxValue = 100; + int testTimes = 1000000; + for (int i = 0; i < testTimes; i++) { + Node head = generateRandomBST(maxLevel, maxValue); + if (maxSubBSTHead1(head) != maxSubBSTHead2(head)) { + System.out.println("Oops!"); + } + } + System.out.println("finish!"); + } + +} diff --git a/src/class08/Code06_IsCBT.java b/src/class08/Code06_IsCBT.java new file mode 100644 index 0000000..6fc3df4 --- /dev/null +++ b/src/class08/Code06_IsCBT.java @@ -0,0 +1,124 @@ +package class08; + +import java.util.LinkedList; + +public class Code06_IsCBT { + + public static class Node { + public int value; + public Node left; + public Node right; + + public Node(int data) { + this.value = data; + } + } + + public static boolean isCBT1(Node head) { + if (head == null) { + return true; + } + LinkedList queue = new LinkedList<>(); + // 是否遇到过左右两个孩子不双全的节点 + boolean leaf = false; + Node l = null; + Node r = null; + queue.add(head); + while (!queue.isEmpty()) { + head = queue.poll(); + l = head.left; + r = head.right; + if ( + // 如果遇到了不双全的节点之后,又发现当前节点不是叶节点 + (leaf && !(l == null && r == null)) || (l == null && r != null)) { + return false; + } + if (l != null) { + queue.add(l); + } + if (r != null) { + queue.add(r); + } + if (l == null || r == null) { + leaf = true; + } + } + return true; + } + + public static boolean isCBT2(Node head) { + if (head == null) { + return true; + } + return process(head).isCBT; + } + + public static class Info { + public boolean isFull; + public boolean isCBT; + public int height; + + public Info(boolean full, boolean cbt, int h) { + isFull = full; + isCBT = cbt; + height = h; + } + } + + public static Info process(Node head) { + if (head == null) { + return new Info(true, true, 0); + } + Info leftInfo = process(head.left); + Info rightInfo = process(head.right); + int height = Math.max(leftInfo.height, rightInfo.height) + 1; + boolean isFull = leftInfo.isFull && rightInfo.isFull && leftInfo.height == rightInfo.height; + boolean isCBT = false; + if (isFull) { + isCBT = true; + } else { + if (leftInfo.isCBT && rightInfo.isCBT) { + if (leftInfo.isCBT && rightInfo.isFull && leftInfo.height == rightInfo.height + 1) { + isCBT = true; + } + if (leftInfo.isFull && rightInfo.isFull && leftInfo.height == rightInfo.height + 1) { + isCBT = true; + } + if (leftInfo.isFull && rightInfo.isCBT && leftInfo.height == rightInfo.height) { + isCBT = true; + } + } + } + return new Info(isFull, isCBT, height); + } + + // for test + public static Node generateRandomBST(int maxLevel, int maxValue) { + return generate(1, maxLevel, maxValue); + } + + // for test + public static Node generate(int level, int maxLevel, int maxValue) { + if (level > maxLevel || Math.random() < 0.5) { + return null; + } + Node head = new Node((int) (Math.random() * maxValue)); + head.left = generate(level + 1, maxLevel, maxValue); + head.right = generate(level + 1, maxLevel, maxValue); + return head; + } + + public static void main(String[] args) { + int maxLevel = 5; + int maxValue = 100; + int testTimes = 1000000; + for (int i = 0; i < testTimes; i++) { + Node head = generateRandomBST(maxLevel, maxValue); + if (isCBT1(head) != isCBT2(head)) { + System.out.println("Oops!"); + } + } + System.out.println("finish!"); + } + +} diff --git a/src/class08/Code07_lowestAncestor.java b/src/class08/Code07_lowestAncestor.java new file mode 100644 index 0000000..a97f4be --- /dev/null +++ b/src/class08/Code07_lowestAncestor.java @@ -0,0 +1,143 @@ +package class08; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; + +public class Code07_lowestAncestor { + + public static class Node { + public int value; + public Node left; + public Node right; + + public Node(int data) { + this.value = data; + } + } + + public static Node lowestAncestor1(Node head, Node o1, Node o2) { + if (head == null) { + return null; + } + HashMap parentMap = new HashMap<>(); + parentMap.put(head, null); + fillParentMap(head, parentMap); + HashSet o1Set = new HashSet<>(); + Node cur = o1; + o1Set.add(cur); + while (parentMap.get(cur) != null) { + cur = parentMap.get(cur); + o1Set.add(cur); + } + cur = o2; + while (!o1Set.contains(cur)) { + cur = parentMap.get(cur); + } + return cur; + } + + public static void fillParentMap(Node head, HashMap parentMap) { + if (head.left != null) { + parentMap.put(head.left, head); + fillParentMap(head.left, parentMap); + } + if (head.right != null) { + parentMap.put(head.right, head); + fillParentMap(head.right, parentMap); + } + } + + public static Node lowestAncestor2(Node head, Node o1, Node o2) { + return process(head, o1, o2).ans; + } + + public static class Info { + public Node ans; + public boolean findO1; + public boolean findO2; + + public Info(Node a, boolean f1, boolean f2) { + ans = a; + findO1 = f1; + findO2 = f2; + } + } + + public static Info process(Node head, Node o1, Node o2) { + if (head == null) { + return new Info(null, false, false); + } + Info leftInfo = process(head.left, o1, o2); + Info rightInfo = process(head.right, o1, o2); + + boolean findO1 = head == o1 || leftInfo.findO1 || rightInfo.findO1; + boolean findO2 = head == o2 || leftInfo.findO2 || rightInfo.findO2; + Node ans = null; + if (leftInfo.ans != null) { + ans = leftInfo.ans; + } + if (rightInfo.ans != null) { + ans = rightInfo.ans; + } + if (ans == null) { + if (findO1 && findO2) { + ans = head; + } + } + return new Info(ans, findO1, findO2); + } + + // for test + public static Node generateRandomBST(int maxLevel, int maxValue) { + return generate(1, maxLevel, maxValue); + } + + // for test + public static Node generate(int level, int maxLevel, int maxValue) { + if (level > maxLevel || Math.random() < 0.5) { + return null; + } + Node head = new Node((int) (Math.random() * maxValue)); + head.left = generate(level + 1, maxLevel, maxValue); + head.right = generate(level + 1, maxLevel, maxValue); + return head; + } + + // for test + public static Node pickRandomOne(Node head) { + if (head == null) { + return null; + } + ArrayList arr = new ArrayList<>(); + fillPrelist(head, arr); + int randomIndex = (int) (Math.random() * arr.size()); + return arr.get(randomIndex); + } + + // for test + public static void fillPrelist(Node head, ArrayList arr) { + if (head == null) { + return; + } + arr.add(head); + fillPrelist(head.left, arr); + fillPrelist(head.right, arr); + } + + public static void main(String[] args) { + int maxLevel = 4; + int maxValue = 100; + int testTimes = 1000000; + for (int i = 0; i < testTimes; i++) { + Node head = generateRandomBST(maxLevel, maxValue); + Node o1 = pickRandomOne(head); + Node o2 = pickRandomOne(head); + if (lowestAncestor1(head, o1, o2) != lowestAncestor2(head, o1, o2)) { + System.out.println("Oops!"); + } + } + System.out.println("finish!"); + } + +} diff --git a/src/class08/Code08_MaxDistance.java b/src/class08/Code08_MaxDistance.java new file mode 100644 index 0000000..1fd6e95 --- /dev/null +++ b/src/class08/Code08_MaxDistance.java @@ -0,0 +1,151 @@ +package class08; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; + +public class Code08_MaxDistance { + + public static class Node { + public int value; + public Node left; + public Node right; + + public Node(int data) { + this.value = data; + } + } + + public static int maxDistance1(Node head) { + if (head == null) { + return 0; + } + ArrayList arr = getPrelist(head); + HashMap parentMap = getParentMap(head); + int max = 0; + for (int i = 0; i < arr.size(); i++) { + for (int j = i; j < arr.size(); j++) { + max = Math.max(max, distance(parentMap, arr.get(i), arr.get(j))); + } + } + return max; + } + + public static ArrayList getPrelist(Node head) { + ArrayList arr = new ArrayList<>(); + fillPrelist(head, arr); + return arr; + } + + public static void fillPrelist(Node head, ArrayList arr) { + if (head == null) { + return; + } + arr.add(head); + fillPrelist(head.left, arr); + fillPrelist(head.right, arr); + } + + public static HashMap getParentMap(Node head) { + HashMap map = new HashMap<>(); + map.put(head, null); + fillParentMap(head, map); + return map; + } + + public static void fillParentMap(Node head, HashMap parentMap) { + if (head.left != null) { + parentMap.put(head.left, head); + fillParentMap(head.left, parentMap); + } + if (head.right != null) { + parentMap.put(head.right, head); + fillParentMap(head.right, parentMap); + } + } + + public static int distance(HashMap parentMap, Node o1, Node o2) { + HashSet o1Set = new HashSet<>(); + Node cur = o1; + o1Set.add(cur); + while (parentMap.get(cur) != null) { + cur = parentMap.get(cur); + o1Set.add(cur); + } + cur = o2; + while (!o1Set.contains(cur)) { + cur = parentMap.get(cur); + } + Node lowestAncestor = cur; + cur = o1; + int distance1 = 1; + while (cur != lowestAncestor) { + cur = parentMap.get(cur); + distance1++; + } + cur = o2; + int distance2 = 1; + while (cur != lowestAncestor) { + cur = parentMap.get(cur); + distance2++; + } + return distance1 + distance2 - 1; + } + + public static int maxDistance2(Node head) { + return process(head).maxDistance; + } + + public static class Info { + public int maxDistance; + public int height; + + public Info(int dis, int h) { + maxDistance = dis; + height = h; + } + } + + public static Info process(Node X) { + if (X == null) { + return new Info(0, 0); + } + Info leftInfo = process(X.left); + Info rightInfo = process(X.right); + int height = Math.max(leftInfo.height, rightInfo.height) + 1; + int maxDistance = Math.max( + Math.max(leftInfo.maxDistance, rightInfo.maxDistance), + leftInfo.height + rightInfo.height + 1); + return new Info(maxDistance, height); + } + + // for test + public static Node generateRandomBST(int maxLevel, int maxValue) { + return generate(1, maxLevel, maxValue); + } + + // for test + public static Node generate(int level, int maxLevel, int maxValue) { + if (level > maxLevel || Math.random() < 0.5) { + return null; + } + Node head = new Node((int) (Math.random() * maxValue)); + head.left = generate(level + 1, maxLevel, maxValue); + head.right = generate(level + 1, maxLevel, maxValue); + return head; + } + + public static void main(String[] args) { + int maxLevel = 4; + int maxValue = 100; + int testTimes = 1000000; + for (int i = 0; i < testTimes; i++) { + Node head = generateRandomBST(maxLevel, maxValue); + if (maxDistance1(head) != maxDistance2(head)) { + System.out.println("Oops!"); + } + } + System.out.println("finish!"); + } + +} diff --git a/src/class08/Code09_MaxHappy.java b/src/class08/Code09_MaxHappy.java new file mode 100644 index 0000000..32294ea --- /dev/null +++ b/src/class08/Code09_MaxHappy.java @@ -0,0 +1,113 @@ +package class08; + +import java.util.ArrayList; +import java.util.List; + +public class Code09_MaxHappy { + + public static class Employee { + public int happy; + public List nexts; + + public Employee(int h) { + happy = h; + nexts = new ArrayList<>(); + } + + } + + public static int maxHappy1(Employee boss) { + if (boss == null) { + return 0; + } + return process1(boss, false); + } + + public static int process1(Employee cur, boolean up) { + if (up) { + int ans = 0; + for (Employee next : cur.nexts) { + ans += process1(next, false); + } + return ans; + } else { + int p1 = cur.happy; + int p2 = 0; + for (Employee next : cur.nexts) { + p1 += process1(next, true); + p2 += process1(next, false); + } + return Math.max(p1, p2); + } + } + + public static int maxHappy2(Employee boss) { + if (boss == null) { + return 0; + } + Info all = process2(boss); + return Math.max(all.yes, all.no); + } + + public static class Info { + public int yes; + public int no; + + public Info(int y, int n) { + yes = y; + no = n; + } + } + + public static Info process2(Employee x) { + if (x.nexts.isEmpty()) { + return new Info(x.happy, 0); + } + int yes = x.happy; + int no = 0; + for (Employee next : x.nexts) { + Info nextInfo = process2(next); + yes += nextInfo.no; + no += Math.max(nextInfo.yes, nextInfo.no); + } + return new Info(yes, no); + } + + // for test + public static Employee genarateBoss(int maxLevel, int maxNexts, int maxHappy) { + if (Math.random() < 0.02) { + return null; + } + Employee boss = new Employee((int) (Math.random() * (maxHappy + 1))); + genarateNexts(boss, 1, maxLevel, maxNexts, maxHappy); + return boss; + } + + // for test + public static void genarateNexts(Employee e, int level, int maxLevel, int maxNexts, int maxHappy) { + if (level > maxLevel) { + return; + } + int nextsSize = (int) (Math.random() * (maxNexts + 1)); + for (int i = 0; i < nextsSize; i++) { + Employee next = new Employee((int) (Math.random() * (maxHappy + 1))); + e.nexts.add(next); + genarateNexts(next, level + 1, maxLevel, maxNexts, maxHappy); + } + } + + public static void main(String[] args) { + int maxLevel = 4; + int maxNexts = 7; + int maxHappy = 100; + int testTimes = 100000; + for (int i = 0; i < testTimes; i++) { + Employee boss = genarateBoss(maxLevel, maxNexts, maxHappy); + if (maxHappy1(boss) != maxHappy2(boss)) { + System.out.println("Oops!"); + } + } + System.out.println("finish!"); + } + +} diff --git a/src/class09/Code01_LowestLexicography.java b/src/class09/Code01_LowestLexicography.java new file mode 100644 index 0000000..d3f7b57 --- /dev/null +++ b/src/class09/Code01_LowestLexicography.java @@ -0,0 +1,101 @@ +package class09; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashSet; + +public class Code01_LowestLexicography { + + public static String lowestString1(String[] strs) { + if (strs == null || strs.length == 0) { + return ""; + } + ArrayList all = new ArrayList<>(); + HashSet use = new HashSet<>(); + process(strs, use, "", all); + String lowest = all.get(0); + for (int i = 1; i < all.size(); i++) { + if (all.get(i).compareTo(lowest) < 0) { + lowest = all.get(i); + } + } + return lowest; + } + + public static void process(String[] strs, HashSet use, String path, ArrayList all) { + if (use.size() == strs.length) { + all.add(path); + } else { + for (int i = 0; i < strs.length; i++) { + if (!use.contains(i)) { + use.add(i); + process(strs, use, path + strs[i], all); + use.remove(i); + } + } + } + } + + public static class MyComparator implements Comparator { + @Override + public int compare(String a, String b) { + return (a + b).compareTo(b + a); + } + } + + public static String lowestString2(String[] strs) { + if (strs == null || strs.length == 0) { + return ""; + } + Arrays.sort(strs, new MyComparator()); + String res = ""; + for (int i = 0; i < strs.length; i++) { + res += strs[i]; + } + return res; + } + + // for test + public static String generateRandomString(int strLen) { + char[] ans = new char[(int) (Math.random() * strLen) + 1]; + for (int i = 0; i < ans.length; i++) { + int value = (int) (Math.random() * 5); + ans[i] = (char) (97 + value); + } + return String.valueOf(ans); + } + + // for test + public static String[] generateRandomStringArray(int arrLen, int strLen) { + String[] ans = new String[(int) (Math.random() * arrLen) + 1]; + for (int i = 0; i < ans.length; i++) { + ans[i] = generateRandomString(strLen); + } + return ans; + } + + // for test + public static String[] copyStringArray(String[] arr) { + String[] ans = new String[arr.length]; + for (int i = 0; i < ans.length; i++) { + ans[i] = String.valueOf(arr[i]); + } + return ans; + } + + public static void main(String[] args) { + int arrLen = 6; + int strLen = 5; + int testTimes = 100000; + for (int i = 0; i < testTimes; i++) { + String[] arr1 = generateRandomStringArray(arrLen, strLen); + String[] arr2 = copyStringArray(arr1); + if (!lowestString1(arr1).equals(lowestString2(arr2))) { + System.out.println("Oops!"); + } + } + System.out.println("finish!"); + } + +} diff --git a/src/class09/Code02_Light.java b/src/class09/Code02_Light.java new file mode 100644 index 0000000..b892240 --- /dev/null +++ b/src/class09/Code02_Light.java @@ -0,0 +1,81 @@ +package class09; + +import java.util.HashSet; + +public class Code02_Light { + + public static int minLight1(String road) { + if (road == null || road.length() == 0) { + return 0; + } + return process(road.toCharArray(), 0, new HashSet<>()); + } + + public static int process(char[] str, int index, HashSet lights) { + if (index == str.length) { + for (int i = 0; i < str.length; i++) { + if (str[i] != 'X') { + if (!lights.contains(i - 1) && !lights.contains(i) && !lights.contains(i + 1)) { + return Integer.MAX_VALUE; + } + } + } + return lights.size(); + } else { + int no = process(str, index + 1, lights); + int yes = Integer.MAX_VALUE; + if (str[index] == '.') { + lights.add(index); + yes = process(str, index + 1, lights); + lights.remove(index); + } + return Math.min(no, yes); + } + } + + public static int minLight2(String road) { + char[] str = road.toCharArray(); + int index = 0; + int light = 0; + while (index < str.length) { + if (str[index] == 'X') { + index++; + } else { + light++; + if (index + 1 == str.length) { + break; + } else { + if (str[index + 1] == 'X') { + index = index + 2; + } else { + index = index + 3; + } + } + } + } + return light; + } + + // for test + public static String randomString(int len) { + char[] res = new char[(int) (Math.random() * len) + 1]; + for (int i = 0; i < res.length; i++) { + res[i] = Math.random() < 0.5 ? 'X' : '.'; + } + return String.valueOf(res); + } + + public static void main(String[] args) { + int len = 20; + int testTime = 100000; + for (int i = 0; i < testTime; i++) { + String test = randomString(len); + int ans1 = minLight1(test); + int ans2 = minLight2(test); + if (ans1 != ans2) { + System.out.println("oops!"); + } + } + System.out.println("finish!"); + } +} diff --git a/src/class09/Code03_LessMoneySplitGold.java b/src/class09/Code03_LessMoneySplitGold.java new file mode 100644 index 0000000..3838941 --- /dev/null +++ b/src/class09/Code03_LessMoneySplitGold.java @@ -0,0 +1,76 @@ +package class09; + +import java.util.PriorityQueue; + +public class Code03_LessMoneySplitGold { + + public static int lessMoney1(int[] arr) { + if (arr == null || arr.length == 0) { + return 0; + } + return process(arr, 0); + } + + public static int process(int[] arr, int pre) { + if (arr.length == 1) { + return pre; + } + int ans = Integer.MAX_VALUE; + for (int i = 0; i < arr.length; i++) { + for (int j = i + 1; j < arr.length; j++) { + ans = Math.min(ans, process(copyAndMergeTwo(arr, i, j), pre + arr[i] + arr[j])); + } + } + return ans; + } + + public static int[] copyAndMergeTwo(int[] arr, int i, int j) { + int[] ans = new int[arr.length - 1]; + int ansi = 0; + for (int arri = 0; arri < arr.length; arri++) { + if (arri != i && arri != j) { + ans[ansi++] = arr[arri]; + } + } + ans[ansi] = arr[i] + arr[j]; + return ans; + } + + public static int lessMoney2(int[] arr) { + PriorityQueue pQ = new PriorityQueue<>(); + for (int i = 0; i < arr.length; i++) { + pQ.add(arr[i]); + } + int sum = 0; + int cur = 0; + while (pQ.size() > 1) { + cur = pQ.poll() + pQ.poll(); + sum += cur; + pQ.add(cur); + } + return sum; + } + + // for test + public static int[] generateRandomArray(int maxSize, int maxValue) { + int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (int) (Math.random() * (maxValue + 1)); + } + return arr; + } + + public static void main(String[] args) { + int testTime = 100000; + int maxSize = 6; + int maxValue = 1000; + for (int i = 0; i < testTime; i++) { + int[] arr = generateRandomArray(maxSize, maxValue); + if (lessMoney1(arr) != lessMoney2(arr)) { + System.out.println("Oops!"); + } + } + System.out.println("finish!"); + } + +} diff --git a/src/class09/Code04_BestArrange.java b/src/class09/Code04_BestArrange.java new file mode 100644 index 0000000..2b5711a --- /dev/null +++ b/src/class09/Code04_BestArrange.java @@ -0,0 +1,100 @@ +package class09; + +import java.util.Arrays; +import java.util.Comparator; + +public class Code04_BestArrange { + + public static class Program { + public int start; + public int end; + + public Program(int start, int end) { + this.start = start; + this.end = end; + } + } + + public static int bestArrange1(Program[] programs) { + if (programs == null || programs.length == 0) { + return 0; + } + return process(programs, 0, 0); + } + + public static int process(Program[] programs, int done, int timeLine) { + if (programs.length == 0) { + return done; + } + int max = done; + for (int i = 0; i < programs.length; i++) { + if (programs[i].start >= timeLine) { + Program[] next = copyButExcept(programs, i); + max = Math.max(max, process(next, done + 1, programs[i].end)); + } + } + return max; + } + + public static Program[] copyButExcept(Program[] programs, int i) { + Program[] ans = new Program[programs.length - 1]; + int index = 0; + for (int k = 0; k < programs.length; k++) { + if (k != i) { + ans[index++] = programs[k]; + } + } + return ans; + } + + public static int bestArrange2(Program[] programs) { + Arrays.sort(programs, new ProgramComparator()); + int timeLine = 0; + int result = 0; + for (int i = 0; i < programs.length; i++) { + if (timeLine <= programs[i].start) { + result++; + timeLine = programs[i].end; + } + } + return result; + } + + public static class ProgramComparator implements Comparator { + + @Override + public int compare(Program o1, Program o2) { + return o1.end - o2.end; + } + + } + + // for test + public static Program[] generatePrograms(int programSize, int timeMax) { + Program[] ans = new Program[(int) (Math.random() * (programSize + 1))]; + for (int i = 0; i < ans.length; i++) { + int r1 = (int) (Math.random() * (timeMax + 1)); + int r2 = (int) (Math.random() * (timeMax + 1)); + if (r1 == r2) { + ans[i] = new Program(r1, r1 + 1); + } else { + ans[i] = new Program(Math.min(r1, r2), Math.max(r1, r2)); + } + } + return ans; + } + + public static void main(String[] args) { + int programSize = 12; + int timeMax = 20; + int timeTimes = 1000000; + for (int i = 0; i < timeTimes; i++) { + Program[] programs = generatePrograms(programSize, timeMax); + if (bestArrange1(programs) != bestArrange2(programs)) { + System.out.println("Oops!"); + } + } + System.out.println("finish!"); + } + +} diff --git a/src/class09/Code05_IPO.java b/src/class09/Code05_IPO.java new file mode 100644 index 0000000..bde9d89 --- /dev/null +++ b/src/class09/Code05_IPO.java @@ -0,0 +1,54 @@ +package class09; + +import java.util.Comparator; +import java.util.PriorityQueue; + +public class Code05_IPO { + + public static int findMaximizedCapital(int K, int W, int[] Profits, int[] Capital) { + PriorityQueue minCostQ = new PriorityQueue<>(new MinCostComparator()); + PriorityQueue maxProfitQ = new PriorityQueue<>(new MaxProfitComparator()); + for (int i = 0; i < Profits.length; i++) { + minCostQ.add(new Program(Profits[i], Capital[i])); + } + for (int i = 0; i < K; i++) { + while (!minCostQ.isEmpty() && minCostQ.peek().c <= W) { + maxProfitQ.add(minCostQ.poll()); + } + if (maxProfitQ.isEmpty()) { + return W; + } + W += maxProfitQ.poll().p; + } + return W; + } + + public static class Program { + public int p; + public int c; + + public Program(int p, int c) { + this.p = p; + this.c = c; + } + } + + public static class MinCostComparator implements Comparator { + + @Override + public int compare(Program o1, Program o2) { + return o1.c - o2.c; + } + + } + + public static class MaxProfitComparator implements Comparator { + + @Override + public int compare(Program o1, Program o2) { + return o2.p - o1.p; + } + + } + +} diff --git a/src/class10/Code01_UnionFind.java b/src/class10/Code01_UnionFind.java new file mode 100644 index 0000000..3421427 --- /dev/null +++ b/src/class10/Code01_UnionFind.java @@ -0,0 +1,73 @@ +package class10; + +import java.util.HashMap; +import java.util.List; +import java.util.Stack; + +public class Code01_UnionFind { + + public static class Node { + V value; + + public Node(V v) { + value = v; + } + } + + public static class UnionSet { + public HashMap> nodes; + public HashMap, Node> parents; + public HashMap, Integer> sizeMap; + + public UnionSet(List values) { + for (V value : values) { + Node node = new Node<>(value); + nodes.put(value, node); + parents.put(node, node); + sizeMap.put(node, 1); + } + } + + public Node findFather(Node cur) { + Stack> path = new Stack<>(); + while (cur != parents.get(cur)) { + path.push(cur); + cur = parents.get(cur); + } + // cur头节点 + while (!path.isEmpty()) { + parents.put(path.pop(), cur); + } + return cur; + } + + public boolean isSameSet(V a, V b) { + if (!nodes.containsKey(a) || !nodes.containsKey(b)) { + return false; + } + return findFather(nodes.get(a)) == findFather(nodes.get(b)); + } + + public void union(V a, V b) { + if (!nodes.containsKey(a) || !nodes.containsKey(b)) { + return; + } + Node aHead = findFather(nodes.get(a)); + Node bHead = findFather(nodes.get(b)); + if (aHead != bHead) { + int aSetSize = sizeMap.get(aHead); + int bSetSize = sizeMap.get(bHead); + if (aSetSize >= bSetSize) { + parents.put(bHead, aHead); + sizeMap.put(aHead, aSetSize + bSetSize); + sizeMap.remove(bHead); + } else { + parents.put(aHead, bHead); + sizeMap.put(bHead, aSetSize + bSetSize); + sizeMap.remove(aHead); + } + } + } + } + +} diff --git a/src/class10/Code02_BFS.java b/src/class10/Code02_BFS.java new file mode 100644 index 0000000..cb87d5e --- /dev/null +++ b/src/class10/Code02_BFS.java @@ -0,0 +1,30 @@ +package class10; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Queue; + +public class Code02_BFS { + + // 从node出发,进行宽度优先遍历 + public static void bfs(Node node) { + if (node == null) { + return; + } + Queue queue = new LinkedList<>(); + HashSet set = new HashSet<>(); + queue.add(node); + set.add(node); + while (!queue.isEmpty()) { + Node cur = queue.poll(); + System.out.println(cur.value); + for (Node next : cur.nexts) { + if (!set.contains(next)) { + set.add(next); + queue.add(next); + } + } + } + } + +} diff --git a/src/class10/Code02_DFS.java b/src/class10/Code02_DFS.java new file mode 100644 index 0000000..6ecc3cf --- /dev/null +++ b/src/class10/Code02_DFS.java @@ -0,0 +1,31 @@ +package class10; + +import java.util.HashSet; +import java.util.Stack; + +public class Code02_DFS { + + public static void dfs(Node node) { + if (node == null) { + return; + } + Stack stack = new Stack<>(); + HashSet set = new HashSet<>(); + stack.add(node); + set.add(node); + System.out.println(node.value); + while (!stack.isEmpty()) { + Node cur = stack.pop(); + for (Node next : cur.nexts) { + if (!set.contains(next)) { + stack.push(cur); + stack.push(next); + set.add(next); + System.out.println(next.value); + break; + } + } + } + } + +} diff --git a/src/class10/Code03_TopologySort.java b/src/class10/Code03_TopologySort.java new file mode 100644 index 0000000..51ba075 --- /dev/null +++ b/src/class10/Code03_TopologySort.java @@ -0,0 +1,38 @@ +package class10; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +public class Code03_TopologySort { + + // directed graph and no loop + public static List sortedTopology(Graph graph) { + // key:某一个node + // value:剩余的入度 + HashMap inMap = new HashMap<>(); + // 入度为0的点,才能进这个队列 + Queue zeroInQueue = new LinkedList<>(); + for (Node node : graph.nodes.values()) { + inMap.put(node, node.in); + if (node.in == 0) { + zeroInQueue.add(node); + } + } + // 拓扑排序的结果,依次加入result + List result = new ArrayList<>(); + while (!zeroInQueue.isEmpty()) { + Node cur = zeroInQueue.poll(); + result.add(cur); + for (Node next : cur.nexts) { + inMap.put(next, inMap.get(next) - 1); + if (inMap.get(next) == 0) { + zeroInQueue.add(next); + } + } + } + return result; + } +} diff --git a/src/class10/Code04_Kruskal.java b/src/class10/Code04_Kruskal.java new file mode 100644 index 0000000..caa1da0 --- /dev/null +++ b/src/class10/Code04_Kruskal.java @@ -0,0 +1,142 @@ +package class10; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.PriorityQueue; +import java.util.Set; +import java.util.Stack; + +//undirected graph only +public class Code04_Kruskal { + + public static class MySets{ + public HashMap> setMap; + public MySets(List nodes) { + for(Node cur : nodes) { + List set = new ArrayList(); + set.add(cur); + setMap.put(cur, set); + } + } + + + public boolean isSameSet(Node from, Node to) { + List fromSet = setMap.get(from); + List toSet = setMap.get(to); + return fromSet == toSet; + } + + + public void union(Node from, Node to) { + List fromSet = setMap.get(from); + List toSet = setMap.get(to); + for(Node toNode : toSet) { + fromSet.add(toNode); + setMap.put(toNode, fromSet); + } + } + } + + + + + + + + + + + + + + // Union-Find Set + public static class UnionFind { + // key 某一个节点, value key节点往上的节点 + private HashMap fatherMap; + // key 某一个集合的代表节点, value key所在集合的节点个数 + private HashMap sizeMap; + + public UnionFind() { + fatherMap = new HashMap(); + sizeMap = new HashMap(); + } + + public void makeSets(Collection nodes) { + fatherMap.clear(); + sizeMap.clear(); + for (Node node : nodes) { + fatherMap.put(node, node); + sizeMap.put(node, 1); + } + } + + private Node findFather(Node n) { + Stack path = new Stack<>(); + while(n != fatherMap.get(n)) { + path.add(n); + n = fatherMap.get(n); + } + while(!path.isEmpty()) { + fatherMap.put(path.pop(), n); + } + return n; + } + + public boolean isSameSet(Node a, Node b) { + return findFather(a) == findFather(b); + } + + public void union(Node a, Node b) { + if (a == null || b == null) { + return; + } + Node aDai = findFather(a); + Node bDai = findFather(b); + if (aDai != bDai) { + int aSetSize = sizeMap.get(aDai); + int bSetSize = sizeMap.get(bDai); + if (aSetSize <= bSetSize) { + fatherMap.put(aDai, bDai); + sizeMap.put(bDai, aSetSize + bSetSize); + sizeMap.remove(aDai); + } else { + fatherMap.put(bDai, aDai); + sizeMap.put(aDai, aSetSize + bSetSize); + sizeMap.remove(bDai); + } + } + } + } + + + public static class EdgeComparator implements Comparator { + + @Override + public int compare(Edge o1, Edge o2) { + return o1.weight - o2.weight; + } + + } + + public static Set kruskalMST(Graph graph) { + UnionFind unionFind = new UnionFind(); + unionFind.makeSets(graph.nodes.values()); + PriorityQueue priorityQueue = new PriorityQueue<>(new EdgeComparator()); + for (Edge edge : graph.edges) { // M 条边 + priorityQueue.add(edge); // O(logM) + } + Set result = new HashSet<>(); + while (!priorityQueue.isEmpty()) { // M 条边 + Edge edge = priorityQueue.poll(); // O(logM) + if (!unionFind.isSameSet(edge.from, edge.to)) { // O(1) + result.add(edge); + unionFind.union(edge.from, edge.to); + } + } + return result; + } +} diff --git a/src/class10/Code05_Prim.java b/src/class10/Code05_Prim.java new file mode 100644 index 0000000..def87d6 --- /dev/null +++ b/src/class10/Code05_Prim.java @@ -0,0 +1,89 @@ +package class10; + +import java.util.Comparator; +import java.util.HashSet; +import java.util.PriorityQueue; +import java.util.Set; + +// undirected graph only +public class Code05_Prim { + + public static class EdgeComparator implements Comparator { + + @Override + public int compare(Edge o1, Edge o2) { + return o1.weight - o2.weight; + } + + } + + public static Set primMST(Graph graph) { + // 解锁的边进入小根堆 + PriorityQueue priorityQueue = new PriorityQueue<>( + new EdgeComparator()); + HashSet set = new HashSet<>(); + Set result = new HashSet<>(); // 依次挑选的的边在result里 + for (Node node : graph.nodes.values()) { // 随便挑了一个点 + // node 是开始点 + if (!set.contains(node)) { + set.add(node); + for (Edge edge : node.edges) { // 由一个点,解锁所有相连的边 + priorityQueue.add(edge); + } + while (!priorityQueue.isEmpty()) { + Edge edge = priorityQueue.poll(); // 弹出解锁的边中,最小的边 + Node toNode = edge.to; // 可能的一个新的点 + if (!set.contains(toNode)) { // 不含有的时候,就是新的点 + set.add(toNode); + result.add(edge); + for (Edge nextEdge : toNode.edges) { + priorityQueue.add(nextEdge); + } + } + } + } + //break; + } + return result; + } + + // 请保证graph是连通图 + // graph[i][j]表示点i到点j的距离,如果是系统最大值代表无路 + // 返回值是最小连通图的路径之和 + public static int prim(int[][] graph) { + int size = graph.length; + int[] distances = new int[size]; + boolean[] visit = new boolean[size]; + visit[0] = true; + for (int i = 0; i < size; i++) { + distances[i] = graph[0][i]; + } + int sum = 0; + for (int i = 1; i < size; i++) { + int minPath = Integer.MAX_VALUE; + int minIndex = -1; + for (int j = 0; j < size; j++) { + if (!visit[j] && distances[j] < minPath) { + minPath = distances[j]; + minIndex = j; + } + } + if (minIndex == -1) { + return sum; + } + visit[minIndex] = true; + sum += minPath; + for (int j = 0; j < size; j++) { + if (!visit[j] && distances[j] > graph[minIndex][j]) { + distances[j] = graph[minIndex][j]; + } + } + } + return sum; + } + + public static void main(String[] args) { + System.out.println("hello world!"); + } + +} diff --git a/src/class10/Code06_Dijkstra.java b/src/class10/Code06_Dijkstra.java new file mode 100644 index 0000000..ed66369 --- /dev/null +++ b/src/class10/Code06_Dijkstra.java @@ -0,0 +1,163 @@ +package class10; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map.Entry; + +// no negative weight +public class Code06_Dijkstra { + + public static HashMap dijkstra1(Node head) { + // 从head出发到所有点的最小距离 + // key : 从head出发到达key + // value : 从head出发到达key的最小距离 + // 如果在表中,没有T的记录,含义是从head出发到T这个点的距离为正无穷 + HashMap distanceMap = new HashMap<>(); + distanceMap.put(head, 0); + // 已经求过距离的节点,存在selectedNodes中,以后再也不碰 + HashSet selectedNodes = new HashSet<>(); + Node minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes); + while (minNode != null) { + int distance = distanceMap.get(minNode); + for (Edge edge : minNode.edges) { + Node toNode = edge.to; + if (!distanceMap.containsKey(toNode)) { + distanceMap.put(toNode, distance + edge.weight); + } else { + distanceMap.put(edge.to, Math.min(distanceMap.get(toNode), distance + edge.weight)); + } + } + selectedNodes.add(minNode); + minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes); + } + return distanceMap; + } + + public static Node getMinDistanceAndUnselectedNode(HashMap distanceMap, HashSet touchedNodes) { + Node minNode = null; + int minDistance = Integer.MAX_VALUE; + for (Entry entry : distanceMap.entrySet()) { + Node node = entry.getKey(); + int distance = entry.getValue(); + if (!touchedNodes.contains(node) && distance < minDistance) { + minNode = node; + minDistance = distance; + } + } + return minNode; + } + + public static class NodeRecord { + public Node node; + public int distance; + + public NodeRecord(Node node, int distance) { + this.node = node; + this.distance = distance; + } + } + + public static class NodeHeap { + private Node[] nodes; // 实际的堆结构 + // key 某一个node, value 上面数组中的位置 + private HashMap heapIndexMap; + // key 某一个节点, value 从源节点出发到该节点的目前最小距离 + private HashMap distanceMap; + private int size; // 堆上有多少个点 + + public NodeHeap(int size) { + nodes = new Node[size]; + heapIndexMap = new HashMap<>(); + distanceMap = new HashMap<>(); + size = 0; + } + + public boolean isEmpty() { + return size == 0; + } + + // 有一个点叫node,现在发现了一个从源节点出发到达node的距离为distance + // 判断要不要更新,如果需要的话,就更新 + public void addOrUpdateOrIgnore(Node node, int distance) { + if (inHeap(node)) { + distanceMap.put(node, Math.min(distanceMap.get(node), distance)); + insertHeapify(node, heapIndexMap.get(node)); + } + if (!isEntered(node)) { + nodes[size] = node; + heapIndexMap.put(node, size); + distanceMap.put(node, distance); + insertHeapify(node, size++); + } + } + + public NodeRecord pop() { + NodeRecord nodeRecord = new NodeRecord(nodes[0], distanceMap.get(nodes[0])); + swap(0, size - 1); + heapIndexMap.put(nodes[size - 1], -1); + distanceMap.remove(nodes[size - 1]); + // free C++同学还要把原本堆顶节点析构,对java同学不必 + nodes[size - 1] = null; + heapify(0, --size); + return nodeRecord; + } + + private void insertHeapify(Node node, int index) { + while (distanceMap.get(nodes[index]) < distanceMap.get(nodes[(index - 1) / 2])) { + swap(index, (index - 1) / 2); + index = (index - 1) / 2; + } + } + + private void heapify(int index, int size) { + int left = index * 2 + 1; + while (left < size) { + int smallest = left + 1 < size && distanceMap.get(nodes[left + 1]) < distanceMap.get(nodes[left]) + ? left + 1 + : left; + smallest = distanceMap.get(nodes[smallest]) < distanceMap.get(nodes[index]) ? smallest : index; + if (smallest == index) { + break; + } + swap(smallest, index); + index = smallest; + left = index * 2 + 1; + } + } + + private boolean isEntered(Node node) { + return heapIndexMap.containsKey(node); + } + + private boolean inHeap(Node node) { + return isEntered(node) && heapIndexMap.get(node) != -1; + } + + private void swap(int index1, int index2) { + heapIndexMap.put(nodes[index1], index2); + heapIndexMap.put(nodes[index2], index1); + Node tmp = nodes[index1]; + nodes[index1] = nodes[index2]; + nodes[index2] = tmp; + } + } + + // 改进后的dijkstra算法 + // 从head出发,所有head能到达的节点,生成到达每个节点的最小路径记录并返回 + public static HashMap dijkstra2(Node head, int size) { + NodeHeap nodeHeap = new NodeHeap(size); + nodeHeap.addOrUpdateOrIgnore(head, 0); + HashMap result = new HashMap<>(); + while (!nodeHeap.isEmpty()) { + NodeRecord record = nodeHeap.pop(); + Node cur = record.node; + int distance = record.distance; + for (Edge edge : cur.edges) { + nodeHeap.addOrUpdateOrIgnore(edge.to, edge.weight + distance); + } + result.put(cur, distance); + } + return result; + } + +} diff --git a/src/class10/Edge.java b/src/class10/Edge.java new file mode 100644 index 0000000..8786552 --- /dev/null +++ b/src/class10/Edge.java @@ -0,0 +1,14 @@ +package class10; + +public class Edge { + public int weight; + public Node from; + public Node to; + + public Edge(int weight, Node from, Node to) { + this.weight = weight; + this.from = from; + this.to = to; + } + +} diff --git a/src/class10/Graph.java b/src/class10/Graph.java new file mode 100644 index 0000000..484504f --- /dev/null +++ b/src/class10/Graph.java @@ -0,0 +1,14 @@ +package class10; + +import java.util.HashMap; +import java.util.HashSet; + +public class Graph { + public HashMap nodes; + public HashSet edges; + + public Graph() { + nodes = new HashMap<>(); + edges = new HashSet<>(); + } +} diff --git a/src/class10/GraphGenerator.java b/src/class10/GraphGenerator.java new file mode 100644 index 0000000..dc6a0b8 --- /dev/null +++ b/src/class10/GraphGenerator.java @@ -0,0 +1,32 @@ +package class10; + +public class GraphGenerator { + + // matrix 所有的边 + // N*3 的矩阵 + // [weight, from节点上面的值,to节点上面的值] + public static Graph createGraph(Integer[][] matrix) { + Graph graph = new Graph(); + for (int i = 0; i < matrix.length; i++) { // matrix[0][0], matrix[0][1] matrix[0][2] + Integer from = matrix[i][0]; + Integer to = matrix[i][1]; + Integer weight = matrix[i][2]; + if (!graph.nodes.containsKey(from)) { + graph.nodes.put(from, new Node(from)); + } + if (!graph.nodes.containsKey(to)) { + graph.nodes.put(to, new Node(to)); + } + Node fromNode = graph.nodes.get(from); + Node toNode = graph.nodes.get(to); + Edge newEdge = new Edge(weight, fromNode, toNode); + fromNode.nexts.add(toNode); + fromNode.out++; + toNode.in++; + fromNode.edges.add(newEdge); + graph.edges.add(newEdge); + } + return graph; + } + +} diff --git a/src/class10/Node.java b/src/class10/Node.java new file mode 100644 index 0000000..f56e977 --- /dev/null +++ b/src/class10/Node.java @@ -0,0 +1,19 @@ +package class10; + +import java.util.ArrayList; + +public class Node { + public int value; + public int in; + public int out; + public ArrayList nexts; + public ArrayList edges; + + public Node(int value) { + this.value = value; + in = 0; + out = 0; + nexts = new ArrayList<>(); + edges = new ArrayList<>(); + } +} diff --git a/src/class11/Code01_Hanoi.java b/src/class11/Code01_Hanoi.java new file mode 100644 index 0000000..b840f8b --- /dev/null +++ b/src/class11/Code01_Hanoi.java @@ -0,0 +1,94 @@ +package class11; + +public class Code01_Hanoi { + + public static void hanoi1(int n) { + leftToRight(n); + } + + public static void leftToRight(int n) { + if (n == 1) { + System.out.println("Move 1 from left to right"); + return; + } + leftToMid(n - 1); + System.out.println("Move " + n + " from left to right"); + midToRight(n - 1); + } + + public static void leftToMid(int n) { + if (n == 1) { + System.out.println("Move 1 from left to mid"); + return; + } + leftToRight(n - 1); + System.out.println("Move " + n + " from left to mid"); + rightToMid(n - 1); + } + + public static void rightToMid(int n) { + if (n == 1) { + System.out.println("Move 1 from right to mid"); + return; + } + rightToLeft(n - 1); + System.out.println("Move " + n + " from right to mid"); + leftToMid(n - 1); + } + + public static void midToRight(int n) { + if (n == 1) { + System.out.println("Move 1 from mid to right"); + return; + } + midToLeft(n - 1); + System.out.println("Move " + n + " from mid to right"); + leftToRight(n - 1); + } + + public static void midToLeft(int n) { + if (n == 1) { + System.out.println("Move 1 from mid to left"); + return; + } + midToRight(n - 1); + System.out.println("Move " + n + " from mid to left"); + rightToLeft(n - 1); + } + + public static void rightToLeft(int n) { + if (n == 1) { + System.out.println("Move 1 from right to left"); + return; + } + rightToMid(n - 1); + System.out.println("Move " + n + " from right to left"); + midToLeft(n - 1); + } + + public static void hanoi2(int n) { + if (n > 0) { + func(n, "left", "right", "mid"); + } + } + + // 1~i 圆盘 目标是from -> to, other是另外一个 + public static void func(int N, String from, String to, String other) { + if (N == 1) { // base + System.out.println("Move 1 from " + from + " to " + to); + } else { + func(N - 1, from, other, to); + System.out.println("Move " + N + " from " + from + " to " + to); + func(N - 1, other, to, from); + } + } + + public static void main(String[] args) { + int n = 3; + hanoi1(n); + System.out.println("============"); + hanoi2(n); + System.out.println("============"); + } + +} diff --git a/src/class11/Code02_PrintAllSubsquences.java b/src/class11/Code02_PrintAllSubsquences.java new file mode 100644 index 0000000..fd5e896 --- /dev/null +++ b/src/class11/Code02_PrintAllSubsquences.java @@ -0,0 +1,67 @@ +package class11; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +public class Code02_PrintAllSubsquences { + + public static List subs(String s) { + char[] str = s.toCharArray(); + String path = ""; + List ans = new ArrayList<>(); + process1(str, 0, ans, path); + return ans; + } + + public static void process1(char[] str, int index, List ans, String path) { + if (index == str.length) { + ans.add(path); + return; + } + String no = path; + process1(str, index + 1, ans, no); + String yes = path + String.valueOf(str[index]); + process1(str, index + 1, ans, yes); + } + + public static List subsNoRepeat(String s) { + char[] str = s.toCharArray(); + String path = ""; + HashSet set = new HashSet<>(); + process2(str, 0, set, path); + List ans = new ArrayList<>(); + for (String cur : set) { + ans.add(cur); + } + return ans; + } + + public static void process2(char[] str, int index, HashSet set, String path) { + if (index == str.length) { + set.add(path); + return; + } + String no = path; + process2(str, index + 1, set, no); + String yes = path + String.valueOf(str[index]); + process2(str, index + 1, set, yes); + } + + public static void main(String[] args) { + String test = "aacc"; + List ans1 = subs(test); + List ans2 = subsNoRepeat(test); + + for (String str : ans1) { + System.out.println(str); + } + System.out.println("================="); + for (String str : ans2) { + System.out.println(str); + } + System.out.println("================="); + + } + +} diff --git a/src/class11/Code03_PrintAllPermutations.java b/src/class11/Code03_PrintAllPermutations.java new file mode 100644 index 0000000..7a8a589 --- /dev/null +++ b/src/class11/Code03_PrintAllPermutations.java @@ -0,0 +1,74 @@ +package class11; + +import java.util.ArrayList; +import java.util.List; + +public class Code03_PrintAllPermutations { + + public static ArrayList permutation(String str) { + ArrayList res = new ArrayList<>(); + if (str == null || str.length() == 0) { + return res; + } + char[] chs = str.toCharArray(); + process(chs, 0, res); + return res; + } + + public static void process(char[] str, int i, ArrayList res) { + if (i == str.length) { + res.add(String.valueOf(str)); + } + for (int j = i; j < str.length; j++) { + swap(str, i, j); + process(str, i + 1, res); + swap(str, i, j); + } + } + + public static ArrayList permutationNoRepeat(String str) { + ArrayList res = new ArrayList<>(); + if (str == null || str.length() == 0) { + return res; + } + char[] chs = str.toCharArray(); + process2(chs, 0, res); + return res; + } + + public static void process2(char[] str, int i, ArrayList res) { + if (i == str.length) { + res.add(String.valueOf(str)); + } + boolean[] visit = new boolean[26]; // visit[0 1 .. 25] + for (int j = i; j < str.length; j++) { + if (!visit[str[j] - 'a']) { + visit[str[j] - 'a'] = true; + swap(str, i, j); + process2(str, i + 1, res); + swap(str, i, j); + } + } + } + + public static void swap(char[] chs, int i, int j) { + char tmp = chs[i]; + chs[i] = chs[j]; + chs[j] = tmp; + } + + public static void main(String[] args) { + String s = "aac"; + List ans1 = permutation(s); + for (String str : ans1) { + System.out.println(str); + } + System.out.println("======="); + List ans2 = permutationNoRepeat(s); + for (String str : ans2) { + System.out.println(str); + } + + } + +} diff --git a/src/class11/Code04_ReverseStackUsingRecursive.java b/src/class11/Code04_ReverseStackUsingRecursive.java new file mode 100644 index 0000000..8e9134c --- /dev/null +++ b/src/class11/Code04_ReverseStackUsingRecursive.java @@ -0,0 +1,41 @@ +package class11; + +import java.util.Stack; + +public class Code04_ReverseStackUsingRecursive { + + public static void reverse(Stack stack) { + if (stack.isEmpty()) { + return; + } + int i = f(stack); + reverse(stack); + stack.push(i); + } + + public static int f(Stack stack) { + int result = stack.pop(); + if (stack.isEmpty()) { + return result; + } else { + int last = f(stack); + stack.push(result); + return last; + } + } + + public static void main(String[] args) { + Stack test = new Stack(); + test.push(1); + test.push(2); + test.push(3); + test.push(4); + test.push(5); + reverse(test); + while (!test.isEmpty()) { + System.out.println(test.pop()); + } + + } + +} diff --git a/src/class11/Code06_ConvertToLetterString.java b/src/class11/Code06_ConvertToLetterString.java new file mode 100644 index 0000000..1a21ffa --- /dev/null +++ b/src/class11/Code06_ConvertToLetterString.java @@ -0,0 +1,74 @@ +package class11; + +public class Code06_ConvertToLetterString { + + public static int number(String str) { + if (str == null || str.length() == 0) { + return 0; + } + return process(str.toCharArray(), 0); + } + + // i之前的位置,如何转化已经做过决定了, 不用再关心 + // i... 有多少种转化的结果 + public static int process(char[] str, int i) { + if (i == str.length) { // base case + return 1; + } + // i没有到终止位置 + if (str[i] == '0') { + return 0; + } + // str[i]字符不是‘0’ + if (str[i] == '1') { + int res = process(str, i + 1); // i自己作为单独的部分,后续有多少种方法 + if (i + 1 < str.length) { + res += process(str, i + 2); // (i和i+1)作为单独的部分,后续有多少种方法 + } + return res; + } + if (str[i] == '2') { + int res = process(str, i + 1); // i自己作为单独的部分,后续有多少种方法 + // (i和i+1)作为单独的部分并且没有超过26,后续有多少种方法 + if (i + 1 < str.length && (str[i + 1] >= '0' && str[i + 1] <= '6')) { + res += process(str, i + 2); // (i和i+1)作为单独的部分,后续有多少种方法 + } + return res; + } + // str[i] == '3' ~ '9' + return process(str, i + 1); + } + + public static int dpWays(String s) { + if (s == null || s.length() == 0) { + return 0; + } + char[] str = s.toCharArray(); + int N = str.length; + int[] dp = new int[N + 1]; + dp[N] = 1; + for (int i = N - 1; i >= 0; i--) { + if (str[i] == '0') { + dp[i] = 0; + } else if (str[i] == '1') { + dp[i] = dp[i + 1]; + if (i + 1 < N) { + dp[i] += dp[i + 2]; + } + } else if (str[i] == '2') { + dp[i] = dp[i + 1]; + if (i + 1 < str.length && (str[i + 1] >= '0' && str[i + 1] <= '6')) { + dp[i] += dp[i + 2]; + } + } else { + dp[i] = dp[i + 1]; + } + } + return dp[0]; + } + + public static void main(String[] args) { + System.out.println(number("11111")); + } + +} diff --git a/src/class11/Code07_Knapsack.java b/src/class11/Code07_Knapsack.java new file mode 100644 index 0000000..6ae4b46 --- /dev/null +++ b/src/class11/Code07_Knapsack.java @@ -0,0 +1,74 @@ +package class11; + +public class Code07_Knapsack { + + public static int getMaxValue(int[] w, int[] v, int bag) { + return process(w, v, 0, 0, bag); + } + + // index... 最大价值 + public static int process(int[] w, int[] v, int index, int alreadyW, int bag) { + if (alreadyW > bag) { + return -1; + } + // 重量没超 + if (index == w.length) { + return 0; + } + int p1 = process(w, v, index + 1, alreadyW, bag); + int p2next = process(w, v, index + 1, alreadyW + w[index], bag); + int p2 = -1; + if (p2next != -1) { + p2 = v[index] + p2next; + } + return Math.max(p1, p2); + + } + + public static int maxValue(int[] w, int[] v, int bag) { + return process(w, v, 0, bag); + } + + // 只剩下rest的空间了, + // index...货物自由选择,但是不要超过rest的空间 + // 返回能够获得的最大价值 + public static int process(int[] w, int[] v, int index, int rest) { + if (rest <= 0) { // base case 1 + return 0; + } + // rest >=0 + if (index == w.length) { // base case 2 + return 0; + } + // 有货也有空间 + int p1 = process(w, v, index + 1, rest); + int p2 = Integer.MIN_VALUE; + if (rest >= w[index]) { + p2 = v[index] + process(w, v, index + 1, rest - w[index]); + } + return Math.max(p1, p2); + } + + public static int dpWay(int[] w, int[] v, int bag) { + int N = w.length; + int[][] dp = new int[N + 1][bag + 1]; + for (int index = N - 1; index >= 0; index--) { + for (int rest = 1; rest <= bag; rest++) { + dp[index][rest] = dp[index + 1][rest]; + if (rest >= w[index]) { + dp[index][rest] = Math.max(dp[index][rest], v[index] + dp[index + 1][rest - w[index]]); + } + } + } + return dp[0][bag]; + } + + public static void main(String[] args) { + int[] weights = { 3, 2, 4, 7 }; + int[] values = { 5, 6, 3, 19 }; + int bag = 11; + System.out.println(maxValue(weights, values, bag)); + System.out.println(dpWay(weights, values, bag)); + } + +} diff --git a/src/class11/Code08_CardsInLine.java b/src/class11/Code08_CardsInLine.java new file mode 100644 index 0000000..7ee3451 --- /dev/null +++ b/src/class11/Code08_CardsInLine.java @@ -0,0 +1,49 @@ +package class11; + +public class Code08_CardsInLine { + + public static int win1(int[] arr) { + if (arr == null || arr.length == 0) { + return 0; + } + return Math.max(f(arr, 0, arr.length - 1), s(arr, 0, arr.length - 1)); + } + + public static int f(int[] arr, int i, int j) { + if (i == j) { + return arr[i]; + } + return Math.max(arr[i] + s(arr, i + 1, j), arr[j] + s(arr, i, j - 1)); + } + + public static int s(int[] arr, int i, int j) { + if (i == j) { + return 0; + } + return Math.min(f(arr, i + 1, j), f(arr, i, j - 1)); + } + + public static int win2(int[] arr) { + if (arr == null || arr.length == 0) { + return 0; + } + int[][] f = new int[arr.length][arr.length]; + int[][] s = new int[arr.length][arr.length]; + for (int j = 0; j < arr.length; j++) { + f[j][j] = arr[j]; + for (int i = j - 1; i >= 0; i--) { + f[i][j] = Math.max(arr[i] + s[i + 1][j], arr[j] + s[i][j - 1]); + s[i][j] = Math.min(f[i + 1][j], f[i][j - 1]); + } + } + return Math.max(f[0][arr.length - 1], s[0][arr.length - 1]); + } + + public static void main(String[] args) { + int[] arr = { 1, 9, 1 }; + System.out.println(win1(arr)); + System.out.println(win2(arr)); + + } + +} diff --git a/src/class11/Code09_NQueens.java b/src/class11/Code09_NQueens.java new file mode 100644 index 0000000..357f698 --- /dev/null +++ b/src/class11/Code09_NQueens.java @@ -0,0 +1,95 @@ +package class11; + +public class Code09_NQueens { + + public static int num1(int n) { + if (n < 1) { + return 0; + } + // record[0] ? record[1] ? record[2] + int[] record = new int[n]; // record[i] -> i行的皇后,放在了第几列 + return process1(0, record, n); + } + + // 潜台词:record[0..i-1]的皇后,任何两个皇后一定都不共行、不共列,不共斜线 + // 目前来到了第i行 + // record[0..i-1]表示之前的行,放了的皇后位置 + // n代表整体一共有多少行 + // 返回值是,摆完所有的皇后,合理的摆法有多少种 + public static int process1(int i, int[] record, int n) { + if (i == n) { // 终止行 + return 1; + } + int res = 0; + for (int j = 0; j < n; j++) { // 当前行在i行,尝试i行所有的列 -> j + // 当前i行的皇后,放在j列,会不会和之前(0..i-1)的皇后,不共行共列或者共斜线, + // 如果是,认为有效 + // 如果不是,认为无效 + if (isValid(record, i, j)) { + record[i] = j; + res += process1(i + 1, record, n); + } + } + return res; + } + + // record[0..i-1]你需要看,record[i...]不需要看 + // 返回i行皇后,放在了j列,是否有效 + public static boolean isValid(int[] record, int i, int j) { + for (int k = 0; k < i; k++) { // 之前的某个k行的皇后 + if (j == record[k] || Math.abs(record[k] - j) == Math.abs(i - k)) { + return false; + } + } + return true; + } + + // 请不要超过32皇后问题 + public static int num2(int n) { + if (n < 1 || n > 32) { + return 0; + } + int limit = n == 32 ? -1 : (1 << n) - 1; + return process2(limit, 0, 0, 0); + } + + // colLim 列的限制,1的位置不能放皇后,0的位置可以 + // leftDiaLim 左斜线的限制,1的位置不能放皇后,0的位置可以 + // rightDiaLim 右斜线的限制,1的位置不能放皇后,0的位置可以 + public static int process2(int limit, + int colLim, + int leftDiaLim, + int rightDiaLim) { + if (colLim == limit) { // base case + return 1; + } + // 所有候选皇后的位置,都在pos上 + int pos = limit & (~(colLim | leftDiaLim | rightDiaLim)); + int mostRightOne = 0; + int res = 0; + while (pos != 0) { + mostRightOne = pos & (~pos + 1); + pos = pos - mostRightOne; + res += process2(limit, + colLim | mostRightOne, + (leftDiaLim | mostRightOne) << 1, + (rightDiaLim | mostRightOne) >>> 1); + } + return res; + } + + public static void main(String[] args) { + int n = 14; + + long start = System.currentTimeMillis(); + System.out.println(num2(n)); + long end = System.currentTimeMillis(); + System.out.println("cost time: " + (end - start) + "ms"); + + start = System.currentTimeMillis(); + System.out.println(num1(n)); + end = System.currentTimeMillis(); + System.out.println("cost time: " + (end - start) + "ms"); + + } +} diff --git a/src/class12/Code01_RobotWalk.java b/src/class12/Code01_RobotWalk.java new file mode 100644 index 0000000..ef8bcd3 --- /dev/null +++ b/src/class12/Code01_RobotWalk.java @@ -0,0 +1,139 @@ +package class12; + +public class Code01_RobotWalk { + + public static int ways1(int N, int M, int K, int P) { + // 参数无效直接返回0 + if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) { + return 0; + } + // 总共N个位置,从M点出发,还剩K步,返回最终能达到P的方法数 + return walk(N, M, K, P); + } + + // N : 位置为1 ~ N,固定参数 + // cur : 当前在cur位置,可变参数 + // rest : 还剩res步没有走,可变参数 + // P : 最终目标位置是P,固定参数 + // 该函数的含义:只能在1~N这些位置上移动,当前在cur位置,走完rest步之后,停在P位置的方法数作为返回值返回 + public static int walk(int N, int cur, int rest, int P) { + // 如果没有剩余步数了,当前的cur位置就是最后的位置 + // 如果最后的位置停在P上,那么之前做的移动是有效的 + // 如果最后的位置没在P上,那么之前做的移动是无效的 + if (rest == 0) { + return cur == P ? 1 : 0; + } + // 如果还有rest步要走,而当前的cur位置在1位置上,那么当前这步只能从1走向2 + // 后续的过程就是,来到2位置上,还剩rest-1步要走 + if (cur == 1) { + return walk(N, 2, rest - 1, P); + } + // 如果还有rest步要走,而当前的cur位置在N位置上,那么当前这步只能从N走向N-1 + // 后续的过程就是,来到N-1位置上,还剩rest-1步要走 + if (cur == N) { + return walk(N, N - 1, rest - 1, P); + } + // 如果还有rest步要走,而当前的cur位置在中间位置上,那么当前这步可以走向左,也可以走向右 + // 走向左之后,后续的过程就是,来到cur-1位置上,还剩rest-1步要走 + // 走向右之后,后续的过程就是,来到cur+1位置上,还剩rest-1步要走 + // 走向左、走向右是截然不同的方法,所以总方法数要都算上 + return walk(N, cur + 1, rest - 1, P) + walk(N, cur - 1, rest - 1, P); + } + + public static int ways2(int N, int M, int K, int P) { + // 参数无效直接返回0 + if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) { + return 0; + } + int[][] dp = new int[K + 1][N + 1]; + dp[0][P] = 1; + for (int i = 1; i <= K; i++) { + for (int j = 1; j <= N; j++) { + if (j == 1) { + dp[i][j] = dp[i - 1][2]; + } else if (j == N) { + dp[i][j] = dp[i - 1][N - 1]; + } else { + dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j + 1]; + } + } + } + return dp[K][M]; + } + + public static int ways3(int N, int M, int K, int P) { + // 参数无效直接返回0 + if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) { + return 0; + } + int[] dp = new int[N + 1]; + dp[P] = 1; + for (int i = 1; i <= K; i++) { + int leftUp = dp[1];// 左上角的值 + for (int j = 1; j <= N; j++) { + int tmp = dp[j]; + if (j == 1) { + dp[j] = dp[j + 1]; + } else if (j == N) { + dp[j] = leftUp; + } else { + dp[j] = leftUp + dp[j + 1]; + } + leftUp = tmp; + } + } + return dp[M]; + } + + // ways4是你的方法 + public static int ways4(int N, int M, int K, int P) { + if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) { + return 0; + } + return process(N, 0, P, M, K); + } + + // 一共N个位置,从M点出发,一共只有K步。返回走到位置j,剩余步数为i的方法数 + public static int process(int N, int i, int j, int M, int K) { + if (i == K) { + return j == M ? 1 : 0; + } + if (j == 1) { + return process(N, i + 1, j + 1, M, K); + } + if (j == N) { + return process(N, i + 1, j - 1, M, K); + } + return process(N, i + 1, j + 1, M, K) + process(N, i + 1, j - 1, M, K); + } + + // ways5是你的方法的dp优化 + public static int ways5(int N, int M, int K, int P) { + if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) { + return 0; + } + int[][] dp = new int[K + 1][N + 1]; + dp[K][M] = 1; + for (int i = K - 1; i >= 0; i--) { + for (int j = 1; j <= N; j++) { + if (j == 1) { + dp[i][j] = dp[i + 1][j + 1]; + } else if (j == N) { + dp[i][j] = dp[i + 1][j - 1]; + } else { + dp[i][j] = dp[i + 1][j + 1] + dp[i + 1][j - 1]; + } + } + } + return dp[0][P]; + } + + public static void main(String[] args) { + System.out.println(ways1(7, 4, 9, 5)); + System.out.println(ways2(7, 4, 9, 5)); + System.out.println(ways3(7, 4, 9, 5)); + System.out.println(ways4(7, 4, 9, 5)); + System.out.println(ways5(7, 4, 9, 5)); + } + +} diff --git a/src/class12/Code02_StickersToSpellWord.java b/src/class12/Code02_StickersToSpellWord.java new file mode 100644 index 0000000..34e7016 --- /dev/null +++ b/src/class12/Code02_StickersToSpellWord.java @@ -0,0 +1,132 @@ +package class12; + +import java.util.Arrays; +import java.util.HashMap; + +public class Code02_StickersToSpellWord { + + public static int minStickers1(String[] stickers, String target) { + int n = stickers.length; + int[][] map = new int[n][26]; + HashMap dp = new HashMap<>(); + for (int i = 0; i < n; i++) { + char[] str = stickers[i].toCharArray(); + for (char c : str) { + map[i][c - 'a']++; + } + } + dp.put("", 0); + return process1(dp, map, target); + } + + // dp 傻缓存,如果t已经算过了,直接返回dp中的值 + // t 剩余的目标 + // 0..N每一个字符串所含字符的词频统计 + public static int process1(HashMap dp, int[][] map, String t) { + if (dp.containsKey(t)) { + return dp.get(t); + } + int ans = Integer.MAX_VALUE; + int n = map.length; + int[] tmap = new int[26]; + char[] target = t.toCharArray(); + for (char c : target) { + tmap[c - 'a']++; + } + for (int i = 0; i < n; i++) { + if (map[i][target[0] - 'a'] == 0) { + continue; + } + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < 26; j++) { + if (tmap[j] > 0) { // j这个字符是target需要的 + for (int k = 0; k < Math.max(0, tmap[j] - map[i][j]); k++) { + sb.append((char) ('a' + j)); + } + } + } + String s = sb.toString(); + int tmp = process1(dp, map, s); + if (tmp != -1) { + ans = Math.min(ans, 1 + tmp); + } + } + dp.put(t, ans == Integer.MAX_VALUE ? -1 : ans); + return dp.get(t); + } + + public static int minStickers2(String[] stickers, String target) { + int n = stickers.length; + int[][] map = new int[n][26]; + for (int i = 0; i < n; i++) { + char[] str = stickers[i].toCharArray(); + for (char c : str) { + map[i][c - 'a']++; + } + } + char[] str = target.toCharArray(); + int[] tmap = new int[26]; + for (char c : str) { + tmap[c - 'a']++; + } + HashMap dp = new HashMap<>(); + int ans = process2(map, 0, tmap, dp); + return ans; + } + + public static int process2(int[][] map, int i, int[] tmap, HashMap dp) { + StringBuilder keyBuilder = new StringBuilder(); + keyBuilder.append(i + "_"); + for (int asc = 0; asc < 26; asc++) { + if (tmap[asc] != 0) { + keyBuilder.append((char) (asc + 'a') + "_" + tmap[asc] + "_"); + } + } + String key = keyBuilder.toString(); + if (dp.containsKey(key)) { + return dp.get(key); + } + boolean finish = true; + for (int asc = 0; asc < 26; asc++) { + if (tmap[asc] != 0) { + finish = false; + break; + } + } + if (finish) { + dp.put(key, 0); + return 0; + } + if (i == map.length) { + dp.put(key, -1); + return -1; + } + int maxZhang = 0; + for (int asc = 0; asc < 26; asc++) { + if (map[i][asc] != 0 && tmap[asc] != 0) { + maxZhang = Math.max(maxZhang, (tmap[asc] / map[i][asc]) + (tmap[asc] % map[i][asc] == 0 ? 0 : 1)); + } + } + int[] backup = Arrays.copyOf(tmap, tmap.length); + int min = Integer.MAX_VALUE; + int next = process2(map, i + 1, tmap, dp); + tmap = Arrays.copyOf(backup, backup.length); + if (next != -1) { + min = next; + } + for (int zhang = 1; zhang <= maxZhang; zhang++) { + for (int asc = 0; asc < 26; asc++) { + tmap[asc] = Math.max(0, tmap[asc] - (map[i][asc] * zhang)); + } + next = process2(map, i + 1, tmap, dp); + tmap = Arrays.copyOf(backup, backup.length); + if (next != -1) { + min = Math.min(min, zhang + next); + } + } + int ans = min == Integer.MAX_VALUE ? -1 : min; + dp.put(key, ans); + return ans; + } + +} diff --git a/src/class12/Code03_Knapsack.java b/src/class12/Code03_Knapsack.java new file mode 100644 index 0000000..23c7a87 --- /dev/null +++ b/src/class12/Code03_Knapsack.java @@ -0,0 +1,74 @@ +package class12; + +public class Code03_Knapsack { + + public static int getMaxValue(int[] w, int[] v, int bag) { + return process(w, v, 0, 0, bag); + } + + // index... 最大价值 + public static int process(int[] w, int[] v, int index, int alreadyW, int bag) { + if (alreadyW > bag) { + return -1; + } + // 重量没超 + if (index == w.length) { + return 0; + } + int p1 = process(w, v, index + 1, alreadyW, bag); + int p2next = process(w, v, index + 1, alreadyW + w[index], bag); + int p2 = -1; + if (p2next != -1) { + p2 = v[index] + p2next; + } + return Math.max(p1, p2); + + } + + public static int maxValue(int[] w, int[] v, int bag) { + return process(w, v, 0, bag); + } + + // 只剩下rest的空间了, + // index...货物自由选择,但是不要超过rest的空间 + // 返回能够获得的最大价值 + public static int process(int[] w, int[] v, int index, int rest) { + if (rest <= 0) { // base case 1 + return 0; + } + // rest >=0 + if (index == w.length) { // base case 2 + return 0; + } + // 有货也有空间 + int p1 = process(w, v, index + 1, rest); + int p2 = Integer.MIN_VALUE; + if (rest >= w[index]) { + p2 = v[index] + process(w, v, index + 1, rest - w[index]); + } + return Math.max(p1, p2); + } + + public static int dpWay(int[] w, int[] v, int bag) { + int N = w.length; + int[][] dp = new int[N + 1][bag + 1]; + for (int index = N - 1; index >= 0; index--) { + for (int rest = 1; rest <= bag; rest++) { + dp[index][rest] = dp[index + 1][rest]; + if (rest >= w[index]) { + dp[index][rest] = Math.max(dp[index][rest], v[index] + dp[index + 1][rest - w[index]]); + } + } + } + return dp[0][bag]; + } + + public static void main(String[] args) { + int[] weights = { 3, 2, 4, 7 }; + int[] values = { 5, 6, 3, 19 }; + int bag = 11; + System.out.println(maxValue(weights, values, bag)); + System.out.println(dpWay(weights, values, bag)); + } + +} diff --git a/src/class12/Code04_CardsInLine.java b/src/class12/Code04_CardsInLine.java new file mode 100644 index 0000000..37ad9e4 --- /dev/null +++ b/src/class12/Code04_CardsInLine.java @@ -0,0 +1,61 @@ +package class12; + +public class Code04_CardsInLine { + + public static int win1(int[] arr) { + if (arr == null || arr.length == 0) { + return 0; + } + return Math.max(f(arr, 0, arr.length - 1), s(arr, 0, arr.length - 1)); + } + + public static int f(int[] arr, int L, int R) { + if (L == R) { + return arr[L]; + } + return Math.max(arr[L] + s(arr, L + 1, R), arr[R] + s(arr, L, R - 1)); + } + + public static int s(int[] arr, int L, int R) { + if (L == R) { + return 0; + } + return Math.min(f(arr, L + 1, R), f(arr, L, R - 1)); + } + + public static int windp(int[] arr) { + if (arr == null || arr.length == 0) { + return 0; + } + int N = arr.length; + int[][] f = new int[N][N]; + int[][] s = new int[N][N]; + for (int i = 0; i < N; i++) { + f[i][i] = arr[i]; + } + // 0,0 右下方移动 + // 0,1 + // 0,2 + // 0,N-1 + for (int col = 1; col < N; col++) { + // 对角线出发位置(0,col) + int L = 0; + int R = col; + while (L < N && R < N) { + f[L][R] = Math.max(arr[L] + s[L + 1][R], arr[R] + s[L][R - 1]); + s[L][R] = Math.min(f[L + 1][R], f[L][R - 1]); + L++; + R++; + } + } + return Math.max(f[0][N - 1], s[0][N - 1]); + } + + public static void main(String[] args) { + int[] arr = { 5, 7, 4, 5, 8, 1, 6, 0, 3, 4, 6, 1, 7 }; + System.out.println(win1(arr)); + System.out.println(windp(arr)); + + } + +} diff --git a/src/class12/Code05_PalindromeSubsequence.java b/src/class12/Code05_PalindromeSubsequence.java new file mode 100644 index 0000000..bb6f089 --- /dev/null +++ b/src/class12/Code05_PalindromeSubsequence.java @@ -0,0 +1,29 @@ +package class12; + +public class Code05_PalindromeSubsequence { + + public static int lcse(char[] str1, char[] str2) { + int[][] dp = new int[str1.length][str2.length]; + dp[0][0] = str1[0] == str2[0] ? 1 : 0; + for (int i = 1; i < str1.length; i++) { + dp[i][0] = Math.max(dp[i - 1][0], str1[i] == str2[0] ? 1 : 0); + } + for (int j = 1; j < str2.length; j++) { + dp[0][j] = Math.max(dp[0][j - 1], str1[0] == str2[j] ? 1 : 0); + } + for (int i = 1; i < str1.length; i++) { + for (int j = 1; j < str2.length; j++) { + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + if (str1[i] == str2[j]) { + dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 1] + 1); + } + } + } + return dp[str1.length - 1][str2.length - 1]; + } + + public static void main(String[] args) { + + } + +} diff --git a/src/class12/Code06_Coffee.java b/src/class12/Code06_Coffee.java new file mode 100644 index 0000000..99750b5 --- /dev/null +++ b/src/class12/Code06_Coffee.java @@ -0,0 +1,183 @@ +package class12; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.PriorityQueue; + +// 题目 +// 数组arr代表每一个咖啡机冲一杯咖啡的时间,每个咖啡机只能串行的制造咖啡。 +// 现在有n个人需要喝咖啡,只能用咖啡机来制造咖啡。 +// 认为每个人喝咖啡的时间非常短,冲好的时间即是喝完的时间。 +// 每个人喝完之后咖啡杯可以选择洗或者自然挥发干净,只有一台洗咖啡杯的机器,只能串行的洗咖啡杯。 +// 洗杯子的机器洗完一个杯子时间为a,任何一个杯子自然挥发干净的时间为b。 +// 四个参数:arr, n, a, b +// 假设时间点从0开始,返回所有人喝完咖啡并洗完咖啡杯的全部过程结束后,至少来到什么时间点。 +public class Code06_Coffee { + + // 方法一:暴力尝试方法 + public static int minTime1(int[] arr, int n, int a, int b) { + int[] times = new int[arr.length]; + int[] drink = new int[n]; + return forceMake(arr, times, 0, drink, n, a, b); + } + + // 方法一,每个人暴力尝试用每一个咖啡机给自己做咖啡 + public static int forceMake(int[] arr, int[] times, int kth, int[] drink, int n, int a, int b) { + if (kth == n) { + int[] drinkSorted = Arrays.copyOf(drink, kth); + Arrays.sort(drinkSorted); + return forceWash(drinkSorted, a, b, 0, 0, 0); + } + int time = Integer.MAX_VALUE; + for (int i = 0; i < arr.length; i++) { + int work = arr[i]; + int pre = times[i]; + drink[kth] = pre + work; + times[i] = pre + work; + time = Math.min(time, forceMake(arr, times, kth + 1, drink, n, a, b)); + drink[kth] = 0; + times[i] = pre; + } + return time; + } + + // 方法一,暴力尝试洗咖啡杯的方式 + public static int forceWash(int[] drinks, int a, int b, int index, int washLine, int time) { + if (index == drinks.length) { + return time; + } + // 选择一:当前index号咖啡杯,选择用洗咖啡机刷干净 + int wash = Math.max(drinks[index], washLine) + a; + int ans1 = forceWash(drinks, a, b, index + 1, wash, Math.max(wash, time)); + + // 选择二:当前index号咖啡杯,选择自然挥发 + int dry = drinks[index] + b; + int ans2 = forceWash(drinks, a, b, index + 1, washLine, Math.max(dry, time)); + return Math.min(ans1, ans2); + } + + // 方法二:稍微好一点的解法 + public static class Machine { + public int timePoint; + public int workTime; + + public Machine(int t, int w) { + timePoint = t; + workTime = w; + } + } + + public static class MachineComparator implements Comparator { + + @Override + public int compare(Machine o1, Machine o2) { + return (o1.timePoint + o1.workTime) - (o2.timePoint + o2.workTime); + } + + } + + // 方法二,每个人暴力尝试用每一个咖啡机给自己做咖啡,优化成贪心 + public static int minTime2(int[] arr, int n, int a, int b) { + PriorityQueue heap = new PriorityQueue(new MachineComparator()); + for (int i = 0; i < arr.length; i++) { + heap.add(new Machine(0, arr[i])); + } + int[] drinks = new int[n]; + for (int i = 0; i < n; i++) { + Machine cur = heap.poll(); + cur.timePoint += cur.workTime; + drinks[i] = cur.timePoint; + heap.add(cur); + } + return process(drinks, a, b, 0, 0); + } + + // 方法二,洗咖啡杯的方式和原来一样,只是这个暴力版本减少了一个可变参数 + public static int process(int[] drinks, int a, int b, int index, int washLine) { + if (index == drinks.length - 1) { + return Math.min(Math.max(washLine, drinks[index]) + a, drinks[index] + b); + } + // wash是我当前的咖啡杯,洗完的时间 + int wash = Math.max(washLine, drinks[index]) + a; + int next1 = process(drinks, a, b, index + 1, wash); + int p1 = Math.max(wash, next1); + int dry = drinks[index] + b; + int next2 = process(drinks, a, b, index + 1, washLine); + int p2 = Math.max(dry, next2); + return Math.min(p1, p2); + } + + // 方法三:最终版本,把方法二洗咖啡杯的暴力尝试进一步优化成动态规划 + public static int minTime3(int[] arr, int n, int a, int b) { + PriorityQueue heap = new PriorityQueue(new MachineComparator()); + for (int i = 0; i < arr.length; i++) { + heap.add(new Machine(0, arr[i])); + } + int[] drinks = new int[n]; + for (int i = 0; i < n; i++) { + Machine cur = heap.poll(); + cur.timePoint += cur.workTime; + drinks[i] = cur.timePoint; + heap.add(cur); + } + if (a >= b) { + return drinks[n - 1] + b; + } + int[][] dp = new int[n][drinks[n - 1] + n * a]; + for (int i = 0; i < dp[0].length; i++) { + dp[n - 1][i] = Math.min(Math.max(i, drinks[n - 1]) + a, drinks[n - 1] + b); + } + for (int row = n - 2; row >= 0; row--) { // row 咖啡杯的编号 + int washLine = drinks[row] + (row + 1) * a; + for (int col = 0; col < washLine; col++) { + int wash = Math.max(col, drinks[row]) + a; + dp[row][col] = Math.min(Math.max(wash, dp[row + 1][wash]), Math.max(drinks[row] + b, dp[row + 1][col])); + } + } + return dp[0][0]; + } + + // for test + public static int[] randomArray(int len, int max) { + int[] arr = new int[len]; + for (int i = 0; i < len; i++) { + arr[i] = (int) (Math.random() * max) + 1; + } + return arr; + } + + // for test + public static void printArray(int[] arr) { + System.out.print("arr : "); + for (int j = 0; j < arr.length; j++) { + System.out.print(arr[j] + ", "); + } + System.out.println(); + } + + public static void main(String[] args) { + int len = 5; + int max = 9; + int testTime = 50000; + for (int i = 0; i < testTime; i++) { + int[] arr = randomArray(len, max); + int n = (int) (Math.random() * 5) + 1; + int a = (int) (Math.random() * 5) + 1; + int b = (int) (Math.random() * 10) + 1; + int ans1 = minTime1(arr, n, a, b); + int ans2 = minTime2(arr, n, a, b); + int ans3 = minTime3(arr, n, a, b); + if (ans1 != ans2 || ans2 != ans3) { + printArray(arr); + System.out.println("n : " + n); + System.out.println("a : " + a); + System.out.println("b : " + b); + System.out.println(ans1 + " , " + ans2 + " , " + ans3); + System.out.println("==============="); + break; + } + } + + } + +} diff --git a/src/class12/Code07_HorseJump.java b/src/class12/Code07_HorseJump.java new file mode 100644 index 0000000..2d2ab17 --- /dev/null +++ b/src/class12/Code07_HorseJump.java @@ -0,0 +1,69 @@ +package class12; + +public class Code07_HorseJump { + + // 10*9 + // 0~9 y + // 0~8 x + public static int ways(int a, int b, int step) { + return f(0, 0, step, a, b); + } + + // 马在(i,j)位置,还有step步要去跳 + // 返回最终来到(a,b)的方法数 + public static int f(int i, int j, int step, int a, int b) { + if (i < 0 || i > 9 || j < 0 || j > 8) { + return 0; + } + if (step == 0) { + return (i == a && j == b) ? 1 : 0; + } + return f(i - 2, j + 1, step - 1, a, b) + + f(i - 1, j + 2, step - 1, a, b) + + f(i + 1, j + 2, step - 1, a, b) + + f(i + 2, j + 1, step - 1, a, b) + + f(i + 2, j - 1, step - 1, a, b) + + f(i + 1, j - 2, step - 1, a, b) + + f(i - 1, j - 2, step - 1, a, b) + + f(i - 2, j - 1, step - 1, a, b); + + } + + + public static int waysdp(int a, int b, int s) { + // (i,j,0~ step) + int[][][] dp = new int[10][9][s+1]; + dp[a][b][0] = 1; + for(int step = 1 ; step <= s;step++ ) { // 按层来 + for(int i = 0 ; i < 10;i++) { + for(int j = 0 ; j < 9; j++) { + dp[i][j][step] = getValue(dp,i - 2, j + 1, step - 1) + + getValue(dp,i - 1, j + 2, step - 1) + + getValue(dp,i + 1, j + 2, step - 1) + + getValue(dp,i + 2, j + 1, step - 1) + + getValue(dp,i + 2, j - 1, step - 1) + + getValue(dp,i + 1, j - 2, step - 1) + + getValue(dp,i - 1, j - 2, step - 1) + + getValue(dp,i - 2, j - 1, step - 1); + } + } + } + return dp[0][0][s]; + } + + // 在dp表中,得到dp[i][j][step]的值,但如果(i,j)位置越界的话,返回0; + public static int getValue(int[][][] dp, int i, int j, int step) { + if (i < 0 || i > 9 || j < 0 || j > 8) { + return 0; + } + return dp[i][j][step]; + } + + public static void main(String[] args) { + int x = 7; + int y = 7; + int step = 10; + System.out.println(ways(x, y, step)); + System.out.println(waysdp(x, y, step)); + } +} diff --git a/src/class12/Code08_MinPathSum.java b/src/class12/Code08_MinPathSum.java new file mode 100644 index 0000000..9aae0a3 --- /dev/null +++ b/src/class12/Code08_MinPathSum.java @@ -0,0 +1,82 @@ +package class12; + +public class Code08_MinPathSum { + + public static int minPathSum1(int[][] m) { + if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) { + return 0; + } + int row = m.length; + int col = m[0].length; + int[][] dp = new int[row][col]; + dp[0][0] = m[0][0]; + for (int i = 1; i < row; i++) { + dp[i][0] = dp[i - 1][0] + m[i][0]; + } + for (int j = 1; j < col; j++) { + dp[0][j] = dp[0][j - 1] + m[0][j]; + } + for (int i = 1; i < row; i++) { + for (int j = 1; j < col; j++) { + dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + m[i][j]; + } + } + return dp[row - 1][col - 1]; + } + + public static int minPathSum2(int[][] m) { + if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) { + return 0; + } + int more = Math.max(m.length, m[0].length); // �����������ϴ���Ǹ�Ϊmore + int less = Math.min(m.length, m[0].length); // ������������С���Ǹ�Ϊless + boolean rowmore = more == m.length; // �����Dz��Ǵ��ڵ������� + int[] arr = new int[less]; // ��������ij��Ƚ�Ϊ�����������е���Сֵ + arr[0] = m[0][0]; + for (int i = 1; i < less; i++) { + arr[i] = arr[i - 1] + (rowmore ? m[0][i] : m[i][0]); + } + for (int i = 1; i < more; i++) { + arr[0] = arr[0] + (rowmore ? m[i][0] : m[0][i]); + for (int j = 1; j < less; j++) { + arr[j] = Math.min(arr[j - 1], arr[j]) + + (rowmore ? m[i][j] : m[j][i]); + } + } + return arr[less - 1]; + } + + // for test + public static int[][] generateRandomMatrix(int rowSize, int colSize) { + if (rowSize < 0 || colSize < 0) { + return null; + } + int[][] result = new int[rowSize][colSize]; + for (int i = 0; i != result.length; i++) { + for (int j = 0; j != result[0].length; j++) { + result[i][j] = (int) (Math.random() * 10); + } + } + return result; + } + + // for test + public static void printMatrix(int[][] matrix) { + for (int i = 0; i != matrix.length; i++) { + for (int j = 0; j != matrix[0].length; j++) { + System.out.print(matrix[i][j] + " "); + } + System.out.println(); + } + } + + public static void main(String[] args) { + // int[][] m = generateRandomMatrix(3, 4); + int[][] m = { { 1, 3, 5, 9 }, { 8, 1, 3, 4 }, { 5, 0, 6, 1 }, + { 8, 8, 4, 0 } }; + printMatrix(m); + System.out.println(minPathSum1(m)); + System.out.println(minPathSum2(m)); + + } +} diff --git a/src/class12/Code09_CoinsWay.java b/src/class12/Code09_CoinsWay.java new file mode 100644 index 0000000..59fd827 --- /dev/null +++ b/src/class12/Code09_CoinsWay.java @@ -0,0 +1,52 @@ +package class12; + +public class Code09_CoinsWay { + + // arr中都是正数且无重复值,返回组成aim的方法数 + public static int ways(int[] arr, int aim) { + if (arr == null || arr.length == 0 || aim < 0) { + return 0; + } + return process(arr, 0, aim); + } + + // 如果自由使用arr[index...]的面值,组成rest这么多钱,返回方法数 (1 , 6) + public static int process(int[] arr, int index, int rest) { + if (index == arr.length) { // 无面值的时候 + return rest == 0 ? 1 : 0; + } + // 有面值的时候 + int ways = 0; + // arr[index] 当钱面值 + for (int zhang = 0; zhang * arr[index] <= rest; zhang++) { + ways += process(arr, index + 1, rest - zhang * arr[index]); + } + return ways; + } + + public static int waysdp(int[] arr, int aim) { + if (arr == null || arr.length == 0 || aim < 0) { + return 0; + } + int N = arr.length; + int[][] dp = new int[N + 1][aim + 1]; + dp[N][0] = 1; + for (int i = N - 1; i >= 0; i--) { // 大顺序 从下往上 + for (int rest = 0; rest <= aim; rest++) { + dp[i][rest] = dp[i + 1][rest]; + if (rest - arr[i] >= 0) { + dp[i][rest] += dp[i][rest - arr[i]]; + } + } + } + return dp[0][aim]; + } + + public static void main(String[] args) { + int[] arr = { 5, 2, 3, 1 }; + int sum = 350; + System.out.println(ways(arr, sum)); + System.out.println(waysdp(arr, sum)); + } + +}