diff --git a/notes/Java 虚拟机.md b/notes/Java 虚拟机.md index 6a90b26c..1d2b4f14 100644 --- a/notes/Java 虚拟机.md +++ b/notes/Java 虚拟机.md @@ -261,7 +261,7 @@ obj = null; finalize() 类似 C++ 的析构函数,用来做关闭外部资源等工作。但是 try-finally 等方式可以做的更好,并且该方法运行代价高昂,不确定性大,无法保证各个对象的调用顺序,因此最好不要使用。 -当一个对象可被回收时,如果需要执行该对象的 finalize() 方法,那么就有可能通过在该方法中让对象重新被引用,从而实现自救。 +当一个对象可被回收时,如果需要执行该对象的 finalize() 方法,那么就有可能通过在该方法中让对象重新被引用,从而实现自救。自救只能进行一次,如果回收的对象之前调用了 finalize() 方法自救,后面回收时不会调用 finalize() 方法。 ## 垃圾收集算法 diff --git a/notes/Linux.md b/notes/Linux.md index 3aefdb35..1e5ebc84 100644 --- a/notes/Linux.md +++ b/notes/Linux.md @@ -130,6 +130,8 @@ info 与 man 类似,但是 info 将文档分成一个个页面,每个页面 /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin ``` +env 命令可以获取当前终端的环境变量。 + ## sudo sudo 允许一般用户使用 root 可执行的命令,不过只有在 /etc/sudoers 配置文件中添加的用户才能使用该指令。 diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index 5afd9aa2..c0c5412f 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -1062,20 +1062,21 @@ public void reOrderArray(int[] nums) {

