From 4184f320007fd77163e472b2276c1078a9706b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=A6=E7=A8=8B=E4=BA=91?= Date: Mon, 15 Mar 2021 17:45:25 +0800 Subject: [PATCH] add class --- src/class32/Code01_IndexTree.java | 6 + src/class32/Code04_AC2.java | 21 +- src/class33/Hash.java | 2 +- src/class37/Code01_CountofRangeSum.java | 11 +- .../Code04_QueueReconstructionByHeight.java | 265 ++++++++++++++++ src/class38/Code01_AppleMinBags.java | 47 +++ src/class38/Code02_EatGrass.java | 45 +++ src/class38/Code03_MSumToN.java | 41 +++ src/class38/Code04_MoneyProblem.java | 131 ++++++++ src/class39/Code01_DifferentBTNum.java | 66 ++++ src/class39/Code02_10Ways.java | 92 ++++++ src/class39/Code03_RotateMatrix.java | 44 +++ .../Code04_PrintMatrixSpiralOrder.java | 53 ++++ src/class39/Code05_ZigZagPrintMatrix.java | 43 +++ src/class39/Code06_PrintStar.java | 46 +++ ...ngestSumSubArrayLengthInPositiveArray.java | 91 ++++++ .../Code02_LongestSumSubArrayLength.java | 90 ++++++ .../Code03_LongestLessSumSubArrayLength.java | 105 +++++++ ...de04_AvgLessEqualValueLongestSubarray.java | 152 +++++++++ src/class41/Code01_NiuNiuSplitField.java | 179 +++++++++++ src/class41/Code02_SplitArrayLargestSum.java | 124 ++++++++ .../Code01_ThrowChessPiecesProblem.java | 194 ++++++++++++ src/class42/Code02_PostOfficeProblem.java | 215 +++++++++++++ src/class43/Code01_TSP.java | 295 ++++++++++++++++++ src/class43/Code02_PavingTile.java | 131 ++++++++ src/class43/Code03_CanIWin.java | 64 ++++ src/class44/Code01_CreateMaximumNumber.java | 248 +++++++++++++++ ...2_LastSubstringInLexicographicalOrder.java | 148 +++++++++ ...e03_InsertS2MakeMostAlphabeticalOrder.java | 249 +++++++++++++++ src/class44/DC3.java | 123 ++++++++ src/class44/DC3_Algorithm.pdf | Bin 0 -> 192716 bytes src/class45/Code01_BurstBalloons.java | 85 +++++ src/class45/Code02_RemoveBoxes.java | 38 +++ src/class45/Code03_StrangePrinter.java | 33 ++ src/class46/Code01_RestoreWays.java | 237 ++++++++++++++ .../Code02_DeleteAdjacentSameCharacter.java | 172 ++++++++++ 36 files changed, 3868 insertions(+), 18 deletions(-) create mode 100644 src/class37/Code04_QueueReconstructionByHeight.java create mode 100644 src/class38/Code01_AppleMinBags.java create mode 100644 src/class38/Code02_EatGrass.java create mode 100644 src/class38/Code03_MSumToN.java create mode 100644 src/class38/Code04_MoneyProblem.java create mode 100644 src/class39/Code01_DifferentBTNum.java create mode 100644 src/class39/Code02_10Ways.java create mode 100644 src/class39/Code03_RotateMatrix.java create mode 100644 src/class39/Code04_PrintMatrixSpiralOrder.java create mode 100644 src/class39/Code05_ZigZagPrintMatrix.java create mode 100644 src/class39/Code06_PrintStar.java create mode 100644 src/class40/Code01_LongestSumSubArrayLengthInPositiveArray.java create mode 100644 src/class40/Code02_LongestSumSubArrayLength.java create mode 100644 src/class40/Code03_LongestLessSumSubArrayLength.java create mode 100644 src/class40/Code04_AvgLessEqualValueLongestSubarray.java create mode 100644 src/class41/Code01_NiuNiuSplitField.java create mode 100644 src/class41/Code02_SplitArrayLargestSum.java create mode 100644 src/class42/Code01_ThrowChessPiecesProblem.java create mode 100644 src/class42/Code02_PostOfficeProblem.java create mode 100644 src/class43/Code01_TSP.java create mode 100644 src/class43/Code02_PavingTile.java create mode 100644 src/class43/Code03_CanIWin.java create mode 100644 src/class44/Code01_CreateMaximumNumber.java create mode 100644 src/class44/Code02_LastSubstringInLexicographicalOrder.java create mode 100644 src/class44/Code03_InsertS2MakeMostAlphabeticalOrder.java create mode 100644 src/class44/DC3.java create mode 100644 src/class44/DC3_Algorithm.pdf create mode 100644 src/class45/Code01_BurstBalloons.java create mode 100644 src/class45/Code02_RemoveBoxes.java create mode 100644 src/class45/Code03_StrangePrinter.java create mode 100644 src/class46/Code01_RestoreWays.java create mode 100644 src/class46/Code02_DeleteAdjacentSameCharacter.java diff --git a/src/class32/Code01_IndexTree.java b/src/class32/Code01_IndexTree.java index f7d5eca..4c4bdab 100644 --- a/src/class32/Code01_IndexTree.java +++ b/src/class32/Code01_IndexTree.java @@ -2,16 +2,19 @@ package class32; public class Code01_IndexTree { + // 下标从1开始! public static class IndexTree { private int[] tree; private int N; + // 0位置弃而不用! public IndexTree(int size) { N = size; tree = new int[N + 1]; } + // 1~index 累加和是多少? public int sum(int index) { int ret = 0; while (index > 0) { @@ -21,6 +24,9 @@ public class Code01_IndexTree { return ret; } + // index & -index : 提取出index最右侧的1出来 + // index : 0011001000 + // index & -index : 0000001000 public void add(int index, int d) { while (index <= N) { tree[index] += d; diff --git a/src/class32/Code04_AC2.java b/src/class32/Code04_AC2.java index fc915bc..e684de3 100644 --- a/src/class32/Code04_AC2.java +++ b/src/class32/Code04_AC2.java @@ -17,6 +17,7 @@ public class Code04_AC2 { public boolean endUse; public Node fail; public Node[] nexts; + public Node() { endUse = false; end = null; @@ -39,8 +40,7 @@ public class Code04_AC2 { for (int i = 0; i < str.length; i++) { index = str[i] - 'a'; if (cur.nexts[index] == null) { - Node next = new Node(); - cur.nexts[index] = next; + cur.nexts[index] = new Node(); } cur = cur.nexts[index]; } @@ -53,14 +53,12 @@ public class Code04_AC2 { Node cur = null; Node cfail = null; while (!queue.isEmpty()) { - // 当前节点弹出, - // 当前节点的所有后代加入到队列里去, - // 当前节点给它的子去设置fail指针 - // cur -> 父亲 + // 某个父亲,cur cur = queue.poll(); for (int i = 0; i < 26; i++) { // 所有的路 - if (cur.nexts[i] != null) { // 找到所有有效的路 - cur.nexts[i].fail = root; // + // cur -> 父亲 i号儿子,必须把i号儿子的fail指针设置好! + if (cur.nexts[i] != null) { // 如果真的有i号儿子 + cur.nexts[i].fail = root; cfail = cur.fail; while (cfail != null) { if (cfail.nexts[i] != null) { @@ -75,6 +73,7 @@ public class Code04_AC2 { } } + // 大文章:content public List containWords(String content) { char[] str = content.toCharArray(); Node cur = root; @@ -92,7 +91,7 @@ public class Code04_AC2 { cur = cur.nexts[index] != null ? cur.nexts[index] : root; follow = cur; while (follow != root) { - if(follow.endUse) { + if (follow.endUse) { break; } // 不同的需求,在这一段之间修改 @@ -115,8 +114,8 @@ public class Code04_AC2 { ac.insert("he"); ac.insert("abcdheks"); // 设置fail指针 - ac.build(); - + ac.build(); + List contains = ac.containWords("abcdhekskdjfafhasldkflskdjhwqaeruv"); for (String word : contains) { System.out.println(word); diff --git a/src/class33/Hash.java b/src/class33/Hash.java index 552191b..2c54b7d 100644 --- a/src/class33/Hash.java +++ b/src/class33/Hash.java @@ -29,7 +29,7 @@ public class Hash { } System.out.println("======="); - String algorithm = "SHA"; + String algorithm = "MD5"; Hash hash = new Hash(algorithm); String input1 = "zuochengyunzuochengyun1"; diff --git a/src/class37/Code01_CountofRangeSum.java b/src/class37/Code01_CountofRangeSum.java index e8f1292..d79fa02 100644 --- a/src/class37/Code01_CountofRangeSum.java +++ b/src/class37/Code01_CountofRangeSum.java @@ -164,18 +164,17 @@ public class Code01_CountofRangeSum { } public static int countRangeSum2(int[] nums, int lower, int upper) { + // 黑盒,加入数字(前缀和),不去重,可以接受重复数字 + // < num , 有几个数? SizeBalancedTreeSet treeSet = new SizeBalancedTreeSet(); long sum = 0; int ans = 0; treeSet.add(0);// 一个数都没有的时候,就已经有一个前缀和累加和为0, for (int i = 0; i < nums.length; i++) { sum += nums[i]; - // sum i结尾的时候[lower, upper] - // 之前所有前缀累加和中,有多少累加和落在[sum - upper, sum - lower] - // 查 ? < sum - lower + 1 a - // 查 ? < sum - upper b - // a - b - + // [sum - upper, sum - lower] + // [10, 20] ? + // < 10 ? < 21 ? long a = treeSet.lessKeySize(sum - lower + 1); long b = treeSet.lessKeySize(sum - upper); ans += a - b; diff --git a/src/class37/Code04_QueueReconstructionByHeight.java b/src/class37/Code04_QueueReconstructionByHeight.java new file mode 100644 index 0000000..2513402 --- /dev/null +++ b/src/class37/Code04_QueueReconstructionByHeight.java @@ -0,0 +1,265 @@ +package class37; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.LinkedList; + +// 本题测试链接:https://leetcode.com/problems/queue-reconstruction-by-height/ +public class Code04_QueueReconstructionByHeight { + + public static int[][] reconstructQueue1(int[][] people) { + int N = people.length; + Unit[] units = new Unit[N]; + for (int i = 0; i < N; i++) { + units[i] = new Unit(people[i][0], people[i][1]); + } + Arrays.sort(units, new UnitComparator()); + ArrayList arrList = new ArrayList<>(); + for (Unit unit : units) { + arrList.add(unit.k, unit); + } + int[][] ans = new int[N][2]; + int index = 0; + for (Unit unit : arrList) { + ans[index][0] = unit.h; + ans[index++][1] = unit.k; + } + return ans; + } + + public static int[][] reconstructQueue2(int[][] people) { + int N = people.length; + Unit[] units = new Unit[N]; + for (int i = 0; i < N; i++) { + units[i] = new Unit(people[i][0], people[i][1]); + } + Arrays.sort(units, new UnitComparator()); + SBTree tree = new SBTree(); + for (int i = 0; i < N; i++) { + tree.insert(units[i].k, i); + } + LinkedList allIndexes = tree.allIndexes(); + int[][] ans = new int[N][2]; + int index = 0; + for (Integer arri : allIndexes) { + ans[index][0] = units[arri].h; + ans[index++][1] = units[arri].k; + } + return ans; + } + + public static class Unit { + public int h; + public int k; + + public Unit(int height, int greater) { + h = height; + k = greater; + } + } + + public static class UnitComparator implements Comparator { + + @Override + public int compare(Unit o1, Unit o2) { + return o1.h != o2.h ? (o2.h - o1.h) : (o1.k - o2.k); + } + + } + + public static class SBTNode { + public int value; + public SBTNode l; + public SBTNode r; + public int size; + + public SBTNode(int arrIndex) { + value = arrIndex; + size = 1; + } + } + + public static class SBTree { + private SBTNode root; + + private SBTNode rightRotate(SBTNode cur) { + SBTNode leftNode = cur.l; + cur.l = leftNode.r; + leftNode.r = cur; + leftNode.size = cur.size; + cur.size = (cur.l != null ? cur.l.size : 0) + (cur.r != null ? cur.r.size : 0) + 1; + return leftNode; + } + + private SBTNode leftRotate(SBTNode cur) { + SBTNode rightNode = cur.r; + cur.r = rightNode.l; + rightNode.l = cur; + rightNode.size = cur.size; + cur.size = (cur.l != null ? cur.l.size : 0) + (cur.r != null ? cur.r.size : 0) + 1; + return rightNode; + } + + private SBTNode maintain(SBTNode cur) { + if (cur == null) { + return null; + } + int leftSize = cur.l != null ? cur.l.size : 0; + int leftLeftSize = cur.l != null && cur.l.l != null ? cur.l.l.size : 0; + int leftRightSize = cur.l != null && cur.l.r != null ? cur.l.r.size : 0; + int rightSize = cur.r != null ? cur.r.size : 0; + int rightLeftSize = cur.r != null && cur.r.l != null ? cur.r.l.size : 0; + int rightRightSize = cur.r != null && cur.r.r != null ? cur.r.r.size : 0; + if (leftLeftSize > rightSize) { + cur = rightRotate(cur); + cur.r = maintain(cur.r); + cur = maintain(cur); + } else if (leftRightSize > rightSize) { + cur.l = leftRotate(cur.l); + cur = rightRotate(cur); + cur.l = maintain(cur.l); + cur.r = maintain(cur.r); + cur = maintain(cur); + } else if (rightRightSize > leftSize) { + cur = leftRotate(cur); + cur.l = maintain(cur.l); + cur = maintain(cur); + } else if (rightLeftSize > leftSize) { + cur.r = rightRotate(cur.r); + cur = leftRotate(cur); + cur.l = maintain(cur.l); + cur.r = maintain(cur.r); + cur = maintain(cur); + } + return cur; + } + + private SBTNode insert(SBTNode root, int index, SBTNode cur) { + if (root == null) { + return cur; + } + root.size++; + int leftAndHeadSize = (root.l != null ? root.l.size : 0) + 1; + if (index < leftAndHeadSize) { + root.l = insert(root.l, index, cur); + } else { + root.r = insert(root.r, index - leftAndHeadSize, cur); + } + root = maintain(root); + return root; + } + + private SBTNode get(SBTNode root, int index) { + int leftSize = root.l != null ? root.l.size : 0; + if (index < leftSize) { + return get(root.l, index); + } else if (index == leftSize) { + return root; + } else { + return get(root.r, index - leftSize - 1); + } + } + + private void process(SBTNode head, LinkedList indexes) { + if (head == null) { + return; + } + process(head.l, indexes); + indexes.addLast(head.value); + process(head.r, indexes); + } + + public void insert(int index, int value) { + SBTNode cur = new SBTNode(value); + if (root == null) { + root = cur; + } else { + if (index <= root.size) { + root = insert(root, index, cur); + } + } + } + + public int get(int index) { + SBTNode ans = get(root, index); + return ans.value; + } + + public LinkedList allIndexes() { + LinkedList indexes = new LinkedList<>(); + process(root, indexes); + return indexes; + } + + } + + // 通过以下这个测试, + // 可以很明显的看到LinkedList的插入和get效率不如SBTree + // LinkedList需要找到index所在的位置之后才能插入或者读取,时间复杂度O(N) + // SBTree是平衡搜索二叉树,所以插入或者读取时间复杂度都是O(logN) + public static void main(String[] args) { + // 功能测试 + int test = 10000; + int max = 1000000; + boolean pass = true; + LinkedList list = new LinkedList<>(); + SBTree sbtree = new SBTree(); + for (int i = 0; i < test; i++) { + int randomIndex = (int) (Math.random() * (i + 1)); + int randomValue = (int) (Math.random() * (max + 1)); + list.add(randomIndex, randomValue); + sbtree.insert(randomIndex, randomValue); + } + for (int i = 0; i < test; i++) { + if (list.get(i) != sbtree.get(i)) { + pass = false; + break; + } + } + System.out.println("功能测试是否通过 : " + pass); + + // 性能测试 + test = 50000; + list = new LinkedList<>(); + sbtree = new SBTree(); + long start = 0; + long end = 0; + + start = System.currentTimeMillis(); + for (int i = 0; i < test; i++) { + int randomIndex = (int) (Math.random() * (i + 1)); + int randomValue = (int) (Math.random() * (max + 1)); + list.add(randomIndex, randomValue); + } + end = System.currentTimeMillis(); + System.out.println("LinkedList插入总时长(毫秒) : " + (end - start)); + + start = System.currentTimeMillis(); + for (int i = 0; i < test; i++) { + int randomIndex = (int) (Math.random() * (i + 1)); + list.get(randomIndex); + } + end = System.currentTimeMillis(); + System.out.println("LinkedList读取总时长(毫秒) : " + (end - start)); + + start = System.currentTimeMillis(); + for (int i = 0; i < test; i++) { + int randomIndex = (int) (Math.random() * (i + 1)); + int randomValue = (int) (Math.random() * (max + 1)); + sbtree.insert(randomIndex, randomValue); + } + end = System.currentTimeMillis(); + System.out.println("SBTree插入总时长(毫秒) : " + (end - start)); + + start = System.currentTimeMillis(); + for (int i = 0; i < test; i++) { + int randomIndex = (int) (Math.random() * (i + 1)); + sbtree.get(randomIndex); + } + end = System.currentTimeMillis(); + System.out.println("SBTree读取总时长(毫秒) : " + (end - start)); + + } + +} diff --git a/src/class38/Code01_AppleMinBags.java b/src/class38/Code01_AppleMinBags.java new file mode 100644 index 0000000..54d4182 --- /dev/null +++ b/src/class38/Code01_AppleMinBags.java @@ -0,0 +1,47 @@ +package class38; + +public class Code01_AppleMinBags { + + public static int minBags(int apple) { + if (apple < 0) { + return -1; + } + int bag6 = -1; + int bag8 = apple / 8; + int rest = apple - 8 * bag8; + while (bag8 >= 0 && rest < 24) { + int restUse6 = minBagBase6(rest); + if (restUse6 != -1) { + bag6 = restUse6; + break; + } + rest = apple - 8 * (--bag8); + } + return bag6 == -1 ? -1 : bag6 + bag8; + } + + // 如果剩余苹果rest可以被装6个苹果的袋子搞定,返回袋子数量 + // 不能搞定返回-1 + public static int minBagBase6(int rest) { + return rest % 6 == 0 ? (rest / 6) : -1; + } + + public static int minBagAwesome(int apple) { + if ((apple & 1) != 0) { // 如果是奇数,返回-1 + return -1; + } + if (apple < 18) { + return apple == 0 ? 0 : (apple == 6 || apple == 8) ? 1 + : (apple == 12 || apple == 14 || apple == 16) ? 2 : -1; + } + return (apple - 18) / 8 + 3; + } + + public static void main(String[] args) { + for(int apple = 1; apple < 100;apple++) { + System.out.println(apple + " : "+ minBags(apple)); + } + + } + +} diff --git a/src/class38/Code02_EatGrass.java b/src/class38/Code02_EatGrass.java new file mode 100644 index 0000000..200abcd --- /dev/null +++ b/src/class38/Code02_EatGrass.java @@ -0,0 +1,45 @@ +package class38; + +public class Code02_EatGrass { + + // n份青草放在一堆 + // 先手后手都绝顶聪明 + // string "先手" "后手" + public static String winner1(int n) { + // 0 1 2 3 4 + // 后 先 后 先 先 + if (n < 5) { // base case + return (n == 0 || n == 2) ? "后手" : "先手"; + } + // n >= 5 时 + int base = 1; // 当前先手决定吃的草数 + // 当前是先手在选 + while (base <= n) { + // 当前一共n份草,先手吃掉的是base份,n - base 是留给后手的草 + // 母过程 先手 在子过程里是 后手 + if (winner1(n - base).equals("后手")) { + return "先手"; + } + if (base > n / 4) { // 防止base*4之后溢出 + break; + } + base *= 4; + } + return "后手"; + } + + public static String winner2(int n) { + if (n % 5 == 0 || n % 5 == 2) { + return "后手"; + } else { + return "先手"; + } + } + + public static void main(String[] args) { + for (int i = 0; i <= 50; i++) { + System.out.println(i + " : " + winner1(i)); + } + } + +} diff --git a/src/class38/Code03_MSumToN.java b/src/class38/Code03_MSumToN.java new file mode 100644 index 0000000..81e6bad --- /dev/null +++ b/src/class38/Code03_MSumToN.java @@ -0,0 +1,41 @@ +package class38; + +public class Code03_MSumToN { + + public static boolean isMSum1(int num) { + for (int i = 1; i <= num; i++) { + int sum = i; + for (int j = i + 1; j <= num; j++) { + if (sum + j > num) { + break; + } + if (sum + j == num) { + return true; + } + sum += j; + } + } + return false; + } + + public static boolean isMSum2(int num) { + if (num < 3) { + return false; + } + return (num & (num - 1)) != 0; + } + + public static void main(String[] args) { + for (int num = 1; num < 200; num++) { + System.out.println(num + " : " + isMSum1(num)); + } + System.out.println("test begin"); + for (int num = 1; num < 5000; num++) { + if (isMSum1(num) != isMSum2(num)) { + System.out.println("Oops!"); + } + } + System.out.println("test end"); + + } +} diff --git a/src/class38/Code04_MoneyProblem.java b/src/class38/Code04_MoneyProblem.java new file mode 100644 index 0000000..0ea4e4a --- /dev/null +++ b/src/class38/Code04_MoneyProblem.java @@ -0,0 +1,131 @@ +package class38; + +public class Code04_MoneyProblem { + + // int[] d d[i]:i号怪兽的武力 + // int[] p p[i]:i号怪兽要求的钱 + // ability 当前你所具有的能力 + // index 来到了第index个怪兽的面前 + + // 目前,你的能力是ability,你来到了index号怪兽的面前,如果要通过后续所有的怪兽, + // 请返回需要花的最少钱数 + public static long process(int[] d, int[] p, int ability, int index) { + if (index == d.length) { + return 0; + } + if (ability < d[index]) { + return p[index] + process(d, p, ability + d[index], index + 1); + } else { // 可以贿赂,也可以不贿赂 + return + Math.min( + p[index] + process(d, p, ability + d[index], index + 1), + process(d, p, ability, index + 1) + ); + } + } + + public static long func1(int[] d, int[] p) { + return process(d, p, 0, 0); + } + + public static long func2(int[] d, int[] p) { + int sum = 0; + for (int num : d) { + sum += num; + } + long[][] dp = new long[d.length + 1][sum + 1]; + for (int i = 0; i <= sum; i++) { + dp[0][i] = 0; + } + for (int cur = d.length - 1; cur >= 0; cur--) { + for (int hp = 0; hp <= sum; hp++) { + // 如果这种情况发生,那么这个hp必然是递归过程中不会出现的状态 + // 既然动态规划是尝试过程的优化,尝试过程碰不到的状态,不必计算 + if (hp + d[cur] > sum) { + continue; + } + if (hp < d[cur]) { + dp[cur][hp] = p[cur] + dp[cur + 1][hp + d[cur]]; + } else { + dp[cur][hp] = Math.min(p[cur] + dp[cur + 1][hp + d[cur]], dp[cur + 1][hp]); + } + } + } + return dp[0][0]; + } + + public static long func3(int[] d, int[] p) { + int sum = 0; + for (int num : p) { + sum += num; + } + // dp[i][j]含义: + // 能经过0~i的怪兽,且花钱为j(花钱的严格等于j)时的武力值最大是多少? + // 如果dp[i][j]==-1,表示经过0~i的怪兽,花钱为j是无法通过的,或者之前的钱怎么组合也得不到正好为j的钱数 + int[][] dp = new int[d.length][sum + 1]; + for (int i = 0; i < dp.length; i++) { + for (int j = 0; j <= sum; j++) { + dp[i][j] = -1; + } + } + // 经过0~i的怪兽,花钱数一定为p[0],达到武力值d[0]的地步。其他第0行的状态一律是无效的 + dp[0][p[0]] = d[0]; + for (int i = 1; i < d.length; i++) { + for (int j = 0; j <= sum; j++) { + // 可能性一,为当前怪兽花钱 + // 存在条件: + // j - p[i]要不越界,并且在钱数为j - p[i]时,要能通过0~i-1的怪兽,并且钱数组合是有效的。 + if (j >= p[i] && dp[i - 1][j - p[i]] != -1) { + dp[i][j] = dp[i - 1][j - p[i]] + d[i]; + } + // 可能性二,不为当前怪兽花钱 + // 存在条件: + // 0~i-1怪兽在花钱为j的情况下,能保证通过当前i位置的怪兽 + if (dp[i - 1][j] >= d[i]) { + // 两种可能性中,选武力值最大的 + dp[i][j] = Math.max(dp[i][j], dp[i - 1][j]); + } + } + } + int ans = 0; + // dp表最后一行上,dp[N-1][j]代表: + // 能经过0~N-1的怪兽,且花钱为j(花钱的严格等于j)时的武力值最大是多少? + // 那么最后一行上,最左侧的不为-1的列数(j),就是答案 + for (int j = 0; j <= sum; j++) { + if (dp[d.length - 1][j] != -1) { + ans = j; + break; + } + } + return ans; + } + + public static int[][] generateTwoRandomArray(int len, int value) { + int size = (int) (Math.random() * len) + 1; + int[][] arrs = new int[2][size]; + for (int i = 0; i < size; i++) { + arrs[0][i] = (int) (Math.random() * value) + 1; + arrs[1][i] = (int) (Math.random() * value) + 1; + } + return arrs; + } + + public static void main(String[] args) { + int len = 10; + int value = 20; + int testTimes = 1000000; + for (int i = 0; i < testTimes; i++) { + int[][] arrs = generateTwoRandomArray(len, value); + int[] d = arrs[0]; + int[] p = arrs[1]; + long ans1 = func1(d, p); + long ans2 = func2(d, p); + long ans3 = func3(d, p); + if (ans1 != ans2 || ans2 != ans3) { + System.out.println("oops!"); + } + } + + } + +} diff --git a/src/class39/Code01_DifferentBTNum.java b/src/class39/Code01_DifferentBTNum.java new file mode 100644 index 0000000..4655e3c --- /dev/null +++ b/src/class39/Code01_DifferentBTNum.java @@ -0,0 +1,66 @@ +package class39; + +public class Code01_DifferentBTNum { + +// k(0) = 1, k(1) = 1 +// +// k(n) = k(0) * k(n - 1) + k(1) * k(n - 2) + ... + k(n - 2) * k(1) + k(n - 1) * k(0) +// 或者 +// k(n) = c(2n, n) / (n + 1) +// 或者 +// k(n) = c(2n, n) - c(2n, n-1) + + public static long num1(int N) { + if (N < 0) { + return 0; + } + if (N < 2) { + return 1; + } + long[] dp = new long[N + 1]; + dp[0] = 1; + dp[1] = 1; + for (int i = 2; i <= N; i++) { + for (int leftSize = 0; leftSize < i; leftSize++) { + dp[i] += dp[leftSize] * dp[i - 1 - leftSize]; + } + } + return dp[N]; + } + + public static long num2(int N) { + if (N < 0) { + return 0; + } + if (N < 2) { + return 1; + } + long a = 1; + long b = 1; + for (int i = 1, j = N + 1; i <= N; i++, j++) { + a *= i; + b *= j; + long gcd = gcd(a, b); + a /= gcd; + b /= gcd; + } + return (b / a) / (N + 1); + } + + public static long gcd(long m, long n) { + return n == 0 ? m : gcd(n, m % n); + } + + public static void main(String[] args) { + System.out.println("test begin"); + for (int i = 0; i < 15; i++) { + long ans1 = num1(i); + long ans2 = num2(i); + if (ans1 != ans2) { + System.out.println("Oops!"); + } + } + System.out.println("test finish"); + } + +} diff --git a/src/class39/Code02_10Ways.java b/src/class39/Code02_10Ways.java new file mode 100644 index 0000000..1068ce2 --- /dev/null +++ b/src/class39/Code02_10Ways.java @@ -0,0 +1,92 @@ +package class39; + +import java.util.LinkedList; + +public class Code02_10Ways { + + public static long ways1(int N) { + int zero = N; + int one = N; + LinkedList path = new LinkedList<>(); + LinkedList> ans = new LinkedList<>(); + process(zero, one, path, ans); + long count = 0; + for (LinkedList cur : ans) { + int status = 0; + for (Integer num : cur) { + if (num == 0) { + status++; + } else { + status--; + } + if (status < 0) { + break; + } + } + if (status == 0) { + count++; + } + } + return count; + } + + public static void process(int zero, int one, LinkedList path, LinkedList> ans) { + if (zero == 0 && one == 0) { + LinkedList cur = new LinkedList<>(); + for (Integer num : path) { + cur.add(num); + } + ans.add(cur); + } else { + if (zero == 0) { + path.addLast(1); + process(zero, one - 1, path, ans); + path.removeLast(); + } else if (one == 0) { + path.addLast(0); + process(zero - 1, one, path, ans); + path.removeLast(); + } else { + path.addLast(1); + process(zero, one - 1, path, ans); + path.removeLast(); + path.addLast(0); + process(zero - 1, one, path, ans); + path.removeLast(); + } + } + } + + public static long ways2(int N) { + if (N < 0) { + return 0; + } + if (N < 2) { + return 1; + } + long a = 1; + long b = 1; + long limit = N << 1; + for (long i = 1; i <= limit; i++) { + if (i <= N) { + a *= i; + } else { + b *= i; + } + } + return (b / a) / (N + 1); + } + + public static void main(String[] args) { + System.out.println("test begin"); + for (int i = 0; i < 10; i++) { + long ans1 = ways1(i); + long ans2 = ways2(i); + if (ans1 != ans2) { + System.out.println("Oops!"); + } + } + System.out.println("test finish"); + } + +} diff --git a/src/class39/Code03_RotateMatrix.java b/src/class39/Code03_RotateMatrix.java new file mode 100644 index 0000000..ee3f956 --- /dev/null +++ b/src/class39/Code03_RotateMatrix.java @@ -0,0 +1,44 @@ +package class39; + +public class Code03_RotateMatrix { + + public static void rotate(int[][] matrix) { + int a = 0; + int b = 0; + int c = matrix.length - 1; + int d = matrix[0].length - 1; + while (a < c) { + rotateEdge(matrix, a++, b++, c--, d--); + } + } + + public static void rotateEdge(int[][] m, int a, int b, int c, int d) { + int tmp = 0; + for (int i = 0; i < d - b; i++) { + tmp = m[a][b + i]; + m[a][b + i] = m[c - i][b]; + m[c - i][b] = m[c][d - i]; + m[c][d - i] = m[a + i][d]; + m[a + i][d] = tmp; + } + } + + 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[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, { 13, 14, 15, 16 } }; + printMatrix(matrix); + rotate(matrix); + System.out.println("========="); + printMatrix(matrix); + + } + +} diff --git a/src/class39/Code04_PrintMatrixSpiralOrder.java b/src/class39/Code04_PrintMatrixSpiralOrder.java new file mode 100644 index 0000000..27b8f30 --- /dev/null +++ b/src/class39/Code04_PrintMatrixSpiralOrder.java @@ -0,0 +1,53 @@ +package class39; + +public class Code04_PrintMatrixSpiralOrder { + + public static void spiralOrderPrint(int[][] matrix) { + int tR = 0; + int tC = 0; + int dR = matrix.length - 1; + int dC = matrix[0].length - 1; + while (tR <= dR && tC <= dC) { + printEdge(matrix, tR++, tC++, dR--, dC--); + } + } + + public static void printEdge(int[][] m, int tR, int tC, int dR, int dC) { + if (tR == dR) { + for (int i = tC; i <= dC; i++) { + System.out.print(m[tR][i] + " "); + } + } else if (tC == dC) { + for (int i = tR; i <= dR; i++) { + System.out.print(m[i][tC] + " "); + } + } else { + int curC = tC; + int curR = tR; + while (curC != dC) { + System.out.print(m[tR][curC] + " "); + curC++; + } + while (curR != dR) { + System.out.print(m[curR][dC] + " "); + curR++; + } + while (curC != tC) { + System.out.print(m[dR][curC] + " "); + curC--; + } + while (curR != tR) { + System.out.print(m[curR][tC] + " "); + curR--; + } + } + } + + public static void main(String[] args) { + int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, + { 13, 14, 15, 16 } }; + spiralOrderPrint(matrix); + + } + +} diff --git a/src/class39/Code05_ZigZagPrintMatrix.java b/src/class39/Code05_ZigZagPrintMatrix.java new file mode 100644 index 0000000..09089cb --- /dev/null +++ b/src/class39/Code05_ZigZagPrintMatrix.java @@ -0,0 +1,43 @@ +package class39; + +public class Code05_ZigZagPrintMatrix { + + public static void printMatrixZigZag(int[][] matrix) { + int tR = 0; + int tC = 0; + int dR = 0; + int dC = 0; + int endR = matrix.length - 1; + int endC = matrix[0].length - 1; + boolean fromUp = false; + while (tR != endR + 1) { + printLevel(matrix, tR, tC, dR, dC, fromUp); + tR = tC == endC ? tR + 1 : tR; + tC = tC == endC ? tC : tC + 1; + dC = dR == endR ? dC + 1 : dC; + dR = dR == endR ? dR : dR + 1; + fromUp = !fromUp; + } + System.out.println(); + } + + public static void printLevel(int[][] m, int tR, int tC, int dR, int dC, + boolean f) { + if (f) { + while (tR != dR + 1) { + System.out.print(m[tR++][tC--] + " "); + } + } else { + while (dR != tR - 1) { + System.out.print(m[dR--][dC++] + " "); + } + } + } + + public static void main(String[] args) { + int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; + printMatrixZigZag(matrix); + + } + +} diff --git a/src/class39/Code06_PrintStar.java b/src/class39/Code06_PrintStar.java new file mode 100644 index 0000000..02f2b5d --- /dev/null +++ b/src/class39/Code06_PrintStar.java @@ -0,0 +1,46 @@ +package class39; + +public class Code06_PrintStar { + + public static void printStar(int N) { + int leftUp = 0; + int rightDown = N - 1; + char[][] m = new char[N][N]; + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + m[i][j] = ' '; + } + } + while (leftUp <= rightDown) { + set(m, leftUp, rightDown); + leftUp += 2; + rightDown -= 2; + } + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + System.out.print(m[i][j] + " "); + } + System.out.println(); + } + } + + public static void set(char[][] m, int leftUp, int rightDown) { + for (int col = leftUp; col <= rightDown; col++) { + m[leftUp][col] = '*'; + } + for (int row = leftUp + 1; row <= rightDown; row++) { + m[row][rightDown] = '*'; + } + for (int col = rightDown - 1; col > leftUp; col--) { + m[rightDown][col] = '*'; + } + for (int row = rightDown - 1; row > leftUp + 1; row--) { + m[row][leftUp + 1] = '*'; + } + } + + public static void main(String[] args) { + printStar(8); + } + +} diff --git a/src/class40/Code01_LongestSumSubArrayLengthInPositiveArray.java b/src/class40/Code01_LongestSumSubArrayLengthInPositiveArray.java new file mode 100644 index 0000000..a2389fa --- /dev/null +++ b/src/class40/Code01_LongestSumSubArrayLengthInPositiveArray.java @@ -0,0 +1,91 @@ +package class40; + +public class Code01_LongestSumSubArrayLengthInPositiveArray { + + public static int getMaxLength(int[] arr, int K) { + if (arr == null || arr.length == 0 || K <= 0) { + return 0; + } + int left = 0; + int right = 0; + int sum = arr[0]; + int len = 0; + while (right < arr.length) { + if (sum == K) { + len = Math.max(len, right - left + 1); + sum -= arr[left++]; + } else if (sum < K) { + right++; + if (right == arr.length) { + break; + } + sum += arr[right]; + } else { + sum -= arr[left++]; + } + } + return len; + } + + // for test + public static int right(int[] arr, int K) { + int max = 0; + for (int i = 0; i < arr.length; i++) { + for (int j = i; j < arr.length; j++) { + if (valid(arr, i, j, K)) { + max = Math.max(max, j - i + 1); + } + } + } + return max; + } + + // for test + public static boolean valid(int[] arr, int L, int R, int K) { + int sum = 0; + for (int i = L; i <= R; i++) { + sum += arr[i]; + } + return sum == K; + } + + // for test + public static int[] generatePositiveArray(int size, int value) { + int[] ans = new int[size]; + for (int i = 0; i != size; i++) { + ans[i] = (int) (Math.random() * value) + 1; + } + return ans; + } + + // for test + 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 len = 50; + int value = 100; + int testTime = 500000; + System.out.println("test begin"); + for (int i = 0; i < testTime; i++) { + int[] arr = generatePositiveArray(len, value); + int K = (int) (Math.random() * value) + 1; + int ans1 = getMaxLength(arr, K); + int ans2 = right(arr, K); + if (ans1 != ans2) { + System.out.println("Oops!"); + printArray(arr); + System.out.println("K : " + K); + System.out.println(ans1); + System.out.println(ans2); + break; + } + } + System.out.println("test end"); + } + +} diff --git a/src/class40/Code02_LongestSumSubArrayLength.java b/src/class40/Code02_LongestSumSubArrayLength.java new file mode 100644 index 0000000..c1a21aa --- /dev/null +++ b/src/class40/Code02_LongestSumSubArrayLength.java @@ -0,0 +1,90 @@ +package class40; + +import java.util.HashMap; + +public class Code02_LongestSumSubArrayLength { + + public static int maxLength(int[] arr, int k) { + if (arr == null || arr.length == 0) { + return 0; + } + HashMap map = new HashMap(); + map.put(0, -1); // important + int len = 0; + int sum = 0; + for (int i = 0; i < arr.length; i++) { + sum += arr[i]; + if (map.containsKey(sum - k)) { + len = Math.max(i - map.get(sum - k), len); + } + if (!map.containsKey(sum)) { + map.put(sum, i); + } + } + return len; + } + + // for test + public static int right(int[] arr, int K) { + int max = 0; + for (int i = 0; i < arr.length; i++) { + for (int j = i; j < arr.length; j++) { + if (valid(arr, i, j, K)) { + max = Math.max(max, j - i + 1); + } + } + } + return max; + } + + // for test + public static boolean valid(int[] arr, int L, int R, int K) { + int sum = 0; + for (int i = L; i <= R; i++) { + sum += arr[i]; + } + return sum == K; + } + + // for test + public static int[] generateRandomArray(int size, int value) { + int[] ans = new int[(int) (Math.random() * size) + 1]; + for (int i = 0; i < ans.length; i++) { + ans[i] = (int) (Math.random() * value) - (int) (Math.random() * value); + } + return ans; + } + + // for test + 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 len = 50; + int value = 100; + int testTime = 500000; + + System.out.println("test begin"); + for (int i = 0; i < testTime; i++) { + int[] arr = generateRandomArray(len, value); + int K = (int) (Math.random() * value) - (int) (Math.random() * value); + int ans1 = maxLength(arr, K); + int ans2 = right(arr, K); + if (ans1 != ans2) { + System.out.println("Oops!"); + printArray(arr); + System.out.println("K : " + K); + System.out.println(ans1); + System.out.println(ans2); + break; + } + } + System.out.println("test end"); + + } + +} diff --git a/src/class40/Code03_LongestLessSumSubArrayLength.java b/src/class40/Code03_LongestLessSumSubArrayLength.java new file mode 100644 index 0000000..5349d2b --- /dev/null +++ b/src/class40/Code03_LongestLessSumSubArrayLength.java @@ -0,0 +1,105 @@ +package class40; + +public class Code03_LongestLessSumSubArrayLength { + + public static int maxLengthAwesome(int[] arr, int k) { + if (arr == null || arr.length == 0) { + return 0; + } + int[] minSums = new int[arr.length]; + int[] minSumEnds = new int[arr.length]; + minSums[arr.length - 1] = arr[arr.length - 1]; + minSumEnds[arr.length - 1] = arr.length - 1; + for (int i = arr.length - 2; i >= 0; i--) { + if (minSums[i + 1] < 0) { + minSums[i] = arr[i] + minSums[i + 1]; + minSumEnds[i] = minSumEnds[i + 1]; + } else { + minSums[i] = arr[i]; + minSumEnds[i] = i; + } + } + int end = 0; + int sum = 0; + int res = 0; + // i是窗口的最左的位置,end扩出来的最右有效块儿的最后一个位置的,再下一个位置 + // end也是下一块儿的开始位置 + // 窗口:[i~end) + for (int i = 0; i < arr.length; i++) { + // while循环结束之后: + // 1) 如果以i开头的情况下,累加和<=k的最长子数组是arr[i..end-1],看看这个子数组长度能不能更新res; + // 2) 如果以i开头的情况下,累加和<=k的最长子数组比arr[i..end-1]短,更新还是不更新res都不会影响最终结果; + while (end < arr.length && sum + minSums[end] <= k) { + sum += minSums[end]; + end = minSumEnds[end] + 1; + } + res = Math.max(res, end - i); + if (end > i) { // 窗口内还有数 [i~end) [4,4) + sum -= arr[i]; + } else { // 窗口内已经没有数了,说明从i开头的所有子数组累加和都不可能<=k + end = i + 1; + } + } + return res; + } + + public static int maxLength(int[] arr, int k) { + int[] h = new int[arr.length + 1]; + int sum = 0; + h[0] = sum; + for (int i = 0; i != arr.length; i++) { + sum += arr[i]; + h[i + 1] = Math.max(sum, h[i]); + } + sum = 0; + int res = 0; + int pre = 0; + int len = 0; + for (int i = 0; i != arr.length; i++) { + sum += arr[i]; + pre = getLessIndex(h, sum - k); + len = pre == -1 ? 0 : i - pre + 1; + res = Math.max(res, len); + } + return res; + } + + public static int getLessIndex(int[] arr, int num) { + int low = 0; + int high = arr.length - 1; + int mid = 0; + int res = -1; + while (low <= high) { + mid = (low + high) / 2; + if (arr[mid] >= num) { + res = mid; + high = mid - 1; + } else { + low = mid + 1; + } + } + return res; + } + + // for test + public static int[] generateRandomArray(int len, int maxValue) { + int[] res = new int[len]; + for (int i = 0; i != res.length; i++) { + res[i] = (int) (Math.random() * maxValue) - (maxValue / 3); + } + return res; + } + + public static void main(String[] args) { + System.out.println("test begin"); + for (int i = 0; i < 10000000; i++) { + int[] arr = generateRandomArray(10, 20); + int k = (int) (Math.random() * 20) - 5; + if (maxLengthAwesome(arr, k) != maxLength(arr, k)) { + System.out.println("Oops!"); + } + } + System.out.println("test finish"); + } + +} diff --git a/src/class40/Code04_AvgLessEqualValueLongestSubarray.java b/src/class40/Code04_AvgLessEqualValueLongestSubarray.java new file mode 100644 index 0000000..c56eef9 --- /dev/null +++ b/src/class40/Code04_AvgLessEqualValueLongestSubarray.java @@ -0,0 +1,152 @@ +package class40; + +import java.util.TreeMap; + +public class Code04_AvgLessEqualValueLongestSubarray { + + // 暴力解,时间复杂度O(N^3),用于做对数器 + public static int ways1(int[] arr, int v) { + int ans = 0; + for (int L = 0; L < arr.length; L++) { + for (int R = L; R < arr.length; R++) { + int sum = 0; + int k = R - L + 1; + for (int i = L; i <= R; i++) { + sum += arr[i]; + } + double avg = (double) sum / (double) k; + if (avg <= v) { + ans = Math.max(ans, k); + } + } + } + return ans; + } + + // 想实现的解法2,时间复杂度O(N*logN) + public static int ways2(int[] arr, int v) { + if (arr == null || arr.length == 0) { + return 0; + } + TreeMap origins = new TreeMap<>(); + int ans = 0; + int modify = 0; + for (int i = 0; i < arr.length; i++) { + int p1 = arr[i] <= v ? 1 : 0; + int p2 = 0; + int querry = -arr[i] - modify; + if (origins.floorKey(querry) != null) { + p2 = i - origins.get(origins.floorKey(querry)) + 1; + } + ans = Math.max(ans, Math.max(p1, p2)); + int curOrigin = -modify - v; + if (origins.floorKey(curOrigin) == null) { + origins.put(curOrigin, i); + } + modify += arr[i] - v; + } + return ans; + } + + // 想实现的解法3,时间复杂度O(N) + public static int ways3(int[] arr, int v) { + if (arr == null || arr.length == 0) { + return 0; + } + for (int i = 0; i < arr.length; i++) { + arr[i] -= v; + } + return maxLengthAwesome(arr, 0); + } + + // 找到数组中累加和<=k的最长子数组 + public static int maxLengthAwesome(int[] arr, int k) { + int N = arr.length; + int[] sums = new int[N]; + int[] ends = new int[N]; + sums[N - 1] = arr[N - 1]; + ends[N - 1] = N - 1; + for (int i = N - 2; i >= 0; i--) { + if (sums[i + 1] < 0) { + sums[i] = arr[i] + sums[i + 1]; + ends[i] = ends[i + 1]; + } else { + sums[i] = arr[i]; + ends[i] = i; + } + } + int end = 0; + int sum = 0; + int res = 0; + for (int i = 0; i < N; i++) { + while (end < N && sum + sums[end] <= k) { + sum += sums[end]; + end = ends[end] + 1; + } + res = Math.max(res, end - i); + if (end > i) { + sum -= arr[i]; + } else { + end = i + 1; + } + } + return res; + } + + // 用于测试 + public static int[] randomArray(int maxLen, int maxValue) { + int len = (int) (Math.random() * maxLen) + 1; + int[] ans = new int[len]; + for (int i = 0; i < len; i++) { + ans[i] = (int) (Math.random() * maxValue); + } + return ans; + } + + // 用于测试 + public static int[] copyArray(int[] arr) { + int[] ans = new int[arr.length]; + for (int i = 0; i < arr.length; i++) { + ans[i] = arr[i]; + } + return ans; + } + + // 用于测试 + 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) { + System.out.println("测试开始"); + int maxLen = 20; + int maxValue = 100; + int testTime = 500000; + for (int i = 0; i < testTime; i++) { + int[] arr = randomArray(maxLen, maxValue); + int value = (int) (Math.random() * maxValue); + int[] arr1 = copyArray(arr); + int[] arr2 = copyArray(arr); + int[] arr3 = copyArray(arr); + int ans1 = ways1(arr1, value); + int ans2 = ways2(arr2, value); + int ans3 = ways3(arr3, value); + if (ans1 != ans2 || ans1 != ans3) { + System.out.println("测试出错!"); + System.out.print("测试数组:"); + printArray(arr); + System.out.println("子数组平均值不小于 :" + value); + System.out.println("方法1得到的最大长度:" + ans1); + System.out.println("方法2得到的最大长度:" + ans2); + System.out.println("方法3得到的最大长度:" + ans3); + System.out.println("========================="); + } + } + System.out.println("测试结束"); + } + +} diff --git a/src/class41/Code01_NiuNiuSplitField.java b/src/class41/Code01_NiuNiuSplitField.java new file mode 100644 index 0000000..d98b48e --- /dev/null +++ b/src/class41/Code01_NiuNiuSplitField.java @@ -0,0 +1,179 @@ +package class41; + +import java.util.*; + +public class Code01_NiuNiuSplitField { + + // arr都是正数,0~i切的时候,怎么切最优,最优的结论生成一个数组返回 + public static int[] getAnswers(int[] arr) { + if (arr == null || arr.length < 1) { + return null; + } + // ans[i] 代表的含义: + // arr[0..i]切两块的各种方案中,哪一种方案能让左右两部份的累加和最小值,尽量大 + int[] ans = new int[arr.length]; + ans[0] = 0; + int best = 0;// 左 0..0 右 无 + for (int i = 1; i < arr.length; i++) { + while (best < i - 1 && getSplit(arr, best, i) < getSplit(arr, best + 1, i)) { + best++; + } + ans[i] = getSplit(arr, best, i); + } + return ans; + } + + public static int getSum(int[] arr, int i, int j) { + return 0; + } + + // arr[0..j] 如果我把切的这一刀定在m位置,左0..m,右m+1..j + public static int getSplit(int[] arr, int m, int j) { + return 0; + } + + public static int maxMinSumIn16(int[][] matrix) { + if (matrix == null || matrix.length < 4 || matrix[0].length < 4) { + return 0; + } + // help[i][j] 含义,左上角为(0,0) 右下角为(i,j)的子矩阵累加和是多少 + int[][] help = generateSumRecord(matrix); + // 通过help,得到任何子矩阵的累加和 + int col = matrix[0].length; + int res = Integer.MIN_VALUE; + // 3个for循环在暴力枚举纵向三刀 + for (int c1 = 0; c1 < col - 3; c1++) { + for (int c2 = c1 + 1; c2 < col - 2; c2++) { + for (int c3 = c2 + 1; c3 < col - 1; c3++) { + // c1 c2 c3 + res = Math.max(res, getBestDicision(help, c1, c2, c3)); + } + } + } + return res; + } + + // record[i][j] 左上角点0,0, 有效角点i、j , 该矩阵的累加和 + public static int[][] generateSumRecord(int[][] matrix) { + int row = matrix.length; + int col = matrix[0].length; + int[][] record = new int[row][col]; + record[0][0] = matrix[0][0]; + for (int i = 1; i < row; i++) { + record[i][0] = record[i - 1][0] + matrix[i][0]; + } + for (int j = 1; j < col; j++) { + record[0][j] = record[0][j - 1] + matrix[0][j]; + } + for (int i = 1; i < row; i++) { + for (int j = 1; j < col; j++) { + record[i][j] = record[i][j - 1] + record[i - 1][j] - record[i - 1][j - 1] + matrix[i][j]; + } + } + return record; + } + + // 忘掉原来的矩阵,只使用help + // 竖着三刀固定,c1,c2,c3 + // 所有横着切三刀的可能性中,那种切法能得到最好的结果,把结果返回 + public static int getBestDicision(int[][] help, int c1, int c2, int c3) { + // 0~i 切一刀,出来八块,最优指标,up[i] + int[] up = getUpSplitArray(help, c1, c2, c3); // 0行~i行 切一刀,分8块,min max + + // i ~ N-1 切一刀,出来八块,最优指标,down[i] + int[] down = getDownSplitArray(help, c1, c2, c3); // i~n-1 切一刀 + + int res = Integer.MIN_VALUE; + for (int mid = 1; mid < help.length - 2; mid++) { + res = Math.max(res, Math.min(up[mid], down[mid + 1])); + } + return res; + } + + public static int value(int[][] record, int c1, int c2, int c3, int prow, int crow) { + int value1 = area(record, prow, 0, crow, c1); + int value2 = area(record, prow, c1 + 1, crow, c2); + int value3 = area(record, prow, c2 + 1, crow, c3); + int value4 = area(record, prow, c3 + 1, crow, record[0].length - 1); + return Math.min(Math.min(value1, value2), Math.min(value3, value4)); + } + + public static int area(int[][] record, int i1, int j1, int i2, int j2) { + int all = record[i2][j2]; + int left = j1 > 0 ? record[i2][j1 - 1] : 0; + int up = i1 > 0 ? record[i1 - 1][j2] : 0; + int makeUp = (i1 > 0 && j1 > 0) ? record[i1 - 1][j1 - 1] : 0; + return all - left - up + makeUp; + } + + public static int[] getUpSplitArray(int[][] record, int c1, int c2, int c3) { + int size = record.length; + int[] up = new int[size]; + int split = 0; + up[1] = Math.min(value(record, c1, c2, c3, 0, 0), value(record, c1, c2, c3, 1, 1)); + for (int i = 2; i < size; i++) { + int minsMax = towSubMatrixMin(record, c1, c2, c3, 0, split, i); + while (split < i) { + if (split == i - 1) { + break; + } + int moved = towSubMatrixMin(record, c1, c2, c3, 0, split + 1, i); + if (moved < minsMax) { + break; + } else { + minsMax = moved; + split++; + } + } + up[i] = minsMax; + } + return up; + } + + public static int[] getDownSplitArray(int[][] record, int c1, int c2, int c3) { + int size = record.length; + int[] down = new int[size]; + int split = size - 1; + down[size - 2] = Math.min(value(record, c1, c2, c3, size - 2, size - 2), + value(record, c1, c2, c3, size - 1, size - 1)); + for (int i = size - 3; i >= 0; i--) { + int minsMax = towSubMatrixMin(record, c1, c2, c3, i, split - 1, size - 1); + while (split > i) { + if (split == i + 1) { + break; + } + int moved = towSubMatrixMin(record, c1, c2, c3, i, split - 2, size - 1); + if (moved < minsMax) { + break; + } else { + minsMax = moved; + split--; + } + } + down[i] = minsMax; + } + return down; + } + + public static int towSubMatrixMin(int[][] record, int c1, int c2, int c3, int i, int split, int j) { + return Math.min(value(record, c1, c2, c3, i, split), value(record, c1, c2, c3, split + 1, j)); + } + + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + while (in.hasNext()) { + int n = in.nextInt(); + int m = in.nextInt(); + int[][] matrix = new int[n][m]; + for (int i = 0; i < n; i++) { + char[] chas = in.next().toCharArray(); + for (int j = 0; j < m; j++) { + matrix[i][j] = chas[j] - '0'; + } + } + System.out.println(maxMinSumIn16(matrix)); + } + in.close(); + } + +} \ No newline at end of file diff --git a/src/class41/Code02_SplitArrayLargestSum.java b/src/class41/Code02_SplitArrayLargestSum.java new file mode 100644 index 0000000..0de1cea --- /dev/null +++ b/src/class41/Code02_SplitArrayLargestSum.java @@ -0,0 +1,124 @@ +package class41; + +public class Code02_SplitArrayLargestSum { + + public static int splitArray1(int[] nums, int m) { + return process(nums, 0, m); + } + + public static int process(int[] arr, int index, int part) { + if (index == arr.length) { + return 0; + } + if (part == 0) { + return -1; + } + int first = 0; + int min = Integer.MAX_VALUE; + for (int end = index; arr.length - end >= part; end++) { + first += arr[end]; + int next = process(arr, end + 1, part - 1); + if (next != -1) { + min = Math.min(min, Math.max(first, next)); + } + } + return min; + } + + public static int splitArray2(int[] nums, int M) { + int N = nums.length; + int[] help = new int[nums.length + 1]; + for (int i = 0; i < N; i++) { + help[i + 1] = help[i] + nums[i]; + } + int[][] dp = new int[N][M + 1]; + for (int i = 0; i < N; i++) { + dp[i][1] = help[i + 1] - help[0]; + } + for (int i = 1; i < Math.min(N, M); i++) { + dp[i][i + 1] = Math.max(dp[i - 1][i], nums[i]); + } + for (int i = 2; i < N; i++) { + for (int j = 2; j <= Math.min(i, M); j++) { + dp[i][j] = Integer.MAX_VALUE; + for (int k = i; k >= j - 1; k--) { + dp[i][j] = Math.min(dp[i][j], Math.max(dp[k - 1][j - 1], help[i + 1] - help[k])); + } + } + } + return dp[N - 1][M]; + } + + public static int splitArray3(int[] nums, int M) { + int N = nums.length; + int[] help = new int[nums.length + 1]; + for (int i = 0; i < N; i++) { + help[i + 1] = help[i] + nums[i]; + } + int[][] dp = new int[N][M + 1]; + int[][] best = new int[N][M + 1]; + for (int i = 0; i < N; i++) { + dp[i][1] = help[i + 1] - help[0]; + } + for (int i = 1; i < Math.min(N, M); i++) { + dp[i][i + 1] = Math.max(dp[i - 1][i], nums[i]); + best[i][i + 1] = i; + } + for (int i = 2; i < N; i++) { + for (int j = Math.min(i, M); j >= 2; j--) { + dp[i][j] = Integer.MAX_VALUE; + int left = best[i - 1][j]; + int right = j + 1 > M ? i : best[i][j + 1]; + for (int k = left; k <= right; k++) { + int curAns = Math.max(dp[k - 1][j - 1], help[i + 1] - help[k]); + if (dp[i][j] > curAns) { + dp[i][j] = curAns; + best[i][j] = k; + } + } + } + } + return dp[N - 1][M]; + } + + public static int splitArray4(int[] nums, int M) { + long sum = 0; + for (int i = 0; i < nums.length; i++) { + sum += nums[i]; + } + long l = 0; + long r = sum; + long ans = 0; + while (l <= r) { + long mid = (l + r) / 2; + long cur = getNeedParts(nums, mid); + if (cur <= M) { + ans = mid; + r = mid - 1; + } else { + l = mid + 1; + } + } + return (int) ans; + } + + public static int getNeedParts(int[] arr, long aim) { + for (int i = 0; i < arr.length; i++) { + if (arr[i] > aim) { + return Integer.MAX_VALUE; + } + } + int parts = 1; + int all = arr[0]; + for (int i = 1; i < arr.length; i++) { + if (all + arr[i] > aim) { + parts++; + all = arr[i]; + } else { + all += arr[i]; + } + } + return parts; + } + +} diff --git a/src/class42/Code01_ThrowChessPiecesProblem.java b/src/class42/Code01_ThrowChessPiecesProblem.java new file mode 100644 index 0000000..2aa44ff --- /dev/null +++ b/src/class42/Code01_ThrowChessPiecesProblem.java @@ -0,0 +1,194 @@ +package class42; + +public class Code01_ThrowChessPiecesProblem { + + public static int solution1(int nLevel, int kChess) { + if (nLevel < 1 || kChess < 1) { + return 0; + } + return Process1(nLevel, kChess); + } + + // rest还剩多少层楼需要去验证 + // k还有多少颗棋子能够使用 + // 一定要验证出最高的不会碎的楼层!但是每次都是坏运气。 + // 返回至少需要扔几次? + public static int Process1(int rest, int k) { + if (rest == 0) { + return 0; + } + if (k == 1) { + return rest; + } + int min = Integer.MAX_VALUE; + for (int i = 1; i != rest + 1; i++) { // 第一次扔的时候,仍在了i层 + min = Math.min(min, + Math.max(Process1(i - 1, k - 1), Process1(rest - i, k))); + } + return min + 1; + } + + public static int solution2(int nLevel, int kChess) { + if (nLevel < 1 || kChess < 1) { + return 0; + } + if (kChess == 1) { + return nLevel; + } + int[][] dp = new int[nLevel + 1][kChess + 1]; + for (int i = 1; i != dp.length; i++) { + dp[i][1] = i; + } + for (int i = 1; i != dp.length; i++) { + for (int j = 2; j != dp[0].length; j++) { + int min = Integer.MAX_VALUE; + for (int k = 1; k != i + 1; k++) { + min = Math.min(min, Math.max(dp[k - 1][j - 1], dp[i - k][j])); + } + dp[i][j] = min + 1; + } + } + return dp[nLevel][kChess]; + } + + public static int solution3(int nLevel, int kChess) { + if (nLevel < 1 || kChess < 1) { + return 0; + } + if (kChess == 1) { + return nLevel; + } + int[] preArr = new int[nLevel + 1]; + int[] curArr = new int[nLevel + 1]; + for (int i = 1; i != curArr.length; i++) { + curArr[i] = i; + } + for (int i = 1; i != kChess; i++) { + int[] tmp = preArr; + preArr = curArr; + curArr = tmp; + for (int j = 1; j != curArr.length; j++) { + int min = Integer.MAX_VALUE; + for (int k = 1; k != j + 1; k++) { + min = Math.min(min, Math.max(preArr[k - 1], curArr[j - k])); + } + curArr[j] = min + 1; + } + } + return curArr[curArr.length - 1]; + } + + public static int solution4(int nLevel, int kChess) { + if (nLevel < 1 || kChess < 1) { + return 0; + } + if (kChess == 1) { + return nLevel; + } + int[][] dp = new int[nLevel + 1][kChess + 1]; + for (int i = 1; i != dp.length; i++) { + dp[i][1] = i; + } + int[] cands = new int[kChess + 1]; + for (int i = 1; i != dp[0].length; i++) { + dp[1][i] = 1; + cands[i] = 1; + } + for (int i = 2; i < nLevel + 1; i++) { + for (int j = kChess; j > 1; j--) { + int min = Integer.MAX_VALUE; + int minEnum = cands[j]; + int maxEnum = j == kChess ? i / 2 + 1 : cands[j + 1]; + for (int k = minEnum; k < maxEnum + 1; k++) { + int cur = Math.max(dp[k - 1][j - 1], dp[i - k][j]); + if (cur <= min) { + min = cur; + cands[j] = k; + } + } + dp[i][j] = min + 1; + } + } + return dp[nLevel][kChess]; + } + + public static int solution5(int nLevel, int kChess) { + if (nLevel < 1 || kChess < 1) { + return 0; + } + int bsTimes = log2N(nLevel) + 1; + if (kChess >= bsTimes) { + return bsTimes; + } + int[] dp = new int[kChess]; + int res = 0; + while (true) { + res++; + int previous = 0; + for (int i = 0; i < dp.length; i++) { + int tmp = dp[i]; + dp[i] = dp[i] + previous + 1; + previous = tmp; + if (dp[i] >= nLevel) { + return res; + } + } + } + } + + public static int log2N(int n) { + int res = -1; + while (n != 0) { + res++; + n >>>= 1; + } + return res; + } + + public static void main(String[] args) { + System.out.println(solution1(21, 2)); + System.out.println(solution2(21, 2)); + System.out.println(solution3(21, 2)); + System.out.println(solution4(21, 2)); + System.out.println(solution5(21, 2)); + + System.out.println("=============="); + + System.out.println(solution2(105, 2)); + System.out.println(solution3(105, 2)); + System.out.println(solution4(105, 2)); + System.out.println(solution5(105, 2)); + + System.out.println("=============="); + + System.out.println(solution2(3000, 10)); + System.out.println(solution3(3000, 10)); + System.out.println(solution4(3000, 10)); + System.out.println(solution5(3000, 10)); + + System.out.println("=============="); + + System.out.println(solution2(6884, 5)); + System.out.println(solution3(6884, 5)); + System.out.println(solution4(6884, 5)); + System.out.println(solution5(6884, 5)); + + System.out.println("=============="); + + System.out.println(solution2(6885, 5)); + System.out.println(solution3(6885, 5)); + System.out.println(solution4(6885, 5)); + System.out.println(solution5(6885, 5)); + + System.out.println("=============="); + + int nLevel = 100000000; + int kChess = 10; + long start = System.currentTimeMillis(); + System.out.println(solution5(nLevel, kChess)); + long end = System.currentTimeMillis(); + System.out.println("cost time: " + (end - start) + " ms"); + + } + +} diff --git a/src/class42/Code02_PostOfficeProblem.java b/src/class42/Code02_PostOfficeProblem.java new file mode 100644 index 0000000..8f91c03 --- /dev/null +++ b/src/class42/Code02_PostOfficeProblem.java @@ -0,0 +1,215 @@ +package class42; + +import java.util.Arrays; + +public class Code02_PostOfficeProblem { + + public static int minDis1(int[] arr, int num) { + if (arr == null || arr.length < 2 || num < 1) { + return 0; + } + // record[L][R]表示如果arr[L...R]上只建立一个邮局,总距离最小是多少? + int[][] record = getRecord(arr); + int N = arr.length; + int[][] dp = new int[N][num + 1]; + // dp[...][0] 0个邮局的时候如何如何 + // dp[0][...] 0 + for (int i = 0; i < N; i++) { + // 0...i 1 + dp[i][1] = record[0][i]; + } + for (int i = 1; i < N; i++) { + for (int j = 2; j <= Math.min(num, i); j++) { + // dp[i][j] + // 枚举最后一个邮局负责的范围,K...i + // i..i + // i-1..i + // i-2..i + // 1....i + // 0....i 单列 + // 0...k-1 j-1个邮局 + + dp[i][j] = record[0][i]; + for (int k = i; k > 0; k--) { // 1 .... i + dp[i][j] = Math.min(dp[i][j], dp[k - 1][j - 1] + record[k][i]); + } + } + } + return dp[N - 1][num]; + } + + public static int minDis2(int[] arr, int num) { + if (arr == null || arr.length < 2 || num < 1) { + return 0; + } + // record[L][R]表示如果arr[L...R]上只建立一个邮局,总距离最小是多少? + int[][] record = getRecord(arr); + int N = arr.length; + int[][] dp = new int[N][num + 1]; + // dp[...][0] + // dp[0][...] 0..0 0 + // choose[0][..] 0 + // choose[i][j] 当时在求dp[i][j]的时候, + // 最右的邮局,如果是在负责k...i这一段的时候,取得的最优解,请把choose[i][j] = k + int[][] choose = new int[N][num + 1]; + for (int i = 0; i < N; i++) { + // 0..i 1个邮局 0...i 0 + dp[i][1] = record[0][i]; + } + for (int i = 1; i < N; i++) { + for (int j = Math.min(num, i); j >= 2; j--) { + int down = choose[i - 1][j]; + int up = j == Math.min(num, i) ? i : choose[i][j + 1]; + dp[i][j] = record[0][i]; + for (int k = Math.max(1, down); k <= Math.min(up, i); k++) { + if (dp[k - 1][j - 1] + record[k][i] < dp[i][j]) { + dp[i][j] = dp[k - 1][j - 1] + record[k][i]; + choose[i][j] = k; + } + } + } + } + return dp[N - 1][num]; + } + + public static int[][] getRecord(int[] arr) { + int N = arr.length; + int[][] record = new int[N][N]; + for (int L = 0; L < N; L++) { + for (int R = L + 1; R < N; R++) { + record[L][R] = record[L][R - 1] + arr[R] - arr[(L + R) >> 1]; + } + } + return record; + } + + public static int minDistances1(int[] arr, int num) { + if (arr == null || num < 1 || arr.length < num) { + return 0; + } + int[][] w = new int[arr.length + 1][arr.length + 1]; + for (int i = 0; i < arr.length; i++) { + for (int j = i + 1; j < arr.length; j++) { + w[i][j] = w[i][j - 1] + arr[j] - arr[(i + j) / 2]; + } + } + int[][] dp = new int[num][arr.length]; + for (int j = 0; j != arr.length; j++) { + dp[0][j] = w[0][j]; + } + for (int i = 1; i < num; i++) { + for (int j = i + 1; j < arr.length; j++) { + dp[i][j] = Integer.MAX_VALUE; + for (int k = 0; k <= j; k++) { + dp[i][j] = Math.min(dp[i][j], dp[i - 1][k] + w[k + 1][j]); + } + } + } + return dp[num - 1][arr.length - 1]; + } + + public static int minDistances2(int[] arr, int num) { + if (arr == null || num < 1 || arr.length < num) { + return 0; + } + int[][] w = new int[arr.length + 1][arr.length + 1]; + for (int i = 0; i < arr.length; i++) { + for (int j = i + 1; j < arr.length; j++) { + w[i][j] = w[i][j - 1] + arr[j] - arr[(i + j) / 2]; + } + } + int[][] dp = new int[num][arr.length]; + int[][] s = new int[num][arr.length]; + for (int j = 0; j != arr.length; j++) { + dp[0][j] = w[0][j]; + s[0][j] = 0; + } + int minK = 0; + int maxK = 0; + int cur = 0; + for (int i = 1; i < num; i++) { + for (int j = arr.length - 1; j > i; j--) { + minK = s[i - 1][j]; + maxK = j == arr.length - 1 ? arr.length - 1 : s[i][j + 1]; + dp[i][j] = Integer.MAX_VALUE; + for (int k = minK; k <= maxK; k++) { + cur = dp[i - 1][k] + w[k + 1][j]; + if (cur <= dp[i][j]) { + dp[i][j] = cur; + s[i][j] = k; + } + } + } + } + return dp[num - 1][arr.length - 1]; + } + + // for test + public static int[] getSortedArray(int len, int range) { + int[] arr = new int[len]; + for (int i = 0; i != len; i++) { + arr[i] = (int) (Math.random() * range); + } + Arrays.sort(arr); + return arr; + } + + // for test + public static void printArray(int[] arr) { + 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[] arr = { 1,3,8,10,12 }; + int num = 3; + System.out.println(minDis1(arr, num)); + System.out.println(minDistances1(arr, num)); + System.out.println(minDistances2(arr, num)); + + int times = 100; // test time + int len = 1000; // test array length + int range = 2000; // every number in [0,range) + int p = 50; // post office number max + long time1 = 0; // method1 all run time + long time2 = 0;// method2 all run time + long time3 = 0; + long start = 0; + long end = 0; + int res1 = 0; + int res2 = 0; + int res3 = 0; + for (int i = 0; i != times; i++) { + int office = (int) (Math.random() * p) + 1; + arr = getSortedArray(len, range); + start = System.currentTimeMillis(); + res1 = minDistances1(arr, office); + end = System.currentTimeMillis(); + time1 += end - start; + start = System.currentTimeMillis(); + res2 = minDis2(arr, office); + end = System.currentTimeMillis(); + time2 += end - start; + + start = System.currentTimeMillis(); + res3 = minDis1(arr, office); + end = System.currentTimeMillis(); + time3 += end - start; + if (res1 != res2 || res1 != res3) { + printArray(arr); + break; + } + if (i % 10 == 0) { + System.out.print(". "); + } + } + System.out.println(); + System.out.println("method1 all run time(ms): " + time1); + System.out.println("method2 all run time(ms): " + time2); + System.out.println("method3 all run time(ms): " + time3); + + } + +} diff --git a/src/class43/Code01_TSP.java b/src/class43/Code01_TSP.java new file mode 100644 index 0000000..87bd69c --- /dev/null +++ b/src/class43/Code01_TSP.java @@ -0,0 +1,295 @@ +package class43; + +import java.util.ArrayList; +import java.util.List; + +public class Code01_TSP { + + public static int t1(int[][] matrix) { + int N = matrix.length; // 0...N-1 + // set + // set.get(i) != null i这座城市在集合里 + // set.get(i) == null i这座城市不在集合里 + List set = new ArrayList<>(); + for (int i = 0; i < N; i++) { + set.add(1); + } + return func1(matrix, set, 0); + } + + // 任何两座城市之间的距离,可以在matrix里面拿到 + // set中表示着哪些城市的集合, + // start这座城一定在set里, + // 从start出发,要把set中所有的城市过一遍,最终回到0这座城市,最小距离是多少 + public static int func1(int[][] matrix, List set, int start) { + int cityNum = 0; + for (int i = 0; i < set.size(); i++) { + if (set.get(i) != null) { + cityNum++; + } + } + if (cityNum == 1) { + return matrix[start][0]; + } + // 不只start这一座城 + set.set(start, null); + int min = Integer.MAX_VALUE; + for (int i = 0; i < set.size(); i++) { + if (set.get(i) != null && i != start) { + // start -> i i... -> 0 + int cur = matrix[start][i] + func1(matrix, set, i); + min = Math.min(min, cur); + } + } + set.set(start, 1); + return min; + } + + public static int t2(int[][] matrix) { + int N = matrix.length; // 0...N-1 + // 7座城 1111111 + int allCity = (1 << N) - 1; + return f2(matrix, allCity, 0); + } + + // 任何两座城市之间的距离,可以在matrix里面拿到 + // set中表示着哪些城市的集合, + // start这座城一定在set里, + // 从start出发,要把set中所有的城市过一遍,最终回到0这座城市,最小距离是多少 + public static int f2(int[][] matrix, int cityStatus, int start) { + // cityStatus == cityStatux & (~cityStaus + 1) + + if (cityStatus == (cityStatus & (~cityStatus + 1))) { + return matrix[start][0]; + } + + // 把start位的1去掉, + cityStatus &= (~(1 << start)); + int min = Integer.MAX_VALUE; + // 枚举所有的城市 + for (int move = 0; move < matrix.length; move++) { + if (move != start && (cityStatus & (1 << move)) != 0) { + int cur = matrix[start][move] + f2(matrix, cityStatus, move); + min = Math.min(min, cur); + } + } + cityStatus |= (1 << start); + return min; + } + + public static int t3(int[][] matrix) { + int N = matrix.length; // 0...N-1 + // 7座城 1111111 + int allCity = (1 << N) - 1; + int[][] dp = new int[1 << N][N]; + for (int i = 0; i < (1 << N); i++) { + for (int j = 0; j < N; j++) { + dp[i][j] = -1; + } + } + return f3(matrix, allCity, 0, dp); + } + + // 任何两座城市之间的距离,可以在matrix里面拿到 + // set中表示着哪些城市的集合, + // start这座城一定在set里, + // 从start出发,要把set中所有的城市过一遍,最终回到0这座城市,最小距离是多少 + public static int f3(int[][] matrix, int cityStatus, int start, int[][] dp) { + if (dp[cityStatus][start] != -1) { + return dp[cityStatus][start]; + } + if (cityStatus == (cityStatus & (~cityStatus + 1))) { + dp[cityStatus][start] = matrix[start][0]; + } else { + // 把start位的1去掉, + cityStatus &= (~(1 << start)); + int min = Integer.MAX_VALUE; + // 枚举所有的城市 + for (int move = 0; move < matrix.length; move++) { + if (move != start && (cityStatus & (1 << move)) != 0) { + int cur = matrix[start][move] + f3(matrix, cityStatus, move, dp); + min = Math.min(min, cur); + } + } + cityStatus |= (1 << start); + dp[cityStatus][start] = min; + } + return dp[cityStatus][start]; + } + + public static int t4(int[][] matrix) { + int N = matrix.length; // 0...N-1 + int statusNums = 1 << N; + int[][] dp = new int[statusNums][N]; + + for (int status = 0; status < statusNums; status++) { + for (int start = 0; start < N; start++) { + if ((status & (1 << start)) != 0) { + if (status == (status & (~status + 1))) { + dp[status][start] = matrix[start][0]; + } else { + int min = Integer.MAX_VALUE; + // start 城市在status里去掉之后,的状态 + int preStatus = status & (~(1 << start)); + // start -> i + for (int i = 0; i < N; i++) { + if ((preStatus & (1 << i)) != 0) { + int cur = matrix[start][i] + dp[preStatus][i]; + min = Math.min(min, cur); + } + } + dp[status][start] = min; + } + } + } + } + return dp[statusNums - 1][0]; + } + + // matrix[i][j] -> i城市到j城市的距离 + public static int tsp1(int[][] matrix, int origin) { + if (matrix == null || matrix.length < 2 || origin < 0 || origin >= matrix.length) { + return 0; + } + // 要考虑的集合 + ArrayList cities = new ArrayList<>(); + // cities[0] != null 表示0城在集合里 + // cities[i] != null 表示i城在集合里 + for (int i = 0; i < matrix.length; i++) { + cities.add(1); + } + // null,1,1,1,1,1,1 + // origin城不参与集合 + cities.set(origin, null); + return process(matrix, origin, cities, origin); + } + + // matrix 所有距离,存在其中 + // origin 固定参数,唯一的目标 + // cities 要考虑的集合,一定不含有origin + // 当前来到的城市是谁,cur + public static int process(int[][] matrix, int aim, ArrayList cities, int cur) { + boolean hasCity = false; // 集团中还是否有城市 + int ans = Integer.MAX_VALUE; + for (int i = 0; i < cities.size(); i++) { + if (cities.get(i) != null) { + hasCity = true; + cities.set(i, null); + // matrix[cur][i] + f(i, 集团(去掉i) ) + ans = Math.min(ans, matrix[cur][i] + process(matrix, aim, cities, i)); + cities.set(i, 1); + } + } + return hasCity ? ans : matrix[cur][aim]; + } + + // cities 里,一定含有cur这座城 + // 解决的是,集合从cur出发,通过集合里所有的城市,最终来到aim,最短距离 + public static int process2(int[][] matrix, int aim, ArrayList cities, int cur) { + if (cities.size() == 1) { + return matrix[cur][aim]; + } + cities.set(cur, null); + int ans = Integer.MAX_VALUE; + for (int i = 0; i < cities.size(); i++) { + if (cities.get(i) != null) { + int dis = matrix[cur][i] + process2(matrix, aim, cities, i); + ans = Math.min(ans, dis); + } + } + cities.set(cur, 1); + return ans; + } + + public static int tsp2(int[][] matrix, int origin) { + if (matrix == null || matrix.length < 2 || origin < 0 || origin >= matrix.length) { + return 0; + } + int N = matrix.length - 1; // 除去origin之后是n-1个点 + int S = 1 << N; // 状态数量 + int[][] dp = new int[S][N]; + int icity = 0; + int kcity = 0; + for (int i = 0; i < N; i++) { + icity = i < origin ? i : i + 1; + // 00000000 i + dp[0][i] = matrix[icity][origin]; + } + for (int status = 1; status < S; status++) { + // 尝试每一种状态 status = 0 0 1 0 0 0 0 0 0 + // 下标 8 7 6 5 4 3 2 1 0 + for (int i = 0; i < N; i++) { + // i 枚举的出发城市 + dp[status][i] = Integer.MAX_VALUE; + if ((1 << i & status) != 0) { + // 如果i这座城是可以枚举的,i = 6 , i对应的原始城的编号,icity + icity = i < origin ? i : i + 1; + for (int k = 0; k < N; k++) { // i 这一步连到的点,k + if ((1 << k & status) != 0) { // i 这一步可以连到k + kcity = k < origin ? k : k + 1; // k对应的原始城的编号,kcity + dp[status][i] = Math.min(dp[status][i], dp[status ^ (1 << i)][k] + matrix[icity][kcity]); + } + } + } + } + } + int ans = Integer.MAX_VALUE; + for (int i = 0; i < N; i++) { + icity = i < origin ? i : i + 1; + ans = Math.min(ans, dp[S - 1][i] + matrix[origin][icity]); + } + return ans; + } + + public static int[][] generateGraph(int maxSize, int maxValue) { + int len = (int) (Math.random() * maxSize) + 1; + int[][] matrix = new int[len][len]; + for (int i = 0; i < len; i++) { + for (int j = 0; j < len; j++) { + matrix[i][j] = (int) (Math.random() * maxValue) + 1; + } + } + for (int i = 0; i < len; i++) { + matrix[i][i] = 0; + } + return matrix; + } + + public static void main(String[] args) { + int len = 10; + int value = 100; + System.out.println("功能测试开始"); + for (int i = 0; i < 20000; i++) { + int[][] matrix = generateGraph(len, value); + int origin = (int) (Math.random() * matrix.length); + int ans1 = t3(matrix); + int ans2 = t4(matrix); + int ans3 = tsp2(matrix, origin); + if (ans1 != ans2 || ans1 != ans3) { + System.out.println("fuck"); + } + } + System.out.println("功能测试结束"); + + len = 22; + System.out.println("性能测试开始,数据规模 : " + len); + int[][] matrix = new int[len][len]; + for (int i = 0; i < len; i++) { + for (int j = 0; j < len; j++) { + matrix[i][j] = (int) (Math.random() * value) + 1; + } + } + for (int i = 0; i < len; i++) { + matrix[i][i] = 0; + } + long start; + long end; + start = System.currentTimeMillis(); + t4(matrix); + end = System.currentTimeMillis(); + System.out.println("运行时间 : " + (end - start) + " 毫秒"); + System.out.println("性能测试结束"); + + } + +} diff --git a/src/class43/Code02_PavingTile.java b/src/class43/Code02_PavingTile.java new file mode 100644 index 0000000..18b3b6d --- /dev/null +++ b/src/class43/Code02_PavingTile.java @@ -0,0 +1,131 @@ +package class43; + +public class Code02_PavingTile { + + /* + * 2*M铺地的问题非常简单,这个是解决N*M铺地的问题 + */ + + public static int ways1(int N, int M) { + if (N < 1 || M < 1 || ((N * M) & 1) != 0) { + return 0; + } + if (N == 1 || M == 1) { + return 1; + } + int[] pre = new int[M]; // pre代表-1行的状况 + for (int i = 0; i < pre.length; i++) { + pre[i] = 1; + } + return process(pre, 0, N); + } + + // pre 表示level-1行的状态 + // level表示,正在level行做决定 + // N 表示一共有多少行 固定的 + // level-2行及其之上所有行,都摆满砖了 + // level做决定,让所有区域都满,方法数返回s + public static int process(int[] pre, int level, int N) { + if (level == N) { // base case + for (int i = 0; i < pre.length; i++) { + if (pre[i] == 0) { + return 0; + } + } + return 1; + } + + // 没到终止行,可以选择在当前的level行摆瓷砖 + int[] op = getOp(pre); + return dfs(op, 0, level, N); + } + + // op[i] == 0 可以考虑摆砖 + // op[i] == 1 只能竖着向上 + public static int dfs(int[] op, int col, int level, int N) { + // 在列上自由发挥,玩深度优先遍历,当col来到终止列,i行的决定做完了 + // 轮到i+1行,做决定 + if (col == op.length) { + return process(op, level + 1, N); + } + int ans = 0; + // col位置不横摆 + ans += dfs(op, col + 1, level, N); // col位置上不摆横转 + // col位置横摆, 向右 + if (col + 1 < op.length && op[col] == 0 && op[col + 1] == 0) { + op[col] = 1; + op[col + 1] = 1; + ans += dfs(op, col + 2, level, N); + op[col] = 0; + op[col + 1] = 0; + } + return ans; + } + + public static int[] getOp(int[] pre) { + int[] cur = new int[pre.length]; + for (int i = 0; i < pre.length; i++) { + cur[i] = pre[i] ^ 1; + } + return cur; + } + + public static int ways2(int N, int M) { + if (N < 1 || M < 1 || ((N * M) & 1) != 0) { + return 0; + } + if (N == 1 || M == 1) { + return 1; + } + int big = N > M ? N : M; + int small = big == N ? M : N; + // big * small + int sn = 1 << small; + int limit = sn - 1; // 全满状态 + int[] dp = new int[sn]; + dp[limit] = 1; // -1行全是满的 + // dp -1 行的状况 + // dp[0000] 0 + // dp[0001] 0 + // dp[1111] 1 + int[] cur = new int[sn]; // 当前行, 要算出所有状态下的解 + for (int level = 0; level < big; level++) { + for (int status = 0; status < sn; status++) { + if (dp[status] != 0) { // 状态出现了 + // 0...1100 + // 1...0011 + // 0...1111 + // 0...0011 + int op = (~status) & limit; + dfs(dp[status], op, 0, small - 1, cur); + } + } + for (int i = 0; i < sn; i++) { + dp[i] = 0; + } + int[] tmp = dp; + dp = cur; + cur = tmp; + } + return dp[limit]; + } + + public static void dfs(int way, int op, int index, int end, int[] cur) { + if (index == end) { + cur[op] += way; + } else { + dfs(way, op, index + 1, end, cur); + if (((3 << index) & op) == 0) { // 11 << index 可以放砖 + dfs(way, op | (3 << index), index + 1, end, cur); + } + } + } + + public static void main(String[] args) { + int N = 8; + int M = 8; + System.out.println(ways1(N, M)); + System.out.println(ways2(N, M)); + } + +} diff --git a/src/class43/Code03_CanIWin.java b/src/class43/Code03_CanIWin.java new file mode 100644 index 0000000..c0221c7 --- /dev/null +++ b/src/class43/Code03_CanIWin.java @@ -0,0 +1,64 @@ +package class43; + +// leetcode 464题 +public class Code03_CanIWin { + + // 这个是暴力尝试,思路是正确的,超时而已 + public static boolean canIWin1(int choose, int total) { + if (total == 0) { + return true; + } + if ((choose * (choose + 1) >> 1) < total) { + return false; + } + return process1(choose, 0, total); + } + + public static boolean process1(int choose, int status, int rest) { + if (rest <= 0) { + return false; + } + for (int i = 1; i <= choose; i++) { + if (((1 << i) & status) == 0) { + if (!process1(choose, (status | (1 << i)), rest - i)) { + return true; + } + } + } + return false; + } + + // 暴力尝试改动态规划而已 + public static boolean canIWin2(int choose, int total) { + if (total == 0) { + return true; + } + if ((choose * (choose + 1) >> 1) < total) { + return false; + } + int[] dp = new int[1 << (choose + 1)]; + return process2(choose, 0, total, dp); + } + + // 为什么明明status和rest是两个可变参数,却只用status来代表状态(也就是dp) + // 因为选了一批数字之后,得到的和一定是一样的,所以rest是由status决定的,所以rest不需要参与记忆化搜索 + public static boolean process2(int choose, int status, int rest, int[] dp) { + if (dp[status] != 0) { + return dp[status] == 1 ? true : false; + } + boolean ans = false; + if (rest > 0) { + for (int i = 1; i <= choose; i++) { + if (((1 << i) & status) == 0) { + if (!process2(choose, (status | (1 << i)), rest - i, dp)) { + ans = true; + break; + } + } + } + } + dp[status] = ans ? 1 : -1; + return ans; + } + +} diff --git a/src/class44/Code01_CreateMaximumNumber.java b/src/class44/Code01_CreateMaximumNumber.java new file mode 100644 index 0000000..bb5e182 --- /dev/null +++ b/src/class44/Code01_CreateMaximumNumber.java @@ -0,0 +1,248 @@ +package class44; + +// 测试链接: https://leetcode.com/problems/create-maximum-number/ +public class Code01_CreateMaximumNumber { + + public static int[] maxNumber1(int[] nums1, int[] nums2, int k) { + int len1 = nums1.length; + int len2 = nums2.length; + if (k < 0 || k > len1 + len2) { + return null; + } + int[] res = new int[k]; + int[][] dp1 = getdp(nums1); // 生成dp1这个表,以后从nums1中,只要固定拿N个数, + int[][] dp2 = getdp(nums2); + for (int get1 = Math.max(0, k - len2); get1 <= Math.min(k, len1); get1++) { + // arr1 挑 get1个,怎么得到一个最优结果 + int[] pick1 = maxPick(nums1, dp1, get1); + int[] pick2 = maxPick(nums2, dp2, k - get1); + int[] merge = merge(pick1, pick2); + res = preMoreThanLast(res, 0, merge, 0) ? res : merge; + } + return res; + } + + public static int[] merge(int[] nums1, int[] nums2) { + int k = nums1.length + nums2.length; + int[] ans = new int[k]; + for (int i = 0, j = 0, r = 0; r < k; ++r) { + ans[r] = preMoreThanLast(nums1, i, nums2, j) ? nums1[i++] : nums2[j++]; + } + return ans; + } + + public static boolean preMoreThanLast(int[] nums1, int i, int[] nums2, int j) { + while (i < nums1.length && j < nums2.length && nums1[i] == nums2[j]) { + i++; + j++; + } + return j == nums2.length || (i < nums1.length && nums1[i] > nums2[j]); + } + + public static int[] maxNumber2(int[] nums1, int[] nums2, int k) { + int len1 = nums1.length; + int len2 = nums2.length; + if (k < 0 || k > len1 + len2) { + return null; + } + int[] res = new int[k]; + int[][] dp1 = getdp(nums1); + int[][] dp2 = getdp(nums2); + for (int get1 = Math.max(0, k - len2); get1 <= Math.min(k, len1); get1++) { + int[] pick1 = maxPick(nums1, dp1, get1); + int[] pick2 = maxPick(nums2, dp2, k - get1); + int[] merge = mergeBySuffixArray(pick1, pick2); + res = moreThan(res, merge) ? res : merge; + } + return res; + } + + public static boolean moreThan(int[] pre, int[] last) { + int i = 0; + int j = 0; + while (i < pre.length && j < last.length && pre[i] == last[j]) { + i++; + j++; + } + return j == last.length || (i < pre.length && pre[i] > last[j]); + } + + public static int[] mergeBySuffixArray(int[] nums1, int[] nums2) { + int size1 = nums1.length; + int size2 = nums2.length; + int[] nums = new int[size1 + 1 + size2]; + for (int i = 0; i < size1; i++) { + nums[i] = nums1[i] + 2; + } + nums[size1] = 1; + for (int j = 0; j < size2; j++) { + nums[j + size1 + 1] = nums2[j] + 2; + } + DC3 dc3 = new DC3(nums, 11); + int[] rank = dc3.rank; + int[] ans = new int[size1 + size2]; + int i = 0; + int j = 0; + int r = 0; + while (i < size1 && j < size2) { + ans[r++] = rank[i] > rank[j + size1 + 1] ? nums1[i++] : nums2[j++]; + } + while (i < size1) { + ans[r++] = nums1[i++]; + } + while (j < size2) { + ans[r++] = nums2[j++]; + } + return ans; + } + + public static class DC3 { + + public int[] sa; + public int[] rank; + + public DC3(int[] nums, int max) { + sa = sa(nums, max); + rank = rank(); + } + + private int[] sa(int[] nums, int max) { + int n = nums.length; + int[] arr = new int[n + 3]; + for (int i = 0; i < n; i++) { + arr[i] = nums[i]; + } + return skew(arr, n, max); + } + + private int[] skew(int[] nums, int n, int K) { + int n0 = (n + 2) / 3, n1 = (n + 1) / 3, n2 = n / 3, n02 = n0 + n2; + int[] s12 = new int[n02 + 3], sa12 = new int[n02 + 3]; + for (int i = 0, j = 0; i < n + (n0 - n1); ++i) { + if (0 != i % 3) { + s12[j++] = i; + } + } + radixPass(nums, s12, sa12, 2, n02, K); + radixPass(nums, sa12, s12, 1, n02, K); + radixPass(nums, s12, sa12, 0, n02, K); + int name = 0, c0 = -1, c1 = -1, c2 = -1; + for (int i = 0; i < n02; ++i) { + if (c0 != nums[sa12[i]] || c1 != nums[sa12[i] + 1] || c2 != nums[sa12[i] + 2]) { + name++; + c0 = nums[sa12[i]]; + c1 = nums[sa12[i] + 1]; + c2 = nums[sa12[i] + 2]; + } + if (1 == sa12[i] % 3) { + s12[sa12[i] / 3] = name; + } else { + s12[sa12[i] / 3 + n0] = name; + } + } + if (name < n02) { + sa12 = skew(s12, n02, name); + for (int i = 0; i < n02; i++) { + s12[sa12[i]] = i + 1; + } + } else { + for (int i = 0; i < n02; i++) { + sa12[s12[i] - 1] = i; + } + } + int[] s0 = new int[n0], sa0 = new int[n0]; + for (int i = 0, j = 0; i < n02; i++) { + if (sa12[i] < n0) { + s0[j++] = 3 * sa12[i]; + } + } + radixPass(nums, s0, sa0, 0, n0, K); + int[] sa = new int[n]; + for (int p = 0, t = n0 - n1, k = 0; k < n; k++) { + int i = sa12[t] < n0 ? sa12[t] * 3 + 1 : (sa12[t] - n0) * 3 + 2; + int j = sa0[p]; + if (sa12[t] < n0 ? leq(nums[i], s12[sa12[t] + n0], nums[j], s12[j / 3]) + : leq(nums[i], nums[i + 1], s12[sa12[t] - n0 + 1], nums[j], nums[j + 1], s12[j / 3 + n0])) { + sa[k] = i; + t++; + if (t == n02) { + for (k++; p < n0; p++, k++) { + sa[k] = sa0[p]; + } + } + } else { + sa[k] = j; + p++; + if (p == n0) { + for (k++; t < n02; t++, k++) { + sa[k] = sa12[t] < n0 ? sa12[t] * 3 + 1 : (sa12[t] - n0) * 3 + 2; + } + } + } + } + return sa; + } + + private void radixPass(int[] nums, int[] input, int[] output, int offset, int n, int k) { + int[] cnt = new int[k + 1]; + for (int i = 0; i < n; ++i) { + cnt[nums[input[i] + offset]]++; + } + for (int i = 0, sum = 0; i < cnt.length; ++i) { + int t = cnt[i]; + cnt[i] = sum; + sum += t; + } + for (int i = 0; i < n; ++i) { + output[cnt[nums[input[i] + offset]]++] = input[i]; + } + } + + private boolean leq(int a1, int a2, int b1, int b2) { + return a1 < b1 || (a1 == b1 && a2 <= b2); + } + + private boolean leq(int a1, int a2, int a3, int b1, int b2, int b3) { + return a1 < b1 || (a1 == b1 && leq(a2, a3, b2, b3)); + } + + private int[] rank() { + int n = sa.length; + int[] ans = new int[n]; + for (int i = 0; i < n; i++) { + ans[sa[i]] = i + 1; + } + return ans; + } + + } + + public static int[][] getdp(int[] arr) { + int size = arr.length; // 0~N-1 + int pick = arr.length + 1; // 1 ~ N + int[][] dp = new int[size][pick]; + // get 不从0开始,因为拿0个无意义 + // get 1 + for (int get = 1; get < pick; get++) { // 1 ~ N + int maxIndex = size - get; + // i~N-1 + for (int i = size - get; i >= 0; i--) { + if (arr[i] >= arr[maxIndex]) { + maxIndex = i; + } + dp[i][get] = maxIndex; + } + } + return dp; + } + + public static int[] maxPick(int[] arr, int[][] dp, int pick) { + int[] res = new int[pick]; + for (int resIndex = 0, dpRow = 0; pick > 0; pick--, resIndex++) { + res[resIndex] = arr[dp[dpRow][pick]]; + dpRow = dp[dpRow][pick] + 1; + } + return res; + } + +} diff --git a/src/class44/Code02_LastSubstringInLexicographicalOrder.java b/src/class44/Code02_LastSubstringInLexicographicalOrder.java new file mode 100644 index 0000000..186fb06 --- /dev/null +++ b/src/class44/Code02_LastSubstringInLexicographicalOrder.java @@ -0,0 +1,148 @@ +package class44; + +// 测试链接: https://leetcode.com/problems/last-substring-in-lexicographical-order/ +public class Code02_LastSubstringInLexicographicalOrder { + + public static String lastSubstring(String s) { + if (s == null || s.length() == 0) { + return s; + } + int N = s.length(); + char[] str = s.toCharArray(); + int min = Integer.MAX_VALUE; + int max = Integer.MIN_VALUE; + for (char cha : str) { + min = Math.min(min, cha); + max = Math.max(max, cha); + } + int[] arr = new int[N]; + for (int i = 0; i < N; i++) { + arr[i] = str[i] - min + 1; + } + DC3 dc3 = new DC3(arr, max - min + 1); + return s.substring(dc3.sa[N - 1]); + } + + public static class DC3 { + + public int[] sa; + + public int[] rank; + + public DC3(int[] nums, int max) { + sa = sa(nums, max); + rank = rank(); + } + + private int[] sa(int[] nums, int max) { + int n = nums.length; + int[] arr = new int[n + 3]; + for (int i = 0; i < n; i++) { + arr[i] = nums[i]; + } + return skew(arr, n, max); + } + + private int[] skew(int[] nums, int n, int K) { + int n0 = (n + 2) / 3, n1 = (n + 1) / 3, n2 = n / 3, n02 = n0 + n2; + int[] s12 = new int[n02 + 3], sa12 = new int[n02 + 3]; + for (int i = 0, j = 0; i < n + (n0 - n1); ++i) { + if (0 != i % 3) { + s12[j++] = i; + } + } + radixPass(nums, s12, sa12, 2, n02, K); + radixPass(nums, sa12, s12, 1, n02, K); + radixPass(nums, s12, sa12, 0, n02, K); + int name = 0, c0 = -1, c1 = -1, c2 = -1; + for (int i = 0; i < n02; ++i) { + if (c0 != nums[sa12[i]] || c1 != nums[sa12[i] + 1] || c2 != nums[sa12[i] + 2]) { + name++; + c0 = nums[sa12[i]]; + c1 = nums[sa12[i] + 1]; + c2 = nums[sa12[i] + 2]; + } + if (1 == sa12[i] % 3) { + s12[sa12[i] / 3] = name; + } else { + s12[sa12[i] / 3 + n0] = name; + } + } + if (name < n02) { + sa12 = skew(s12, n02, name); + for (int i = 0; i < n02; i++) { + s12[sa12[i]] = i + 1; + } + } else { + for (int i = 0; i < n02; i++) { + sa12[s12[i] - 1] = i; + } + } + int[] s0 = new int[n0], sa0 = new int[n0]; + for (int i = 0, j = 0; i < n02; i++) { + if (sa12[i] < n0) { + s0[j++] = 3 * sa12[i]; + } + } + radixPass(nums, s0, sa0, 0, n0, K); + int[] sa = new int[n]; + for (int p = 0, t = n0 - n1, k = 0; k < n; k++) { + int i = sa12[t] < n0 ? sa12[t] * 3 + 1 : (sa12[t] - n0) * 3 + 2; + int j = sa0[p]; + if (sa12[t] < n0 ? leq(nums[i], s12[sa12[t] + n0], nums[j], s12[j / 3]) + : leq(nums[i], nums[i + 1], s12[sa12[t] - n0 + 1], nums[j], nums[j + 1], s12[j / 3 + n0])) { + sa[k] = i; + t++; + if (t == n02) { + for (k++; p < n0; p++, k++) { + sa[k] = sa0[p]; + } + } + } else { + sa[k] = j; + p++; + if (p == n0) { + for (k++; t < n02; t++, k++) { + sa[k] = sa12[t] < n0 ? sa12[t] * 3 + 1 : (sa12[t] - n0) * 3 + 2; + } + } + } + } + return sa; + } + + private void radixPass(int[] nums, int[] input, int[] output, int offset, int n, int k) { + int[] cnt = new int[k + 1]; + for (int i = 0; i < n; ++i) { + cnt[nums[input[i] + offset]]++; + } + for (int i = 0, sum = 0; i < cnt.length; ++i) { + int t = cnt[i]; + cnt[i] = sum; + sum += t; + } + for (int i = 0; i < n; ++i) { + output[cnt[nums[input[i] + offset]]++] = input[i]; + } + } + + private boolean leq(int a1, int a2, int b1, int b2) { + return a1 < b1 || (a1 == b1 && a2 <= b2); + } + + private boolean leq(int a1, int a2, int a3, int b1, int b2, int b3) { + return a1 < b1 || (a1 == b1 && leq(a2, a3, b2, b3)); + } + + private int[] rank() { + int n = sa.length; + int[] ans = new int[n]; + for (int i = 0; i < n; i++) { + ans[sa[i]] = i + 1; + } + return ans; + } + + } + +} diff --git a/src/class44/Code03_InsertS2MakeMostAlphabeticalOrder.java b/src/class44/Code03_InsertS2MakeMostAlphabeticalOrder.java new file mode 100644 index 0000000..f533492 --- /dev/null +++ b/src/class44/Code03_InsertS2MakeMostAlphabeticalOrder.java @@ -0,0 +1,249 @@ +package class44; + +public class Code03_InsertS2MakeMostAlphabeticalOrder { + + // 暴力方法 + public static String right(String s1, String s2) { + if (s1 == null || s1.length() == 0) { + return s2; + } + if (s2 == null || s2.length() == 0) { + return s1; + } + String p1 = s1 + s2; + String p2 = s2 + s1; + String ans = p1.compareTo(p2) > 0 ? p1 : p2; + for (int end = 1; end < s1.length(); end++) { + String cur = s1.substring(0, end) + s2 + s1.substring(end); + if (cur.compareTo(ans) > 0) { + ans = cur; + } + } + return ans; + } + + // 正式方法 + public static String max(String s1, String s2) { + if (s1 == null || s1.length() == 0) { + return s2; + } + if (s2 == null || s2.length() == 0) { + return s1; + } + char[] str1 = s1.toCharArray(); + char[] str2 = s2.toCharArray(); + int N = str1.length; + int M = str2.length; + int min = str1[0]; + int max = str1[0]; + for (int i = 1; i < N; i++) { + min = Math.min(min, str1[i]); + max = Math.max(max, str1[i]); + } + for (int i = 0; i < M; i++) { + min = Math.min(min, str2[i]); + max = Math.max(max, str2[i]); + } + int[] all = new int[N + M + 1]; + int index = 0; + for (int i = 0; i < N; i++) { + all[index++] = str1[i] - min + 2; + } + all[index++] = 1; + for (int i = 0; i < M; i++) { + all[index++] = str2[i] - min + 2; + } + DC3 dc3 = new DC3(all, max - min + 2); + int[] rank = dc3.rank; + int comp = N + 1; + for (int i = 0; i < N; i++) { + if (rank[i] < rank[comp]) { + int best = whereSplit(s1, s2, i); + return s1.substring(0, best) + s2 + s1.substring(best); + } + } + return s1 + s2; + } + + public static class DC3 { + + public int[] sa; + public int[] rank; + + public DC3(int[] nums, int max) { + sa = sa(nums, max); + rank = rank(); + } + + private int[] sa(int[] nums, int max) { + int n = nums.length; + int[] arr = new int[n + 3]; + for (int i = 0; i < n; i++) { + arr[i] = nums[i]; + } + return skew(arr, n, max); + } + + private int[] skew(int[] nums, int n, int K) { + int n0 = (n + 2) / 3, n1 = (n + 1) / 3, n2 = n / 3, n02 = n0 + n2; + int[] s12 = new int[n02 + 3], sa12 = new int[n02 + 3]; + for (int i = 0, j = 0; i < n + (n0 - n1); ++i) { + if (0 != i % 3) { + s12[j++] = i; + } + } + radixPass(nums, s12, sa12, 2, n02, K); + radixPass(nums, sa12, s12, 1, n02, K); + radixPass(nums, s12, sa12, 0, n02, K); + int name = 0, c0 = -1, c1 = -1, c2 = -1; + for (int i = 0; i < n02; ++i) { + if (c0 != nums[sa12[i]] || c1 != nums[sa12[i] + 1] || c2 != nums[sa12[i] + 2]) { + name++; + c0 = nums[sa12[i]]; + c1 = nums[sa12[i] + 1]; + c2 = nums[sa12[i] + 2]; + } + if (1 == sa12[i] % 3) { + s12[sa12[i] / 3] = name; + } else { + s12[sa12[i] / 3 + n0] = name; + } + } + if (name < n02) { + sa12 = skew(s12, n02, name); + for (int i = 0; i < n02; i++) { + s12[sa12[i]] = i + 1; + } + } else { + for (int i = 0; i < n02; i++) { + sa12[s12[i] - 1] = i; + } + } + int[] s0 = new int[n0], sa0 = new int[n0]; + for (int i = 0, j = 0; i < n02; i++) { + if (sa12[i] < n0) { + s0[j++] = 3 * sa12[i]; + } + } + radixPass(nums, s0, sa0, 0, n0, K); + int[] sa = new int[n]; + for (int p = 0, t = n0 - n1, k = 0; k < n; k++) { + int i = sa12[t] < n0 ? sa12[t] * 3 + 1 : (sa12[t] - n0) * 3 + 2; + int j = sa0[p]; + if (sa12[t] < n0 ? leq(nums[i], s12[sa12[t] + n0], nums[j], s12[j / 3]) + : leq(nums[i], nums[i + 1], s12[sa12[t] - n0 + 1], nums[j], nums[j + 1], s12[j / 3 + n0])) { + sa[k] = i; + t++; + if (t == n02) { + for (k++; p < n0; p++, k++) { + sa[k] = sa0[p]; + } + } + } else { + sa[k] = j; + p++; + if (p == n0) { + for (k++; t < n02; t++, k++) { + sa[k] = sa12[t] < n0 ? sa12[t] * 3 + 1 : (sa12[t] - n0) * 3 + 2; + } + } + } + } + return sa; + } + + private void radixPass(int[] nums, int[] input, int[] output, int offset, int n, int k) { + int[] cnt = new int[k + 1]; + for (int i = 0; i < n; ++i) { + cnt[nums[input[i] + offset]]++; + } + for (int i = 0, sum = 0; i < cnt.length; ++i) { + int t = cnt[i]; + cnt[i] = sum; + sum += t; + } + for (int i = 0; i < n; ++i) { + output[cnt[nums[input[i] + offset]]++] = input[i]; + } + } + + private boolean leq(int a1, int a2, int b1, int b2) { + return a1 < b1 || (a1 == b1 && a2 <= b2); + } + + private boolean leq(int a1, int a2, int a3, int b1, int b2, int b3) { + return a1 < b1 || (a1 == b1 && leq(a2, a3, b2, b3)); + } + + private int[] rank() { + int n = sa.length; + int[] ans = new int[n]; + for (int i = 0; i < n; i++) { + ans[sa[i]] = i + 1; + } + return ans; + } + + } + + public static int whereSplit(String str1, String str2, int first) { + int M = str2.length(); + String bestPrefix = str2; + int bestSplit = first; + for (int i = first + 1, j = M - 1; i <= Math.min(str1.length(), first + M); i++, j--) { + String curPrefix = str1.substring(first, i) + str2.substring(0, j); + if (curPrefix.compareTo(bestPrefix) >= 0) { + bestPrefix = curPrefix; + bestSplit = i; + } + } + return bestSplit; + } + + // for test + public static String randomNumberString(int len, int range) { + char[] str = new char[len]; + for (int i = 0; i < len; i++) { + str[i] = (char) ((int) (Math.random() * range) + '0'); + } + return String.valueOf(str); + } + + // for test + public static void main(String[] args) { + int range = 10; + int len = 50; + int testTime = 100000; + System.out.println("功能测试开始"); + for (int i = 0; i < testTime; i++) { + int s1Len = (int) (Math.random() * len); + int s2Len = (int) (Math.random() * len); + String s1 = randomNumberString(s1Len, range); + String s2 = randomNumberString(s2Len, range); + String ans1 = right(s1, s2); + String ans2 = max(s1, s2); + if (!ans1.equals(ans2)) { + System.out.println("Oops!"); + System.out.println(s1); + System.out.println(s2); + System.out.println(ans1); + System.out.println(ans2); + break; + } + } + System.out.println("功能测试结束"); + System.out.println("=========="); + System.out.println("性能测试开始"); + + int s1Len = 1000000; + int s2Len = 50; + String s1 = randomNumberString(s1Len, range); + String s2 = randomNumberString(s2Len, range); + long start = System.currentTimeMillis(); + max(s1, s2); + long end = System.currentTimeMillis(); + System.out.println("运行时间 : " + (end - start) + " ms"); + System.out.println("性能测试结束"); + } + +} diff --git a/src/class44/DC3.java b/src/class44/DC3.java new file mode 100644 index 0000000..6a43e3b --- /dev/null +++ b/src/class44/DC3.java @@ -0,0 +1,123 @@ +package class44; + +public class DC3 { + + public int[] sa; + + public int[] rank; + + public DC3(int[] nums, int max) { + sa = sa(nums, max); + rank = rank(); + } + + private int[] sa(int[] nums, int max) { + int n = nums.length; + int[] arr = new int[n + 3]; + for (int i = 0; i < n; i++) { + arr[i] = nums[i]; + } + return skew(arr, n, max); + } + + private int[] skew(int[] nums, int n, int K) { + int n0 = (n + 2) / 3, n1 = (n + 1) / 3, n2 = n / 3, n02 = n0 + n2; + int[] s12 = new int[n02 + 3], sa12 = new int[n02 + 3]; + for (int i = 0, j = 0; i < n + (n0 - n1); ++i) { + if (0 != i % 3) { + s12[j++] = i; + } + } + radixPass(nums, s12, sa12, 2, n02, K); + radixPass(nums, sa12, s12, 1, n02, K); + radixPass(nums, s12, sa12, 0, n02, K); + int name = 0, c0 = -1, c1 = -1, c2 = -1; + for (int i = 0; i < n02; ++i) { + if (c0 != nums[sa12[i]] || c1 != nums[sa12[i] + 1] || c2 != nums[sa12[i] + 2]) { + name++; + c0 = nums[sa12[i]]; + c1 = nums[sa12[i] + 1]; + c2 = nums[sa12[i] + 2]; + } + if (1 == sa12[i] % 3) { + s12[sa12[i] / 3] = name; + } else { + s12[sa12[i] / 3 + n0] = name; + } + } + if (name < n02) { + sa12 = skew(s12, n02, name); + for (int i = 0; i < n02; i++) { + s12[sa12[i]] = i + 1; + } + } else { + for (int i = 0; i < n02; i++) { + sa12[s12[i] - 1] = i; + } + } + int[] s0 = new int[n0], sa0 = new int[n0]; + for (int i = 0, j = 0; i < n02; i++) { + if (sa12[i] < n0) { + s0[j++] = 3 * sa12[i]; + } + } + radixPass(nums, s0, sa0, 0, n0, K); + int[] sa = new int[n]; + for (int p = 0, t = n0 - n1, k = 0; k < n; k++) { + int i = sa12[t] < n0 ? sa12[t] * 3 + 1 : (sa12[t] - n0) * 3 + 2; + int j = sa0[p]; + if (sa12[t] < n0 ? leq(nums[i], s12[sa12[t] + n0], nums[j], s12[j / 3]) + : leq(nums[i], nums[i + 1], s12[sa12[t] - n0 + 1], nums[j], nums[j + 1], s12[j / 3 + n0])) { + sa[k] = i; + t++; + if (t == n02) { + for (k++; p < n0; p++, k++) { + sa[k] = sa0[p]; + } + } + } else { + sa[k] = j; + p++; + if (p == n0) { + for (k++; t < n02; t++, k++) { + sa[k] = sa12[t] < n0 ? sa12[t] * 3 + 1 : (sa12[t] - n0) * 3 + 2; + } + } + } + } + return sa; + } + + private void radixPass(int[] nums, int[] input, int[] output, int offset, int n, int k) { + int[] cnt = new int[k + 1]; + for (int i = 0; i < n; ++i) { + cnt[nums[input[i] + offset]]++; + } + for (int i = 0, sum = 0; i < cnt.length; ++i) { + int t = cnt[i]; + cnt[i] = sum; + sum += t; + } + for (int i = 0; i < n; ++i) { + output[cnt[nums[input[i] + offset]]++] = input[i]; + } + } + + private boolean leq(int a1, int a2, int b1, int b2) { + return a1 < b1 || (a1 == b1 && a2 <= b2); + } + + private boolean leq(int a1, int a2, int a3, int b1, int b2, int b3) { + return a1 < b1 || (a1 == b1 && leq(a2, a3, b2, b3)); + } + + private int[] rank() { + int n = sa.length; + int[] ans = new int[n]; + for (int i = 0; i < n; i++) { + ans[sa[i]] = i + 1; + } + return ans; + } + +} \ No newline at end of file diff --git a/src/class44/DC3_Algorithm.pdf b/src/class44/DC3_Algorithm.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f053a6749606ad2ae8abbdffb6bc2a959c2f1617 GIT binary patch literal 192716 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 literal 0 HcmV?d00001 diff --git a/src/class45/Code01_BurstBalloons.java b/src/class45/Code01_BurstBalloons.java new file mode 100644 index 0000000..004fd4d --- /dev/null +++ b/src/class45/Code01_BurstBalloons.java @@ -0,0 +1,85 @@ +package class45; + +public class Code01_BurstBalloons { + + public static int maxCoins1(int[] arr) { + if (arr == null || arr.length == 0) { + return 0; + } + if (arr.length == 1) { + return arr[0]; + } + int N = arr.length; + int[] help = new int[N + 2]; + help[0] = 1; + help[N + 1] = 1; + for (int i = 0; i < N; i++) { + help[i + 1] = arr[i]; + } + return process(help, 1, N); + } + + // 打爆arr[L..R]范围上的所有气球,返回最大的分数 + // 假设arr[L-1]和arr[R+1]一定没有被打爆 + public static int process(int[] arr, int L, int R) { + if (L == R) {// 如果arr[L..R]范围上只有一个气球,直接打爆即可 + return arr[L - 1] * arr[L] * arr[R + 1]; + } + // 最后打爆arr[L]的方案,和最后打爆arr[R]的方案,先比较一下 + int max = Math.max( + arr[L - 1] * arr[L] * arr[R + 1] + process(arr, L + 1, R), + arr[L - 1] * arr[R] * arr[R + 1] + process(arr, L, R - 1)); + // 尝试中间位置的气球最后被打爆的每一种方案 + for (int i = L + 1; i < R; i++) { + max = Math.max(max, + arr[L - 1] * arr[i] * arr[R + 1] + process(arr, L, i - 1) + + process(arr, i + 1, R)); + } + return max; + } + + public static int maxCoins2(int[] arr) { + if (arr == null || arr.length == 0) { + return 0; + } + if (arr.length == 1) { + return arr[0]; + } + int N = arr.length; + int[] help = new int[N + 2]; + help[0] = 1; + help[N + 1] = 1; + for (int i = 0; i < N; i++) { + help[i + 1] = arr[i]; + } + int[][] dp = new int[N + 2][N + 2]; + for (int i = 1; i <= N; i++) { + dp[i][i] = help[i - 1] * help[i] * help[i + 1]; + System.out.println(dp[i][i]); + } + for (int L = N; L >= 1; L--) { + for (int R = L + 1; R <= N; R++) { + // 求解dp[L][R],表示help[L..R]上打爆所有气球的最大分数 + // 最后打爆help[L]的方案 + int finalL = help[L - 1] * help[L] * help[R + 1] + dp[L + 1][R]; + // 最后打爆help[R]的方案 + int finalR = help[L - 1] * help[R] * help[R + 1] + dp[L][R - 1]; + // 最后打爆help[L]的方案,和最后打爆help[R]的方案,先比较一下 + dp[L][R] = Math.max(finalL, finalR); + // 尝试中间位置的气球最后被打爆的每一种方案 + for (int i = L + 1; i < R; i++) { + dp[L][R] = Math.max(dp[L][R], help[L - 1] * help[i] + * help[R + 1] + dp[L][i - 1] + dp[i + 1][R]); + } + } + } + return dp[1][N]; + } + + public static void main(String[] args) { + int[] arr = { 4, 2, 3, 5, 1, 6 }; + System.out.println(maxCoins1(arr)); + System.out.println(maxCoins2(arr)); + } + +} diff --git a/src/class45/Code02_RemoveBoxes.java b/src/class45/Code02_RemoveBoxes.java new file mode 100644 index 0000000..6a9f2f8 --- /dev/null +++ b/src/class45/Code02_RemoveBoxes.java @@ -0,0 +1,38 @@ +package class45; + +public class Code02_RemoveBoxes { + + public int removeBoxes(int[] boxes) { + int N = boxes.length; + int[][][] dp = new int[N][N][N]; + return process(boxes, 0, N - 1, 0, dp); + } + + // boxes[L....R],前面还跟着K个boxes[L] + // 前面的包袱和L...R所有的数都消掉,最好得分是什么 + public static int process(int[] boxes, int L, int R, int K, int[][][] dp) { + if (L > R) { + return 0; + } + if (dp[L][R][K] != 0) { + return dp[L][R][K]; + } + if (L == R) { + dp[L][R][K] = (K + 1) * (K + 1); + return dp[L][R][K]; + } + while (L < R && boxes[L] == boxes[L + 1]) { + L++; + K++; + } + int ans = (K + 1) * (K + 1) + process(boxes, L + 1, R, 0, dp); + for (int m = L + 1; m <= R; m++) { + if (boxes[L] == boxes[m]) { + ans = Math.max(ans, process(boxes, L + 1, m - 1, 0, dp) + process(boxes, m, R, K + 1, dp)); + } + } + dp[L][R][K] = ans; + return ans; + } + +} diff --git a/src/class45/Code03_StrangePrinter.java b/src/class45/Code03_StrangePrinter.java new file mode 100644 index 0000000..cfcf7ca --- /dev/null +++ b/src/class45/Code03_StrangePrinter.java @@ -0,0 +1,33 @@ +package class45; + +public class Code03_StrangePrinter { + + public static int strangePrinter(String s) { + if (s == null || s.length() == 0) { + return 0; + } + char[] str = s.toCharArray(); + int N = str.length; + int[][] dp = new int[N][N]; + dp[N - 1][N - 1] = 1; + for (int i = 0; i < N - 1; i++) { + dp[i][i] = 1; + dp[i][i + 1] = str[i] == str[i + 1] ? 1 : 2; + } + for (int L = N - 3; L >= 0; L--) { + for (int R = L + 2; R < N; R++) { + + // L....R + + dp[L][R] = R - L + 1; + + // L...k-1 k...R + for (int k = L + 1; k <= R; k++) { + dp[L][R] = Math.min(dp[L][R], dp[L][k - 1] + dp[k][R] - (str[L] == str[k] ? 1 : 0)); + } + } + } + return dp[0][N - 1]; + } + +} diff --git a/src/class46/Code01_RestoreWays.java b/src/class46/Code01_RestoreWays.java new file mode 100644 index 0000000..a4d913e --- /dev/null +++ b/src/class46/Code01_RestoreWays.java @@ -0,0 +1,237 @@ +package class46; + +public class Code01_RestoreWays { + + /* + * 整型数组arr长度为n(3 <= n <= 10^4),最初每个数字是<=200的正数且满足如下条件: 1. 0位置的要求:arr[0] <= + * arr[1] 2. n-1位置的要求:arr[n-1] <= arr[n-2] 3. 中间i位置的要求:arr[i] <= max(arr[i-1], + * arr[i+1]) 但是在arr有些数字丢失了,比如k位置的数字之前是正数,丢失之后k位置的数字为0。 请你根据上述条件, + * 计算可能有多少种不同的arr可以满足以上条件。 比如 [6,0,9] 只有还原成 [6,9,9]满足全部三个条件,所以返回1种。 [6,9,9] 达标 + * + * [ ...... 0 0] + */ + + public static int ways0(int[] arr) { + return process0(arr, 0); + } + + public static int process0(int[] arr, int index) { + if (index == arr.length) { + return isValid(arr) ? 1 : 0; + } else { + if (arr[index] != 0) { + return process0(arr, index + 1); + } else { + int ways = 0; + for (int v = 1; v < 201; v++) { + arr[index] = v; + ways += process0(arr, index + 1); + } + arr[index] = 0; + return ways; + } + } + } + + public static boolean isValid(int[] arr) { + if (arr[0] > arr[1]) { + return false; + } + if (arr[arr.length - 1] > arr[arr.length - 2]) { + return false; + } + for (int i = 1; i < arr.length - 1; i++) { + if (arr[i] > Math.max(arr[i - 1], arr[i + 1])) { + return false; + } + } + return true; + } + + public static int ways1(int[] arr) { + int N = arr.length; + if (arr[N - 1] != 0) { + return process1(arr, N - 1, arr[N - 1], 2); + } else { + int ways = 0; + for (int v = 1; v < 201; v++) { + ways += process1(arr, N - 1, v, 2); + } + return ways; + } + } + + // 如果i位置的数字变成了v, + // 并且arr[i]和arr[i+1]的关系为s, + // s==0,代表arr[i] < arr[i+1] 右大 + // s==1,代表arr[i] == arr[i+1] + // s==2,代表arr[i] > arr[i+1] 右小 + // 返回0...i范围上有多少种有效的转化方式? + public static int process1(int[] arr, int i, int v, int s) { + if (i == 0) { // 0...i 只剩一个数了,0...0 + return ((s == 0 || s == 1) && (arr[i] == 0 || v == arr[i])) ? 1 : 0; + } + // i > 0 + if (arr[i] != 0 && v != arr[i]) { + return 0; + } + // i>0 并且 i位置的数真的可以变成V, + int ways = 0; + if (s == 0 || s == 1) { // [i - 1] [i] <= 右 + for (int pre = 1; pre < 201; pre++) { + ways += process1(arr, i - 1, pre, pre < v ? 0 : (pre == v ? 1 : 2)); + } + } else { // s == 2 i > 右 i-1 >= i > 右 + for (int pre = v; pre < 201; pre++) { + ways += process1(arr, i - 1, pre, pre == v ? 1 : 2); + } + } + return ways; + } + + public static int ways2(int[] arr) { + int N = arr.length; + int[][][] dp = new int[N][201][3]; + // dp[0][...][...] + // dp[0][...][2] = 0 + // dp[0][...][0] = 1 + // dp[0][...][1] = 1 + if (arr[0] != 0) { + dp[0][arr[0]][0] = 1; + dp[0][arr[0]][1] = 1; + } else { + for (int v = 1; v < 201; v++) { + dp[0][v][0] = 1; + dp[0][v][1] = 1; + } + } + for (int i = 1; i < N; i++) { + for (int v = 1; v < 201; v++) { + for (int s = 0; s < 3; s++) { + if (arr[i] == 0 || v == arr[i]) { + if (s == 0 || s == 1) { + for (int pre = 1; pre < 201; pre++) { + dp[i][v][s] += dp[i - 1][pre][pre < v ? 0 : (pre == v ? 1 : 2)]; + } + } else { + for (int pre = v; pre < 201; pre++) { + dp[i][v][s] += dp[i - 1][pre][pre < v ? 0 : (pre == v ? 1 : 2)]; + } + } + } + } + } + } + if (arr[N - 1] != 0) { + return dp[N - 1][arr[N - 1]][2]; + } else { + int ways = 0; + for (int v = 1; v < 201; v++) { + ways += dp[N - 1][v][2]; + } + return ways; + } + } + + public static int ways3(int[] arr) { + int N = arr.length; + int[][][] dp = new int[N][201][3]; + if (arr[0] != 0) { + dp[0][arr[0]][0] = 1; + dp[0][arr[0]][1] = 1; + } else { + for (int v = 1; v < 201; v++) { + dp[0][v][0] = 1; + dp[0][v][1] = 1; + } + } + // presum[0~V][0] -> sum0[] + // presum[0~V][1] -> sum1[] + // presum[0~V][2] -> sum2[] + int[][] presum = new int[201][3]; + // presum -> dp[0][..][..] 三张表 + for (int v = 1; v < 201; v++) { + for (int s = 0; s < 3; s++) { + presum[v][s] = presum[v - 1][s] + dp[0][v][s]; + } + } + for (int i = 1; i < N; i++) { + for (int v = 1; v < 201; v++) { + for (int s = 0; s < 3; s++) { + if (arr[i] == 0 || v == arr[i]) { + if (s == 0 || s == 1) { + // dp[i][..][..] -> dp[i-1][..][..] + dp[i][v][s] += sum(1, v - 1, 0, presum); + dp[i][v][s] += dp[i - 1][v][1]; + dp[i][v][s] += sum(v + 1, 200, 2, presum); + } else { + dp[i][v][s] += dp[i - 1][v][1]; + dp[i][v][s] += sum(v + 1, 200, 2, presum); + } + } + } + } + for (int v = 1; v < 201; v++) { + for (int s = 0; s < 3; s++) { + presum[v][s] = presum[v - 1][s] + dp[i][v][s]; + } + } + } + if (arr[N - 1] != 0) { + return dp[N - 1][arr[N - 1]][2]; + } else { + return sum(1, 200, 2, presum); + } + } + + public static int sum(int begin, int end, int relation, int[][] presum) { + return presum[end][relation] - presum[begin - 1][relation]; + } + + // for test + public static int[] generateRandomArray(int len) { + int[] ans = new int[(int) (Math.random() * len) + 2]; + for (int i = 0; i < ans.length; i++) { + if (Math.random() < 0.5) { + ans[i] = 0; + } else { + ans[i] = (int) (Math.random() * 200) + 1; + } + } + return ans; + } + + // for test + public static void printArray(int[] arr) { + System.out.println("arr size : " + arr.length); + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + public static void main(String[] args) { + int len = 3; + int testTime = 10; + System.out.println("test begin"); + for (int i = 0; i < testTime; i++) { + int[] arr = generateRandomArray(len); + int ans0 = ways0(arr); + int ans1 = ways1(arr); + int ans2 = ways2(arr); + int ans3 = ways3(arr); + if (ans0 != ans1 || ans2 != ans3 || ans0 != ans2) { + System.out.println("Oops!"); + } + } + System.out.println("test finish"); + int[] arr = generateRandomArray(100000); + System.out.println(arr.length); + long begin = System.currentTimeMillis(); + ways3(arr); + long end = System.currentTimeMillis(); + System.out.println("run time : " + (end - begin) + " ms"); + + } + +} diff --git a/src/class46/Code02_DeleteAdjacentSameCharacter.java b/src/class46/Code02_DeleteAdjacentSameCharacter.java new file mode 100644 index 0000000..bc94ccb --- /dev/null +++ b/src/class46/Code02_DeleteAdjacentSameCharacter.java @@ -0,0 +1,172 @@ +package class46; + +// 如果一个字符相邻的位置没有相同字符,那么这个位置的字符出现不能被消掉 +// 比如:"ab",其中a和b都不能被消掉 +// 如果一个字符相邻的位置有相同字符,就可以一起消掉 +// 比如:"abbbc",中间一串的b是可以被消掉的,消除之后剩下"ac" +// 某些字符如果消掉了,剩下的字符认为重新靠在一起 +// 给定一个字符串,你可以决定每一步消除的顺序,目标是请尽可能多的消掉字符,返回最少的剩余字符数量 +// 比如:"aacca", 如果先消掉最左侧的"aa",那么将剩下"cca",然后把"cc"消掉,剩下的"a"将无法再消除,返回1 +// 但是如果先消掉中间的"cc",那么将剩下"aaa",最后都消掉就一个字符也不剩了,返回0,这才是最优解。 +// 再比如:"baaccabb", +// 如果先消除最左侧的两个a,剩下"bccabb", +// 如果再消除最左侧的两个c,剩下"babb", +// 最后消除最右侧的两个b,剩下"ba"无法再消除,返回2 +// 而最优策略是: +// 如果先消除中间的两个c,剩下"baaabb", +// 如果再消除中间的三个a,剩下"bbb", +// 最后消除三个b,不留下任何字符,返回0,这才是最优解 +public class Code02_DeleteAdjacentSameCharacter { + + // 暴力解 + public static int restMin1(String s) { + if (s == null) { + return 0; + } + if (s.length() < 2) { + return s.length(); + } + int minLen = s.length(); + for (int L = 0; L < s.length(); L++) { + for (int R = L + 1; R < s.length(); R++) { + if (canDelete(s.substring(L, R + 1))) { + minLen = Math.min(minLen, restMin1(s.substring(0, L) + s.substring(R + 1, s.length()))); + } + } + } + return minLen; + } + + public static boolean canDelete(String s) { + char[] str = s.toCharArray(); + for (int i = 1; i < str.length; i++) { + if (str[i - 1] != str[i]) { + return false; + } + } + return true; + } + + // 优良尝试的暴力递归版本 + public static int restMin2(String s) { + if (s == null) { + return 0; + } + if (s.length() < 2) { + return s.length(); + } + char[] str = s.toCharArray(); + return process(str, 0, str.length - 1, false); + } + + public static int process(char[] str, int L, int R, boolean has) { + if (L > R) { + return 0; + } + if (L == R) { + return has ? 0 : 1; + } + int index = L; + int K = has ? 1 : 0; + while (index <= R && str[index] == str[L]) { + K++; + index++; + } + int way1 = (K > 1 ? 0 : 1) + process(str, index, R, false); + int way2 = Integer.MAX_VALUE; + for (int split = index; split <= R; split++) { + if (str[split] == str[L] && str[split] != str[split - 1]) { + if (process(str, index, split - 1, false) == 0) { + way2 = Math.min(way2, process(str, split, R, K != 0)); + } + } + } + return Math.min(way1, way2); + } + + // 优良尝试的动态规划版本 + public static int restMin3(String s) { + if (s == null) { + return 0; + } + if (s.length() < 2) { + return s.length(); + } + char[] str = s.toCharArray(); + int N = str.length; + int[][][] dp = new int[N][N][2]; + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + for (int k = 0; k < 2; k++) { + dp[i][j][k] = -1; + } + } + } + return dpProcess(str, 0, N - 1, false, dp); + } + + public static int dpProcess(char[] str, int L, int R, boolean has, int[][][] dp) { + if (L > R) { + return 0; + } + int K = has ? 1 : 0; + if (dp[L][R][K] != -1) { + return dp[L][R][K]; + } + int ans = 0; + if (L == R) { + ans = (K == 0 ? 1 : 0); + } else { + int index = L; + int all = K; + while (index <= R && str[index] == str[L]) { + all++; + index++; + } + int way1 = (all > 1 ? 0 : 1) + dpProcess(str, index, R, false, dp); + int way2 = Integer.MAX_VALUE; + for (int split = index; split <= R; split++) { + if (str[split] == str[L] && str[split] != str[split - 1]) { + if (dpProcess(str, index, split - 1, false, dp) == 0) { + way2 = Math.min(way2, dpProcess(str, split, R, all > 0, dp)); + } + } + } + ans = Math.min(way1, way2); + } + dp[L][R][K] = ans; + return ans; + } + + public static String randomString(int len, int variety) { + char[] str = new char[len]; + for (int i = 0; i < len; i++) { + str[i] = (char) ((int) (Math.random() * variety) + 'a'); + } + return String.valueOf(str); + } + + public static void main(String[] args) { + int maxLen = 16; + int variety = 3; + int testTime = 100000; + System.out.println("测试开始"); + for (int i = 0; i < testTime; i++) { + int len = (int) (Math.random() * maxLen); + String str = randomString(len, variety); + int ans1 = restMin1(str); + int ans2 = restMin2(str); + int ans3 = restMin3(str); + if (ans1 != ans2 || ans1 != ans3) { + System.out.println(str); + System.out.println(ans1); + System.out.println(ans2); + System.out.println(ans3); + System.out.println("出错了!"); + break; + } + } + System.out.println("测试结束"); + } + +}