diff --git a/MCA算法突击课/第03期/mca_01/Code01_Swap.java b/MCA算法突击课/第03期/mca_01/Code01_Swap.java index 330f493..74333cc 100644 --- a/MCA算法突击课/第03期/mca_01/Code01_Swap.java +++ b/MCA算法突击课/第03期/mca_01/Code01_Swap.java @@ -15,8 +15,8 @@ public class Code01_Swap { printBinary(a); printBinary(b); System.out.println("======="); - printBinary(a & b); - System.out.println(a & b); + printBinary(a ^ b); + System.out.println(a ^ b); a = a ^ b; b = a ^ b; diff --git a/MCA算法突击课/第03期/mca_01/Code02_EvenTimesOddTimes.java b/MCA算法突击课/第03期/mca_01/Code02_EvenTimesOddTimes.java index 0eb4fe5..8adfede 100644 --- a/MCA算法突击课/第03期/mca_01/Code02_EvenTimesOddTimes.java +++ b/MCA算法突击课/第03期/mca_01/Code02_EvenTimesOddTimes.java @@ -5,79 +5,43 @@ public class Code02_EvenTimesOddTimes { // arr中,只有一种数,出现奇数次 public static void printOddTimesNum1(int[] arr) { int eor = 0; - for (int i = 0; i < arr.length; i++) { - eor ^= arr[i]; + for (int num : arr) { + eor ^= num; } System.out.println(eor); } - // arr中,有两种数,出现奇数次 - public static void printOddTimesNum2(int[] arr) { + // 请保证,arr中,有两种数出现奇数次,其他的数都是偶数次 + // 打印 + public static void printOddTimesNumber(int[] arr) { int eor = 0; - for (int i = 0; i < arr.length; i++) { - eor ^= arr[i]; + for (int num : arr) { + eor ^= num; } - // a 和 b是两种数 - // eor != 0 - // eor最右侧的1,提取出来 - // eor : 00110010110111000 - // rightOne :00000000000001000 - int rightOne = eor & (-eor); // 提取出最右的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]; + // eor = a ^ b + // 请把eor状态中,最右侧的1提取出来 + // eor = 0000110010 + // rightOne = 0000000010 & | ^ << >> >>> + // >> 带符号右移 + // >>> 不带符号右移 + // java 干啥的,自己查 + int rightOne = eor & (-eor); + int zuo = 0; + for (int num : arr) { + // zuo只去异或一类,另一类忽略 + if ((num & rightOne) == 0) { + zuo ^= num; } } - System.out.println(onlyOne + " " + (eor ^ onlyOne)); + System.out.println("一个是 :" + zuo); + System.out.println("另一个是 :" + (eor ^ zuo)); } - - 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); - + // 5 7 521 14 10 + int[] arr = { 5, 7, 14, 14, 521, 7, 10, 7, 5, 5, 521, 7, 7, 7, 5, 14 }; + // 请找到 14 和 10 + printOddTimesNumber(arr); } } diff --git a/MCA算法突击课/第03期/mca_01/Code03_BinarySearch.java b/MCA算法突击课/第03期/mca_01/Code03_BinarySearch.java index 02c4e2b..8db56cc 100644 --- a/MCA算法突击课/第03期/mca_01/Code03_BinarySearch.java +++ b/MCA算法突击课/第03期/mca_01/Code03_BinarySearch.java @@ -22,24 +22,25 @@ public class Code03_BinarySearch { } return sortedArr[L] == num; } - + // 在arr上,找满足>=value的最左位置 public static int nearest1(int[] sortedArr, int value) { int L = 0; int R = sortedArr.length - 1; - int index = -1; // 记录最左的对号 - while (L <= R) { // 至少一个数的时候 - int mid = L + ((R - L) >> 1); + // 0....N-1 + int ans = -1; + while (L <= R) { // L...R L < R + int mid = (L + R) / 2; if (sortedArr[mid] >= value) { - index = mid; + ans = mid; R = mid - 1; } else { L = mid + 1; } } - return index; + return ans; } - + // 在arr上,找满足<=value的最右位置 public static int nearest2(int[] sortedArr, int value) { int L = 0; diff --git a/MCA算法突击课/第03期/mca_01/Code05_KokoEatingBananas.java b/MCA算法突击课/第03期/mca_01/Code05_KokoEatingBananas.java index cf1e7c4..163addc 100644 --- a/MCA算法突击课/第03期/mca_01/Code05_KokoEatingBananas.java +++ b/MCA算法突击课/第03期/mca_01/Code05_KokoEatingBananas.java @@ -1,6 +1,8 @@ package 第03期.mca_01; // leetcode 875题 +// 一定有答案 +// 管理员,1小时,5堆,-1 public class Code05_KokoEatingBananas { public static int minEatingSpeed(int[] piles, int h) { @@ -9,6 +11,7 @@ public class Code05_KokoEatingBananas { for (int pile : piles) { R = Math.max(R, pile); } + // 1......Max int ans = 0; int M = 0; while (L <= R) { @@ -23,6 +26,9 @@ public class Code05_KokoEatingBananas { return ans; } + // piles : 每一堆香蕉的个数,都在piles里 + // speed : 猩猩的速度 + // 在这个速度下,几小时吃完! public static int hours(int[] piles, int speed) { int ans = 0; int offset = speed - 1; diff --git a/MCA算法突击课/第03期/mca_01/Code06_SplitArrayLargestSum.java b/MCA算法突击课/第03期/mca_01/Code06_SplitArrayLargestSum.java index c4be3da..2478260 100644 --- a/MCA算法突击课/第03期/mca_01/Code06_SplitArrayLargestSum.java +++ b/MCA算法突击课/第03期/mca_01/Code06_SplitArrayLargestSum.java @@ -4,113 +4,7 @@ package 第03期.mca_01; // 测试链接:https://leetcode.cn/problems/split-array-largest-sum/ public class Code06_SplitArrayLargestSum { - // 求原数组arr[L...R]的累加和 - public static int sum(int[] sum, int L, int R) { - return sum[R + 1] - sum[L]; - } - - // 不优化枚举的动态规划方法,O(N^2 * K) - public static int splitArray1(int[] nums, int K) { - int N = nums.length; - int[] sum = new int[N + 1]; - for (int i = 0; i < N; i++) { - sum[i + 1] = sum[i] + nums[i]; - } - int[][] dp = new int[N][K + 1]; - for (int j = 1; j <= K; j++) { - dp[0][j] = nums[0]; - } - for (int i = 1; i < N; i++) { - dp[i][1] = sum(sum, 0, i); - } - // 每一行从上往下 - // 每一列从左往右 - // 根本不去凑优化位置对儿! - for (int i = 1; i < N; i++) { - for (int j = 2; j <= K; j++) { - int ans = Integer.MAX_VALUE; - // 枚举是完全不优化的! - for (int leftEnd = 0; leftEnd <= i; leftEnd++) { - int leftCost = leftEnd == -1 ? 0 : dp[leftEnd][j - 1]; - int rightCost = leftEnd == i ? 0 : sum(sum, leftEnd + 1, i); - int cur = Math.max(leftCost, rightCost); - if (cur < ans) { - ans = cur; - } - } - dp[i][j] = ans; - } - } - return dp[N - 1][K]; - } - - // 课上现场写的方法,用了枚举优化,O(N * K) - public static int splitArray2(int[] nums, int K) { - int N = nums.length; - int[] sum = new int[N + 1]; - for (int i = 0; i < N; i++) { - sum[i + 1] = sum[i] + nums[i]; - } - int[][] dp = new int[N][K + 1]; - int[][] best = new int[N][K + 1]; - for (int j = 1; j <= K; j++) { - dp[0][j] = nums[0]; - best[0][j] = -1; - } - for (int i = 1; i < N; i++) { - dp[i][1] = sum(sum, 0, i); - best[i][1] = -1; - } - // 从第2列开始,从左往右 - // 每一列,从下往上 - // 为什么这样的顺序?因为要去凑(左,下)优化位置对儿! - for (int j = 2; j <= K; j++) { - for (int i = N - 1; i >= 1; i--) { - int down = best[i][j - 1]; - // 如果i==N-1,则不优化上限 - int up = i == N - 1 ? N - 1 : best[i + 1][j]; - int ans = Integer.MAX_VALUE; - int bestChoose = -1; - for (int leftEnd = down; leftEnd <= up; leftEnd++) { - int leftCost = leftEnd == -1 ? 0 : dp[leftEnd][j - 1]; - int rightCost = leftEnd == i ? 0 : sum(sum, leftEnd + 1, i); - int cur = Math.max(leftCost, rightCost); - // 注意下面的if一定是 < 课上的错误就是此处!当时写的 <= ! - // 也就是说,只有取得明显的好处才移动! - // 举个例子来说明,比如[2,6,4,4],3个画匠时候,如下两种方案都是最优: - // (2,6) (4) 两个画匠负责 | (4) 最后一个画匠负责 - // (2,6) (4,4)两个画匠负责 | 最后一个画匠什么也不负责 - // 第一种方案划分为,[0~2] [3~3] - // 第二种方案划分为,[0~3] [无] - // 两种方案的答案都是8,但是划分点位置一定不要移动! - // 只有明显取得好处时(<),划分点位置才移动! - // 也就是说后面的方案如果==前面的最优,不要移动!只有优于前面的最优,才移动 - // 比如上面的两个方案,如果你移动到了方案二,你会得到: - // [2,6,4,4] 三个画匠时,最优为[0~3](前两个画家) [无](最后一个画家), - // 最优划分点为3位置(best[3][3]) - // 那么当4个画匠时,也就是求解dp[3][4]时 - // 因为best[3][3] = 3,这个值提供了dp[3][4]的下限 - // 而事实上dp[3][4]的最优划分为: - // [0~2](三个画家处理) [3~3] (一个画家处理),此时最优解为6 - // 所以,你就得不到dp[3][4]的最优解了,因为划分点已经越过2了 - // 提供了对数器验证,你可以改成<=,对数器和leetcode都过不了 - // 这里是<,对数器和leetcode都能通过 - // 这里面会让同学们感到困惑的点: - // 为啥==的时候,不移动,只有<的时候,才移动呢?例子懂了,但是道理何在? - // 哈哈哈哈哈,看了邮局选址问题,你更懵,请看42节! - if (cur < ans) { - ans = cur; - bestChoose = leftEnd; - } - } - dp[i][j] = ans; - best[i][j] = bestChoose; - } - } - return dp[N - 1][K]; - } - - public static int splitArray3(int[] nums, int M) { + public static int splitArray(int[] nums, int M) { long sum = 0; for (int i = 0; i < nums.length; i++) { sum += nums[i]; @@ -150,44 +44,4 @@ public class Code06_SplitArrayLargestSum { return parts; } - public static int[] randomArray(int len, int maxValue) { - int[] arr = new int[len]; - for (int i = 0; i < len; i++) { - arr[i] = (int) (Math.random() * maxValue); - } - return arr; - } - - public static void printArray(int[] arr) { - for (int i = 0; i < arr.length; i++) { - System.out.print(arr[i] + " "); - } - System.out.println(); - } - - public static void main(String[] args) { - int N = 100; - int maxValue = 100; - int testTime = 10000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int len = (int) (Math.random() * N) + 1; - int M = (int) (Math.random() * N) + 1; - int[] arr = randomArray(len, maxValue); - int ans1 = splitArray1(arr, M); - int ans2 = splitArray2(arr, M); - int ans3 = splitArray3(arr, M); - if (ans1 != ans2 || ans1 != ans3) { - System.out.print("arr : "); - printArray(arr); - System.out.println("M : " + M); - System.out.println("ans1 : " + ans1); - System.out.println("ans2 : " + ans2); - System.out.println("ans3 : " + ans3); - System.out.println("Oops!"); - break; - } - } - System.out.println("测试结束"); - } } diff --git a/MCA算法突击课/第03期/mca_01/Code07_HashMapAndSortedMap.java b/MCA算法突击课/第03期/mca_01/Code07_HashMapAndSortedMap.java index 42364a6..33e4e65 100644 --- a/MCA算法突击课/第03期/mca_01/Code07_HashMapAndSortedMap.java +++ b/MCA算法突击课/第03期/mca_01/Code07_HashMapAndSortedMap.java @@ -1,128 +1,126 @@ package 第03期.mca_01; +import java.util.Arrays; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.TreeMap; +import java.util.TreeSet; public class Code07_HashMapAndSortedMap { - public static class Node { - public int value; + public static class Student { + public int age; - public Node(int v) { - value = v; - } - } - - public static class Zuo { - public int value; - - public Zuo(int v) { - value = v; + public Student(int a) { + age = a; } } public static void main(String[] args) { + Student s1 = new Student(4); + Student s2 = new Student(4); + Student s3 = new Student(4); + HashSet set = new HashSet<>(); + set.add(s1); + set.add(s2); + set.add(s3); + System.out.println(set.size()); + Student s4 = new Student(4); + System.out.println(set.contains(s4)); - HashMap test = new HashMap<>(); - Integer a = 19000000; - Integer b = 19000000; - System.out.println(a == b); - - test.put(a, "我是3"); - System.out.println(test.containsKey(b)); - - Zuo z1 = new Zuo(1); - Zuo z2 = new Zuo(1); - HashMap test2 = new HashMap<>(); - test2.put(z1, "我是z1"); - System.out.println(test2.containsKey(z2)); - - // 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("====================="); - - 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); + map.put(7, "我是7"); + map.remove(7); + map.put(7, "我是7"); + map.put(7, "他是7"); + map.get(7); + map.containsKey(7); - 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()); + // O(1) 常数时间 - System.out.println("======================"); - - // TreeMap 有序表:接口名 - // 红黑树、avl、sb树、跳表 - // O(logN) - 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(15, "我是5"); + treeMap.put(555, "我是5"); treeMap.put(5, "我是5"); - treeMap.put(7, "我是7"); - treeMap.put(1, "我是1"); - treeMap.put(2, "我是2"); + treeMap.put(3, "我是5"); + treeMap.put(50, "我是5"); - System.out.println(treeMap.containsKey(1)); - System.out.println(treeMap.containsKey(10)); + // put、remove、get、containsKey + // log N + System.out.println(treeMap.firstKey()); + System.out.println(treeMap.lastKey()); + int num = -10; + // <= num 且离num最近的key + System.out.println(treeMap.floorKey(num)); + // >= num 且离num最近的key + System.out.println(treeMap.ceilingKey(num)); + System.out.println("=========="); + Cat cat1 = new Cat(4, 40); + Cat cat2 = new Cat(3, 400); + Cat cat3 = new Cat(-9, 17); + Cat cat4 = new Cat(1000, 7); + + Cat[] cats = { cat1, cat2, cat3, cat4 }; + + // 根据年龄排序 + Arrays.sort(cats, (a, b) -> b.age - a.age); + for (Cat cat : cats) { + System.out.println(cat.age + " , " + cat.weight); + } - System.out.println(treeMap.get(4)); - System.out.println(treeMap.get(10)); + TreeSet catSet = new TreeSet<>((a, b) -> b.age - a.age); + catSet.add(cat1); + catSet.add(cat2); + catSet.add(cat3); + catSet.add(cat4); - treeMap.put(4, "他是4"); - System.out.println(treeMap.get(4)); + System.out.println(catSet.first().age); - // treeMap.remove(4); - System.out.println(treeMap.get(4)); + // 根据重量排序 - System.out.println("新鲜:"); + Integer[] arr = { 3, 4, 7, 2 }; + Arrays.sort(arr, (a,b) -> b - a); + for(Integer x : arr) { + System.out.println(x); + } + + int[] arr2 = { 3, 4, 7, 2 }; + Arrays.sort(arr2); + for(int x : arr2) { + System.out.println(x); + } + } - 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) + public static class CatComparator implements Comparator { + + // 返回负,o1好! + // 返回正,o2好! + // 返回0,o1、o2一样好! + + @Override + public int compare(Cat o1, Cat o2) { +// if (o1.age < o2.age) { +// return -1; +// } else if (o1.age > o2.age) { +// return 1; +// } else { +// return 0; +// } + return o2.age - o1.age; + } } + public static class Cat { + public int age; + public int weight; + + public Cat(int a, int w) { + age = a; + weight = w; + } + } + } diff --git a/MCA算法突击课/第03期/mca_01/Code08_CoverMax.java b/MCA算法突击课/第03期/mca_02/Code08_CoverMax.java similarity index 99% rename from MCA算法突击课/第03期/mca_01/Code08_CoverMax.java rename to MCA算法突击课/第03期/mca_02/Code08_CoverMax.java index a5ec2b1..be5de70 100644 --- a/MCA算法突击课/第03期/mca_01/Code08_CoverMax.java +++ b/MCA算法突击课/第03期/mca_02/Code08_CoverMax.java @@ -1,4 +1,4 @@ -package 第03期.mca_01; +package 第03期.mca_02; import java.util.Arrays; import java.util.Comparator; diff --git a/MCA算法突击课/第03期/mca_01/Code09_LessMoneySplitGold.java b/MCA算法突击课/第03期/mca_02/Code09_LessMoneySplitGold.java similarity index 98% rename from MCA算法突击课/第03期/mca_01/Code09_LessMoneySplitGold.java rename to MCA算法突击课/第03期/mca_02/Code09_LessMoneySplitGold.java index 0166372..aa9eecd 100644 --- a/MCA算法突击课/第03期/mca_01/Code09_LessMoneySplitGold.java +++ b/MCA算法突击课/第03期/mca_02/Code09_LessMoneySplitGold.java @@ -1,4 +1,4 @@ -package 第03期.mca_01; +package 第03期.mca_02; import java.util.PriorityQueue;