```java -public ListNode FindKthToTail(ListNode head, int k) { +public ListNode FindKthToTail(ListNode head, int k) +{ if (head == null) return null; - ListNode fast, slow; - fast = slow = head; - while (fast != null && k-- > 0) - fast = fast.next; + ListNode P1 = head; + while (P1 != null && k-- > 0) + P1 = P1.next; if (k > 0) return null; - while (fast != null) { - fast = fast.next; - slow = slow.next; + ListNode P2 = head; + while (P1 != null) { + P1 = P1.next; + P2 = P2.next; } - return slow; + return P2; } ``` @@ -1083,6 +1084,12 @@ public ListNode FindKthToTail(ListNode head, int k) { [NowCoder](https://www.nowcoder.com/practice/253d2c59ec3e4bc68da16833f79a38e4?tpId=13&tqId=11208&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking) +## 题目描述 + +一个链表中包含环,请找出该链表的环的入口结点。 + +要求不能使用额外的空间。 + ## 解题思路 使用双指针,一个指针 fast 每次移动两个节点,一个指针 slow 每次移动一个节点。因为存在环,所以两个指针必定相遇在环中的某个节点上。假设相遇点在下图的 z1 位置,此时 fast 移动的节点数为 x+2y+z,slow 为 x+y,由于 fast 速度比 slow 快一倍,因此 x+2y+z=2(x+y),得到 x=z。 @@ -1092,16 +1099,15 @@ public ListNode FindKthToTail(ListNode head, int k) {

```java -public ListNode EntryNodeOfLoop(ListNode pHead) { +public ListNode EntryNodeOfLoop(ListNode pHead) +{ if (pHead == null || pHead.next == null) return null; ListNode slow = pHead, fast = pHead; - while (fast != null && fast.next != null) { + do { fast = fast.next.next; slow = slow.next; - if (slow == fast) - break; - } + } while (slow != fast); fast = pHead; while (slow != fast) { slow = slow.next; @@ -1159,7 +1165,8 @@ public ListNode ReverseList(ListNode head) { ### 递归 ```java -public ListNode Merge(ListNode list1, ListNode list2) { +public ListNode Merge(ListNode list1, ListNode list2) +{ if (list1 == null) return list2; if (list2 == null) @@ -1177,7 +1184,8 @@ public ListNode Merge(ListNode list1, ListNode list2) { ### 迭代 ```java -public ListNode Merge(ListNode list1, ListNode list2) { +public ListNode Merge(ListNode list1, ListNode list2) +{ ListNode head = new ListNode(-1); ListNode cur = head; while (list1 != null && list2 != null) { @@ -1209,20 +1217,22 @@ public ListNode Merge(ListNode list1, ListNode list2) { ## 解题思路 ```java -public boolean HasSubtree(TreeNode root1, TreeNode root2) { +public boolean HasSubtree(TreeNode root1, TreeNode root2) +{ if (root1 == null || root2 == null) return false; - return isSubtree(root1, root2) || HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2); + return isSubtreeWithRoot(root1, root2) || HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2); } -private boolean isSubtree(TreeNode root1, TreeNode root2) { +private boolean isSubtreeWithRoot(TreeNode root1, TreeNode root2) +{ if (root2 == null) return true; if (root1 == null) return false; if (root1.val != root2.val) return false; - return isSubtree(root1.left, root2.left) && isSubtree(root1.right, root2.right); + return isSubtreeWithRoot(root1.left, root2.left) && isSubtreeWithRoot(root1.right, root2.right); } ``` @@ -1237,7 +1247,8 @@ private boolean isSubtree(TreeNode root1, TreeNode root2) { ## 解题思路 ```java -public void Mirror(TreeNode root) { +public void Mirror(TreeNode root) +{ if (root == null) return; swap(root); @@ -1245,7 +1256,8 @@ public void Mirror(TreeNode root) { Mirror(root.right); } -private void swap(TreeNode root) { +private void swap(TreeNode root) +{ TreeNode t = root.left; root.left = root.right; root.right = t; @@ -1263,13 +1275,15 @@ private void swap(TreeNode root) { ## 解题思路 ```java -boolean isSymmetrical(TreeNode pRoot) { +boolean isSymmetrical(TreeNode pRoot) +{ if (pRoot == null) return true; return isSymmetrical(pRoot.left, pRoot.right); } -boolean isSymmetrical(TreeNode t1, TreeNode t2) { +boolean isSymmetrical(TreeNode t1, TreeNode t2) +{ if (t1 == null && t2 == null) return true; if (t1 == null || t2 == null) @@ -1293,7 +1307,8 @@ boolean isSymmetrical(TreeNode t1, TreeNode t2) { ## 解题思路 ```java -public ArrayList printMatrix(int[][] matrix) { +public ArrayList printMatrix(int[][] matrix) +{ ArrayList ret = new ArrayList<>(); int r1 = 0, r2 = matrix.length - 1, c1 = 0, c2 = matrix[0].length - 1; while (r1 <= r2 && c1 <= c2) { @@ -1324,24 +1339,28 @@ public ArrayList printMatrix(int[][] matrix) { ## 解题思路 ```java -private Stack stack = new Stack<>(); +private Stack dataStack = new Stack<>(); private Stack minStack = new Stack<>(); -public void push(int node) { - stack.push(node); +public void push(int node) +{ + dataStack.push(node); minStack.push(minStack.isEmpty() ? node : Math.min(minStack.peek(), node)); } -public void pop() { - stack.pop(); +public void pop() +{ + dataStack.pop(); minStack.pop(); } -public int top() { - return stack.peek(); +public int top() +{ + return dataStack.peek(); } -public int min() { +public int min() +{ return minStack.peek(); } ``` @@ -1359,12 +1378,13 @@ public int min() { 使用一个栈来模拟压入弹出操作。 ```java -public boolean IsPopOrder(int[] pushA, int[] popA) { - int n = pushA.length; +public boolean IsPopOrder(int[] pushSequence, int[] popSequence) +{ + int n = pushSequence.length; Stack stack = new Stack<>(); for (int pushIndex = 0, popIndex = 0; pushIndex < n; pushIndex++) { - stack.push(pushA[pushIndex]); - while (popIndex < n && stack.peek() == popA[popIndex]) { + stack.push(pushSequence[pushIndex]); + while (popIndex < n && stack.peek() == popSequence[popIndex]) { stack.pop(); popIndex++; } @@ -1392,21 +1412,20 @@ public boolean IsPopOrder(int[] pushA, int[] popA) { 不需要使用两个队列分别存储当前层的节点和下一层的节点,因为在开始遍历一层的节点时,当前队列中的节点数就是当前层的节点数,只要控制遍历这么多节点数,就能保证这次遍历的都是当前层的节点。 ```java -public ArrayList PrintFromTopToBottom(TreeNode root) { +public ArrayList PrintFromTopToBottom(TreeNode root) +{ Queue queue = new LinkedList<>(); ArrayList ret = new ArrayList<>(); - if (root == null) - return ret; queue.add(root); while (!queue.isEmpty()) { int cnt = queue.size(); while (cnt-- > 0) { TreeNode t = queue.poll(); - if (t.left != null) - queue.add(t.left); - if (t.right != null) - queue.add(t.right); + if (t == null) + continue; ret.add(t.val); + queue.add(t.left); + queue.add(t.right); } } return ret; @@ -1424,10 +1443,9 @@ public ArrayList PrintFromTopToBottom(TreeNode root) { ## 解题思路 ```java -ArrayList> Print(TreeNode pRoot) { +ArrayList> Print(TreeNode pRoot) +{ ArrayList> ret = new ArrayList<>(); - if (pRoot == null) - return ret; Queue queue = new LinkedList<>(); queue.add(pRoot); while (!queue.isEmpty()) { @@ -1435,13 +1453,14 @@ ArrayList> Print(TreeNode pRoot) { int cnt = queue.size(); while (cnt-- > 0) { TreeNode node = queue.poll(); + if (node == null) + continue; list.add(node.val); - if (node.left != null) - queue.add(node.left); - if (node.right != null) - queue.add(node.right); + queue.add(node.left); + queue.add(node.right); } - ret.add(list); + if (list.size() != 0) + ret.add(list); } return ret; } @@ -1458,10 +1477,9 @@ ArrayList> Print(TreeNode pRoot) { ## 解题思路 ```java -public ArrayList> Print(TreeNode pRoot) { +public ArrayList> Print(TreeNode pRoot) +{ ArrayList> ret = new ArrayList<>(); - if (pRoot == null) - return ret; Queue queue = new LinkedList<>(); queue.add(pRoot); boolean reverse = false; @@ -1470,16 +1488,17 @@ public ArrayList> Print(TreeNode pRoot) { int cnt = queue.size(); while (cnt-- > 0) { TreeNode node = queue.poll(); + if (node == null) + continue; list.add(node.val); - if (node.left != null) - queue.add(node.left); - if (node.right != null) - queue.add(node.right); + queue.add(node.left); + queue.add(node.right); } if (reverse) Collections.reverse(list); reverse = !reverse; - ret.add(list); + if (list.size() != 0) + ret.add(list); } return ret; } @@ -1500,13 +1519,15 @@ public ArrayList> Print(TreeNode pRoot) { ## 解题思路 ```java -public boolean VerifySquenceOfBST(int[] sequence) { +public boolean VerifySquenceOfBST(int[] sequence) +{ if (sequence == null || sequence.length == 0) return false; return verify(sequence, 0, sequence.length - 1); } -private boolean verify(int[] sequence, int first, int last) { +private boolean verify(int[] sequence, int first, int last) +{ if (last - first <= 1) return true; int rootVal = sequence[last]; @@ -1537,18 +1558,20 @@ private boolean verify(int[] sequence, int first, int last) { ```java private ArrayList> ret = new ArrayList<>(); -public ArrayList> FindPath(TreeNode root, int target) { +public ArrayList> FindPath(TreeNode root, int target) +{ backtracking(root, target, new ArrayList<>()); return ret; } -private void backtracking(TreeNode node, int target, ArrayList path) { +private void backtracking(TreeNode node, int target, ArrayList path) +{ if (node == null) return; path.add(node.val); target -= node.val; if (target == 0 && node.left == null && node.right == null) { - ret.add(new ArrayList(path)); + ret.add(new ArrayList<>(path)); } else { backtracking(node.left, target, path); backtracking(node.right, target, path); @@ -1582,7 +1605,8 @@ private void backtracking(TreeNode node, int target, ArrayList path) {

```java -public RandomListNode Clone(RandomListNode pHead) { +public RandomListNode Clone(RandomListNode pHead) +{ if (pHead == null) return null; // 插入新节点 @@ -1629,14 +1653,14 @@ public RandomListNode Clone(RandomListNode pHead) { private TreeNode pre = null; private TreeNode head = null; -public TreeNode Convert(TreeNode root) { - if (root == null) - return null; +public TreeNode Convert(TreeNode root) +{ inOrder(root); return head; } -private void inOrder(TreeNode node) { +private void inOrder(TreeNode node) +{ if (node == null) return; inOrder(node.left); @@ -1661,35 +1685,35 @@ private void inOrder(TreeNode node) { ## 解题思路 ```java -public class Solution { +private String deserializeStr; - private String deserializeStr; +public String Serialize(TreeNode root) +{ + if (root == null) + return "#"; + return root.val + " " + Serialize(root.left) + " " + Serialize(root.right); +} - public String Serialize(TreeNode root) { - if (root == null) - return "#"; - return root.val + " " + Serialize(root.left) + " " + Serialize(root.right); - } +public TreeNode Deserialize(String str) +{ + deserializeStr = str; + return Deserialize(); +} - public TreeNode Deserialize(String str) { - deserializeStr = str; - return Deserialize(); - } - - private TreeNode Deserialize() { - if (deserializeStr.length() == 0) - return null; - int index = deserializeStr.indexOf(" "); - String node = index == -1 ? deserializeStr : deserializeStr.substring(0, index); - deserializeStr = index == -1 ? "" : deserializeStr.substring(index + 1); - if (node.equals("#")) - return null; - int val = Integer.valueOf(node); - TreeNode t = new TreeNode(val); - t.left = Deserialize(); - t.right = Deserialize(); - return t; - } +private TreeNode Deserialize() +{ + if (deserializeStr.length() == 0) + return null; + int index = deserializeStr.indexOf(" "); + String node = index == -1 ? deserializeStr : deserializeStr.substring(0, index); + deserializeStr = index == -1 ? "" : deserializeStr.substring(index + 1); + if (node.equals("#")) + return null; + int val = Integer.valueOf(node); + TreeNode t = new TreeNode(val); + t.left = Deserialize(); + t.right = Deserialize(); + return t; } ```