From 613c51bd45e836bcd40e0a1e2a6831321be38685 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sun, 1 Apr 2018 20:17:38 +0800 Subject: [PATCH] auto commit --- notes/Java 基础.md | 2 +- notes/剑指 offer 题解.md | 53 ++++++++++++------ pics/41392d76-dd1d-4712-85d9-e8bb46b04a2d.png | Bin 0 -> 4096 bytes 3 files changed, 36 insertions(+), 19 deletions(-) create mode 100644 pics/41392d76-dd1d-4712-85d9-e8bb46b04a2d.png diff --git a/notes/Java 基础.md b/notes/Java 基础.md index ba6cdd13..6cc8a936 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -535,7 +535,7 @@ Reflection is powerful, but should not be used indiscriminately. If it is possib # 八、异常 -Throwable 可以用来表示任何可以作为异常抛出的类,分为两种: **Error** 和 **Exception**,其中 Error 用来表示编译时系统错误。 +Throwable 可以用来表示任何可以作为异常抛出的类,分为两种: **Error** 和 **Exception**,其中 Error 用来表示 JVM 无法处理的错误(比如 java.lang.OutOfMemoryError)。 Exception 分为两种: diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index 7292b327..b4781e57 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -797,13 +797,13 @@ private void printNumber(char[] number) { ① 如果该节点不是尾节点,那么可以直接将下一个节点的值赋给该节点,令该节点指向下下个节点,然后删除下一个节点,时间复杂度为 O(1)。 -

+

② 否则,就需要先遍历链表,找到节点的前一个节点,然后让前一个节点指向 null,时间复杂度为 O(N)。

