modify code

master
algorithmzuo 2 years ago
parent fcabcf49b4
commit 0d01ef1a35

@ -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;

@ -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);
}
}

@ -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;

@ -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;

@ -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("测试结束");
}
}

@ -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<Student> 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<Integer, String> 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<Zuo, String> test2 = new HashMap<>();
test2.put(z1, "我是z1");
System.out.println(test2.containsKey(z2));
// UnSortedMap
HashMap<Integer, String> 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<String> set = new HashSet<>();
set.add("abc");
set.contains("abc");
set.remove("abc");
// 哈希表增、删、改、查在使用时O1
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<Node, String> 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<Integer, String> 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<Cat> 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<Cat> {
// 返回负o1好
// 返回正o2好
// 返回0o1、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;
}
}
}

@ -1,4 +1,4 @@
package 03.mca_01;
package 03.mca_02;
import java.util.Arrays;
import java.util.Comparator;
Loading…
Cancel
Save