-综上,如果进行 N 次操作,那么大约需要操作节点的次数为 N-1+N=2N-1,其中 N-1 表示 N-1 个不是尾节点的每个节点以 O(1) 的时间复杂度操作节点的总次数,N 表示 1 个为节点以 O(n) 的时间复杂度操作节点的总次数。(2N-1)/N \~ 2,因此该算法的平均时间复杂度为 O(1)。 +综上,如果进行 N 次操作,那么大约需要操作节点的次数为 N-1+N=2N-1,其中 N-1 表示 N-1 个不是尾节点的每个节点以 O(1) 的时间复杂度操作节点的总次数,N 表示 1 个尾节点以 O(N) 的时间复杂度操作节点的总次数。(2N-1)/N \~ 2,因此该算法的平均时间复杂度为 O(1)。 ```java public ListNode deleteNode(ListNode head, ListNode tobeDelete) { @@ -852,17 +852,17 @@ public ListNode deleteDuplication(ListNode pHead) { ## 解题思路 -应该注意到,'.' 是用来代替一个任意字符,而 '\*' 是用来重复前面的字符。这两个的作用不同,不能把 '.' 的作用和 '\*' 进行类比,从而把它当成重复前面字符一次。 +应该注意到,'.' 是用来当做一个任意字符,而 '\*' 是用来重复前面的字符。这两个的作用不同,不能把 '.' 的作用和 '\*' 进行类比,从而把它当成重复前面字符一次。 ```html p.charAt(j) == s.charAt(i) : dp[i][j] = dp[i-1][j-1]; p.charAt(j) == '.' : dp[i][j] = dp[i-1][j-1]; p.charAt(j) == '*' : - p.charAt(j-1) != s.charAt(i) : dp[i][j] = dp[i][j-2] // in this case, a* only counts as empty + p.charAt(j-1) != s.charAt(i) : dp[i][j] = dp[i][j-2] //a* only counts as empty p.charAt(j-1) == s.charAt(i) or p.charAt(i-1) == '.': - dp[i][j] = dp[i-1][j] // in this case, a* counts as multiple a - or dp[i][j] = dp[i][j-1] // in this case, a* counts as single a - or dp[i][j] = dp[i][j-2] // in this case, a* counts as empty + dp[i][j] = dp[i-1][j] // a* counts as multiple a + or dp[i][j] = dp[i][j-1] // a* counts as single a + or dp[i][j] = dp[i][j-2] // a* counts as empty ``` ```java @@ -1217,6 +1217,8 @@ public int min() { ## 解题思路 +使用一个栈来模拟压入弹出操作。 + ```java public boolean IsPopOrder(int[] pushA, int[] popA) { int n = pushA.length; @@ -1494,7 +1496,7 @@ public class Solution { public String Serialize(TreeNode root) { if (root == null) return "#"; - return root.val + " " + Serialize(root.left) + " " + Serialize(root.right); + return root.val + " " + Serialize(root.left) + " " + Serialize(root.right); } public TreeNode Deserialize(String str) { @@ -1557,7 +1559,7 @@ private void backtracking(char[] chars, boolean[] hasUsed, StringBuffer s) { ## 解题思路 -多数投票问题,可以利用 Boyer-Moore Majority Vote Algorithm 来解决这个问题,使得时间复杂度为 O(n)。 +多数投票问题,可以利用 Boyer-Moore Majority Vote Algorithm 来解决这个问题,使得时间复杂度为 O(N)。 使用 cnt 来统计一个元素出现的次数,当遍历到的元素和统计元素不相等时,令 cnt--。如果前面查找了 i 个元素,且 cnt == 0 ,说明前 i 个元素没有 majority,或者有 majority,但是出现的次数少于 i / 2 ,因为如果多于 i / 2 的话 cnt 就一定不会为 0 。此时剩下的 n - i 个元素中,majority 的数目依然多于 (n - i) / 2,因此继续查找就能找出 majority。 @@ -1978,7 +1980,7 @@ public int FirstNotRepeatingChar(String str) { } ``` -以上的空间复杂度还不是最优的。考虑到只需要找到只出现一次的字符,那么我们只需要统计的次数信息只有 0,1,更大,那么使用两个比特位就能存储这些信息。 +以上实现的空间复杂度还不是最优的。考虑到只需要找到只出现一次的字符,那么我们只需要统计的次数信息只有 0,1,更大,那么使用两个比特位就能存储这些信息。 ```java public int FirstNotRepeatingChar(String str) { @@ -2077,7 +2079,10 @@ Output: ## 解题思路 -可以用二分查找找出数字在数组的最左端和最右端。 +可以用二分查找找出数字在数组的最左端和最右端,找最左端和最右端在方法实现上的区别主要在于对 nums[m] == K 的处理: + +- 找最左端令 h = m - 1 +- 找最右端令 l = m + 1 ```java public int GetNumberOfK(int[] nums, int K) { @@ -2313,7 +2318,7 @@ private void reverse(char[] c, int i, int j) { ## 解题思路 ```java -public String LeftRotateString(String str,int n) { +public String LeftRotateString(String str, int n) { if(str.length() == 0) return ""; char[] c = str.toCharArray(); reverse(c, 0, n - 1); @@ -2365,7 +2370,7 @@ public ArrayList maxInWindows(int[] num, int size) { ### 动态规划解法 -空间复杂度:O(n2) +空间复杂度:O(N2) ```java private static int face = 6; @@ -2393,7 +2398,7 @@ public double countProbability(int n, int s) { ### 动态规划解法 + 旋转数组 -空间复杂度:O(n) +空间复杂度:O(N) ```java private static int face = 6; @@ -2449,11 +2454,11 @@ public boolean isContinuous(int[] nums) { ## 题目描述 -让小朋友们围成一个大圈。然后 , 他随机指定一个数 m, 让编号为 0 的小朋友开始报数。每次喊到 m-1 的那个小朋友要出列唱首歌 , 然后可以在礼品箱中任意的挑选礼物 , 并且不再回到圈中 , 从他的下一个小朋友开始 , 继续 0...m-1 报数 .... 这样下去 .... 直到剩下最后一个小朋友 , 可以不用表演。 +让小朋友们围成一个大圈。然后,他随机指定一个数 m,让编号为 0 的小朋友开始报数。每次喊到 m-1 的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续 0...m-1 报数 .... 这样下去 .... 直到剩下最后一个小朋友,可以不用表演。 ## 解题思路 -约瑟夫环 +约瑟夫环,圆圈长度为 n 的解可以看成长度为 n-1 的解再加上报数的长度 m。因为是圆圈,所以最后需要对 n 取余。 ```java public int LastRemaining_Solution(int n, int m) { @@ -2471,6 +2476,8 @@ public int LastRemaining_Solution(int n, int m) { ## 解题思路 +使用贪心策略,假设第 i 轮进行卖出操作,买入操作价格应该是 i 之前并且价格最低。 + ```java public int maxProfit(int[] prices) { int n = prices.length; @@ -2503,7 +2510,11 @@ public int Sum_Solution(int n) { # 65. 不用加减乘除做加法 -a ^ b 表示没有考虑进位的情况下两数的和,(a & b) << 1 就是进位。递归会终止的原因是 (a & b) << 1 最右边会多一个 0,那么继续递归,进位最右边的 0 会慢慢增多,最后进位会变为 0,递归终止。 +## 解题思路 + +a ^ b 表示没有考虑进位的情况下两数的和,(a & b) << 1 就是进位。 + +递归会终止的原因是 (a & b) << 1 最右边会多一个 0,那么继续递归,进位最右边的 0 会慢慢增多,最后进位会变为 0,递归终止。 ```java public int Add(int num1, int num2) { @@ -2536,6 +2547,8 @@ public int[] multiply(int[] A) { # 67. 把字符串转换成整数 +## 解题思路 + ```java public int StrToInt(String str) { if (str.length() == 0) return 0; @@ -2544,7 +2557,7 @@ public int StrToInt(String str) { int ret = 0; for (int i = 0; i < chars.length; i++) { if (i == 0 && (chars[i] == '+' || chars[i] == '-')) continue; - if (chars[i] < '0' || chars[i] > '9') return 0; + if (chars[i] < '0' || chars[i] > '9') return 0; // 非法输入 ret = ret * 10 + (chars[i] - '0'); } return isNegative ? -ret : ret; @@ -2559,6 +2572,8 @@ public int StrToInt(String str) {

+二叉查找树中,两个节点 p, q 的公共祖先 root 满足 p.val <= root.val && root.val <= q.val,只要找到满足这个条件的最低层节点即可。换句话说,应该先考虑子树的解而不是根节点的解,二叉树的后序遍历操作满足这个特性。在本题中我们可以利用后序遍历的特性,先在左右子树中查找解,最后再考虑根节点的解。 + ```java public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if(root.val > p.val && root.val > q.val) return lowestCommonAncestor(root.left, p, q); @@ -2571,6 +2586,8 @@ public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {

+在左右子树中查找两个节点的最低公共祖先,如果在其中一颗子树中查找到,那么就返回这个解,否则可以认为根节点就是最低公共祖先。 + ```java public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if (root == null || root == p || root == q) return root; diff --git a/pics/41392d76-dd1d-4712-85d9-e8bb46b04a2d.png b/pics/41392d76-dd1d-4712-85d9-e8bb46b04a2d.png new file mode 100644 index 0000000000000000000000000000000000000000..d2fd2c630bbb7c7c1a464920250cadf625f57e93 GIT binary patch literal 4096 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 literal 0 HcmV?d00001