auto commit

This commit is contained in:
CyC2018 2018-03-03 22:29:45 +08:00
parent aeaa7740c0
commit 01ad228af2
7 changed files with 172 additions and 172 deletions

View File

@ -80,7 +80,7 @@
该区域可能抛出以下异常:
1. 当线程请求的栈深度超过最大值,会抛出 StackOverflowError 异常;
2. 栈进行动态扩展时如果无法申请足够内存,会抛出 OutOfMemoryError 异常。
2. 栈进行动态扩展时如果无法申请足够内存,会抛出 OutOfMemoryError 异常。
## 3. 本地方法栈
@ -172,7 +172,7 @@ sf.get();
sf 是对 obj 的一个软引用,通过 sf.get() 方法可以取到这个对象,当然,当这个对象被标记为需要回收的对象时,则返回 null
软引用主要用实现类似缓存的功能,在内存足够的情况下直接通过软引用取值,无需从繁忙的真实来源查询数据,提升速度;当内存不足时,自动删除这部分缓存数据,从真正的来源查询这些数据。
软引用主要用实现类似缓存的功能,在内存足够的情况下直接通过软引用取值,无需从繁忙的真实来源查询数据,提升速度;当内存不足时,自动删除这部分缓存数据,从真正的来源查询这些数据。
#### 1.3.3 弱引用
@ -219,7 +219,7 @@ pf.isEnQueued();
当一个对象可被回收时,如果该对象有必要执行 finalize() 方法,那么就有可能可能通过在该方法中让对象重新被引用,从而实现自救。
finalize() 类似 C++ 的构函数,用来做关闭外部资源等工作。但是 try-finally 等方式可以做的更好,并且该方法运行代价高昂,不确定性大,无法保证各个对象的调用顺序,因此最好不要使用。
finalize() 类似 C++ 的构函数,用来做关闭外部资源等工作。但是 try-finally 等方式可以做的更好,并且该方法运行代价高昂,不确定性大,无法保证各个对象的调用顺序,因此最好不要使用。
## 2. 垃圾收集算法

View File

@ -59,7 +59,7 @@
1. 在计算 mid 时不能使用 mid = (l + h) / 2 这种方式,因为 l + h 可能会导致加法溢出,应该使用 mid = l + (h - l) / 2。
2. 对 h 的赋值和循环条件有关,当循环条件为 l <= h 时h = mid - 1当循环条件为 l < h h = mid。
解释如下:在循环条件为 l <= h 时,如果 h = mid会出现循环无法退出的情况例如 l = 1h = 1此时 mid 也等于 1如果此时继续执行 h = mid那么就会无限循环在循环条件为 l < h如果 h = mid - 1会错误跳过查找的数例如对于数组 [1,2,3]要查找 1最开始 l = 0h = 2mid = 1判断 key < arr[mid] 执行 h = mid - 1 = 0此时循环退出直接把查找的数跳过了。
解释如下:在循环条件为 l <= h 时,如果 h = mid会出现循环无法退出的情况例如 l = 1h = 1此时 mid 也等于 1如果此时继续执行 h = mid那么就会无限循环在循环条件为 l < h如果 h = mid - 1会错误跳过查找的数例如对于数组 [1, 2, 3]要查找 1最开始 l = 0h = 2mid = 1判断 key < arr[mid] 执行 h = mid - 1 = 0此时循环退出直接把查找的数跳过了。
3. l 的赋值一般都为 l = mid + 1。
@ -196,7 +196,7 @@ public int findContentChildren(int[] g, int[] s) {
```
Input:
[[10,16], [2,8], [1,6], [7,12]]
[[10, 16], [2, 8], [1, 6], [7, 12]]
Output:
2
@ -212,7 +212,7 @@ Output:
```java
public int findMinArrowShots(int[][] points) {
if(points.length == 0) return 0;
Arrays.sort(points,(a,b) -> (a[1] - b[1]));
Arrays.sort(points,(a, b) -> (a[1] - b[1]));
int curPos = points[0][1];
int ret = 1;
for (int i = 1; i < points.length; i++) {
@ -249,7 +249,7 @@ public int maxProfit(int[] prices) {
[Leetcode : 605. Can Place Flowers (Easy)](https://leetcode.com/problems/can-place-flowers/description/)
```html
Input: flowerbed = [1,0,0,0,1], n = 1
Input: flowerbed = [1, 0, 0, 0, 1], n = 1
Output: True
```
@ -318,7 +318,7 @@ public boolean isSubsequence(String s, String t) {
```java
Input: S = "ababcbacadefegdehijhklij"
Output: [9,7,8]
Output: [9, 7, 8]
Explanation:
The partition is "ababcbaca", "defegde", "hijhklij".
This is a partition so that each letter appears in at most one part.
@ -351,10 +351,10 @@ public List<Integer> partitionLabels(String S) {
```html
Input:
[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]
[[7, 0], [4, 4], [7, 1], [5, 0], [6, 1], [5, 2]]
Output:
[[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]
[[5, 0], [7, 0], [5, 2], [6, 1], [4, 4], [7, 1]]
```
题目描述:一个学生用两个分量 (h, k) 描述h 表示身高k 表示排在前面的有 k 个学生的身高比他高或者和他一样高。
@ -373,13 +373,13 @@ public int[][] reconstructQueue(int[][] people) {
return b[0] - a[0];
}
});
int n = people.length;
List<int[]> tmp = new ArrayList<>();
for(int i = 0; i < n; i++) {
tmp.add(people[i][1], new int[]{people[i][0], people[i][1]});
}
int[][] ret = new int[n][2];
for(int i = 0; i < n; i++) {
ret[i][0] = tmp.get(i)[0];
@ -677,7 +677,7 @@ public List<Integer> topKFrequent(int[] nums, int k) {
}
bucket[frequency].add(key);
}
for(int i = bucket.length - 1; i >= 0 && ret.size() < k; i--) {
if(bucket[i] != null) {
ret.addAll(bucket[i]);
@ -711,10 +711,10 @@ public List<Integer> topKFrequent(int[] nums, int k) {
**计算在网格中从原点到特定点的最短路径长度**
```html
[[1,1,0,1],
[1,0,1,0],
[1,1,1,1],
[1,0,1,1]]
[[1, 1, 0, 1],
[1, 0, 1, 0],
[1, 1, 1, 1],
[1, 0, 1, 1]]
```
```java
@ -766,14 +766,14 @@ private class Position {
[Leetcode : 695. Max Area of Island (Easy)](https://leetcode.com/problems/max-area-of-island/description/)
```html
[[0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,1,1,0,1,0,0,0,0,0,0,0,0],
[0,1,0,0,1,1,0,0,1,0,1,0,0],
[0,1,0,0,1,1,0,0,1,1,1,0,0],
[0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,0,1,1,0,0,0,0]]
[[0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
[0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0],
[0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0]]
```
```java
@ -803,9 +803,9 @@ private int dfs(int[][] grid, int i, int j){
```html
Input:
[[1,1,0],
[1,1,0],
[0,0,1]]
[[1, 1, 0],
[1, 1, 0],
[0, 0, 1]]
Output: 2
Explanation:The 0th and 1st students are direct friends, so they are in a friend circle.
The 2nd student himself is in a friend circle. So return 2.
@ -974,7 +974,7 @@ private void dfs(char[][] board, int r, int c) {
```html
Given the following 5x5 matrix:
Pacific ~ ~ ~ ~ ~
Pacific ~ ~ ~ ~ ~
~ 1 2 2 3 (5) *
~ 3 2 3 (4) (4) *
~ 2 4 (5) 3 1 *
@ -1042,11 +1042,11 @@ private void dfs(int r, int c, boolean[][] canReach) {
一行一行地摆放在确定一行中的那个皇后应该摆在哪一列时需要用三个标记数组来确定某一列是否合法这三个标记数组分别为列标记数组、45 度对角线标记数组和 135 度对角线标记数组。
45 度对角线标记数组的维度为 2\*n - 1通过下图可以明确 (r,c) 的位置所在的数组下标为 r + c。
45 度对角线标记数组的维度为 2\*n - 1通过下图可以明确 (r, c) 的位置所在的数组下标为 r + c。
![](https://github.com/CyC2018/InterviewNotes/blob/master/pics//85583359-1b45-45f2-9811-4f7bb9a64db7.jpg)
135 度对角线标记数组的维度也是 2\*n - 1(r,c) 的位置所在的数组下标为 n - 1 - (r - c)。
135 度对角线标记数组的维度也是 2\*n - 1(r, c) 的位置所在的数组下标为 n - 1 - (r - c)。
![](https://github.com/CyC2018/InterviewNotes/blob/master/pics//9e80f75a-b12b-4344-80c8-1f9ccc2d5246.jpg)
@ -1230,14 +1230,14 @@ private void doRestore(int k, String path, String s) {
[Leetcode : 46. Permutations (Medium)](https://leetcode.com/problems/permutations/description/)
```html
[1,2,3] have the following permutations:
[1, 2, 3] have the following permutations:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
[1, 2, 3],
[1, 3, 2],
[2, 1, 3],
[2, 3, 1],
[3, 1, 2],
[3, 2, 1]
]
```
@ -1272,8 +1272,8 @@ private void backtracking(List<Integer> permuteList, boolean[] visited, int[] nu
[Leetcode : 47. Permutations II (Medium)](https://leetcode.com/problems/permutations-ii/description/)
```html
[1,1,2] have the following unique permutations:
[[1,1,2], [1,2,1], [2,1,1]]
[1, 1, 2] have the following unique permutations:
[[1, 1, 2], [1, 2, 1], [2, 1, 1]]
```
题目描述:数组元素可能含有相同的元素,进行排列时就有可能出先重复的排列,要求重复的排列只返回一个。
@ -1315,12 +1315,12 @@ private void backtracking(List<Integer> permuteList, boolean[] visited, int[] nu
```html
If n = 4 and k = 2, a solution is:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
[2, 4],
[3, 4],
[2, 3],
[1, 2],
[1, 3],
[1, 4],
]
```
@ -1337,7 +1337,7 @@ private void backtracking(int start, int n, int k, List<Integer> combineList, Li
ret.add(new ArrayList(combineList)); // 这里要重新构造一个 List
return;
}
for(int i = start; i <= n - k + 1; i++){ // 剪枝
combineList.add(i); // 把 i 标记为已访问
@ -1386,8 +1386,8 @@ A solution set is:
[Leetcode : 40. Combination Sum II (Medium)](https://leetcode.com/problems/combination-sum-ii/description/)
```html
For example, given candidate set [10, 1, 2, 7, 6, 1, 5] and target 8,
A solution set is:
For example, given candidate set [10, 1, 2, 7, 6, 1, 5] and target 8,
A solution set is:
[
[1, 7],
[1, 2, 5],
@ -1463,14 +1463,14 @@ private void backtracking(int startIdx, int size, int[] nums) {
```html
For example,
If nums = [1,2,2], a solution is:
If nums = [1, 2, 2], a solution is:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[1, 2, 2],
[2, 2],
[1, 2],
[]
]
```
@ -1792,7 +1792,7 @@ public int climbStairs(int n) {
**母牛生产**
[程序员代码面试指南-P181](#)
[ 程序员代码面试指南 -P181](#)
题目描述:假设农场中成熟的母牛每年都会生 1 头小母牛,并且永远不会死。第一年有 1 只小母牛,从第二年开始,母牛开始生小母牛。每只小母牛 3 年之后成熟又可以生小母牛。给定整数 N求 N 年后牛的数量。
@ -1896,11 +1896,11 @@ dp[N] 即为所求。
### 最长递增子序列
已知一个序列 {S<sub>1</sub>, S<sub>2</sub>,...,S<sub>n</sub>} ,取出若干数组成新的序列 {S<sub>i1</sub>, S<sub>i2</sub>,..., S<sub>im</sub>},其中 i1、i2 ... im 保持递增,即新序列中各个数仍然保持原数列中的先后顺序,称新序列为原序列的一个**子序列**。
已知一个序列 {S<sub>1</sub>, S<sub>2</sub>,..., S<sub>n</sub>} ,取出若干数组成新的序列 {S<sub>i1</sub>, S<sub>i2</sub>,..., S<sub>im</sub>},其中 i1、i2 ... im 保持递增,即新序列中各个数仍然保持原数列中的先后顺序,称新序列为原序列的一个**子序列**。
如果在子序列中,当下标 ix > iy 时S<sub>ix</sub> > S<sub>iy</sub>,称子序列为原序列的一个**递增子序列**。
定义一个数组 dp 存储最长递增子序列的长度dp[n] 表示以 S<sub>n</sub> 结尾的序列的最长递增子序列长度。对于一个递增子序列 {S<sub>i1</sub>, S<sub>i2</sub>,...,S<sub>im</sub>},如果 im < n 并且 S<sub>im</sub> < S<sub>n</sub> ,此时 {S<sub>i1</sub>, S<sub>i2</sub>,..., S<sub>im</sub>, S<sub>n</sub>} 为一个递增子序列,递增子序列的长度增加 1。满足上述条件的递增子序列中长度最长的那个递增子序列就是要找的在长度最长的递增子序列上加上 S<sub>n</sub> 就构成了以 S<sub>n</sub> 为结尾的最长递增子序列。因此 dp[n] = max{ dp[i]+1 | S<sub>i</sub> < S<sub>n</sub> && i < n}
定义一个数组 dp 存储最长递增子序列的长度dp[n] 表示以 S<sub>n</sub> 结尾的序列的最长递增子序列长度。对于一个递增子序列 {S<sub>i1</sub>, S<sub>i2</sub>,..., S<sub>im</sub>},如果 im < n 并且 S<sub>im</sub> < S<sub>n</sub> ,此时 {S<sub>i1</sub>, S<sub>i2</sub>,..., S<sub>im</sub>, S<sub>n</sub>} 为一个递增子序列,递增子序列的长度增加 1。满足上述条件的递增子序列中长度最长的那个递增子序列就是要找的在长度最长的递增子序列上加上 S<sub>n</sub> 就构成了以 S<sub>n</sub> 为结尾的最长递增子序列。因此 dp[n] = max{ dp[i]+1 | S<sub>i</sub> < S<sub>n</sub> && i < n}
因为在求 dp[n] 时可能无法找到一个满足条件的递增子序列,此时 {S<sub>n</sub>} 就构成了递增子序列,因此需要对前面的求解方程做修改,令 dp[n] 最小为 1
@ -1931,7 +1931,7 @@ public int lengthOfLIS(int[] nums) {
}
```
以上解法的时间复杂度为 O(n<sup>2</sup>) ,可以使用二分查找使得时间复杂度降低为 O(nlog<sub>n</sub>)。定义一个 tails 数组,其中 tails[i] 存储长度为 i + 1 的最长递增子序列的最后一个元素,例如对于数组 [4,5,6,3],有
以上解法的时间复杂度为 O(n<sup>2</sup>) ,可以使用二分查找使得时间复杂度降低为 O(nlog<sub>n</sub>)。定义一个 tails 数组,其中 tails[i] 存储长度为 i + 1 的最长递增子序列的最后一个元素,例如对于数组 [4, 5, 6, 3],有
```html
len = 1 : [4], [5], [6], [3] => tails[0] = 3
@ -2150,9 +2150,9 @@ public boolean wordBreak(String s, List<String> wordDict) {
[Leetcode : 494. Target Sum (Medium)](https://leetcode.com/problems/target-sum/description/)
```html
Input: nums is [1, 1, 1, 1, 1], S is 3.
Input: nums is [1, 1, 1, 1, 1], S is 3.
Output: 5
Explanation:
Explanation:
-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
@ -2199,7 +2199,7 @@ private int subsetSum(int[] nums, int targetSum) {
}
```
**01字符构成最多的字符串**
**01 字符构成最多的字符串**
[Leetcode : 474. Ones and Zeroes (Medium)](https://leetcode.com/problems/ones-and-zeroes/description/)
@ -2242,7 +2242,7 @@ public int findMaxForm(String[] strs, int m, int n) {
题目描述:给一些面额的硬币,要求用这些硬币来组成给定面额的钱数,并且使得硬币数量最少。硬币可以重复使用。
这是一个完全背包问题,完全背包问题和 0-1背包问题在实现上唯一的不同是第二层循环是从 0 开始的,而不是从尾部开始。
这是一个完全背包问题,完全背包问题和 0-1 背包问题在实现上唯一的不同是,第二层循环是从 0 开始的,而不是从尾部开始。
```java
public int coinChange(int[] coins, int amount) {
@ -2356,15 +2356,15 @@ public int maxProfit(int k, int[] prices) {
```java
class NumArray {
int[] nums;
public NumArray(int[] nums) {
for(int i = 1; i < nums.length; i++)
nums[i] += nums[i - 1];
this.nums = nums;
}
public int sumRange(int i, int j) {
return i == 0 ? nums[j] : nums[j] - nums[i - 1];
}
@ -2415,7 +2415,7 @@ A = [1, 2, 3, 4]
return: 3, for 3 arithmetic slices in A: [1, 2, 3], [2, 3, 4] and [1, 2, 3, 4] itself.
```
对于 (1,2,3,4),它有三种组成递增子区间的方式,而对于 (1,2,3,4,5),它组成递增子区间的方式除了 (1,2,3,4) 的三种外还多了一种,即 (1,2,3,4,5),因此 dp[i] = dp[i - 1] + 1。
对于 (1, 2, 3, 4),它有三种组成递增子区间的方式,而对于 (1, 2, 3, 4, 5),它组成递增子区间的方式除了 (1, 2, 3, 4) 的三种外还多了一种,即 (1, 2, 3, 4, 5),因此 dp[i] = dp[i - 1] + 1。
```java
public int numberOfArithmeticSlices(int[] A) {
@ -2538,7 +2538,7 @@ public int findLongestChain(int[][] pairs) {
}
}
}
int ret = 0;
for(int num : dp) {
ret = Math.max(ret, num);
@ -2614,9 +2614,9 @@ public int minSteps(int n) {
如果 x 整除 yy mod x == 0则对于所有 imi <= ni。
x 和 y 的 **最大公约数**gcd(x,y) = 2<sup>min(m0,n0)</sup> \* 3<sup>min(m1,n1)</sup> \* 5<sup>min(m2,n2)</sup> \* ...
x 和 y 的 **最大公约数**gcd(x, y) = 2<sup>min(m0, n0)</sup> \* 3<sup>min(m1, n1)</sup> \* 5<sup>min(m2, n2)</sup> \* ...
x 和 y 的 **最小公倍数**lcm(x,y) = 2<sup>max(m0,n0)</sup> \* 3<sup>max(m1,n1)</sup> \* 5<sup>max(m2,n2)</sup> \* ...
x 和 y 的 **最小公倍数**lcm(x, y) = 2<sup>max(m0, n0)</sup> \* 3<sup>max(m1, n1)</sup> \* 5<sup>max(m2, n2)</sup> \* ...
**生成素数序列**
@ -2868,8 +2868,8 @@ public int majorityElement(int[] nums) {
[Leetcode : 367. Valid Perfect Square (Easy)](https://leetcode.com/problems/valid-perfect-square/description/)
平方序列1,4,9,16,..
间隔3,5,7,...
平方序列1, 4, 9, 16,..
间隔3, 5, 7,...
间隔为等差数列,使用这个特性可以得到从 1 开始的平方序列。
@ -2992,7 +2992,7 @@ class MyQueue {
class MyQueue {
private Stack<Integer> in = new Stack();
private Stack<Integer> out = new Stack();
public void push(int x) {
in.push(x);
}
@ -3006,7 +3006,7 @@ class MyQueue {
in2out();
return out.peek();
}
private void in2out(){
if(out.isEmpty()){
while(!in.isEmpty()){
@ -3027,28 +3027,28 @@ class MyQueue {
```java
class MyStack {
private Queue<Integer> queue;
public MyStack() {
queue = new LinkedList<>();
}
public void push(int x) {
queue.add(x);
for(int i = 1; i < queue.size(); i++){ // 翻转
queue.add(queue.remove());
}
}
public int pop() {
return queue.remove();
}
public int top() {
return queue.peek();
}
public boolean empty() {
return queue.isEmpty();
}
@ -3063,7 +3063,7 @@ class MyStack {
```java
class MinStack {
private Stack<Integer> dataStack;
private Stack<Integer> minStack;
private int min;
@ -3073,7 +3073,7 @@ class MinStack {
minStack = new Stack<>();
min = Integer.MAX_VALUE;
}
public void push(int x) {
dataStack.add(x);
if(x < min) {
@ -3081,7 +3081,7 @@ class MinStack {
}
minStack.add(min);
}
public void pop() {
dataStack.pop();
minStack.pop();
@ -3091,11 +3091,11 @@ class MinStack {
min = Integer.MAX_VALUE;
}
}
public int top() {
return dataStack.peek();
}
public int getMin() {
return min;
}
@ -3166,8 +3166,8 @@ public int[] dailyTemperatures(int[] temperatures) {
[Leetcode : 496. Next Greater Element I (Easy)](https://leetcode.com/problems/next-greater-element-i/description/)
```html
Input: nums1 = [4,1,2], nums2 = [1,3,4,2].
Output: [-1,3,-1]
Input: nums1 = [4, 1, 2], nums2 = [1, 3, 4, 2].
Output: [-1, 3,-1]
```
在遍历数组时用 Stack 把数组中的数存起来,如果当前遍历的数比栈顶元素来的大,说明栈顶元素的下一个比它大的数就是当前元素。
@ -3421,11 +3421,11 @@ s1 进行循环移位的结果是 s1s1 的子字符串,因此只要判断 s2
例如 abcd123 向右移动 3 位 得到 123abcd
将 abcd123 中的 abcd 和 123 单独逆序,得到 dcba321然后对整个字符串进行逆序得到123abcd。
将 abcd123 中的 abcd 和 123 单独逆序,得到 dcba321然后对整个字符串进行逆序得到 123abcd。
**字符串中单词的翻转**
[程序员代码面试指南](#)
[ 程序员代码面试指南 ](#)
例如将 "I am a student" 翻转成 "student a am I"
@ -3470,11 +3470,11 @@ public int[] findErrorNums(int[] nums) {
for(int i = 0; i < nums.length; i++){
while(nums[i] != i + 1 && nums[i] != nums[nums[i] - 1]) swap(nums, i, nums[i] - 1);
}
for(int i = 0; i < nums.length; i++){
if(i + 1 != nums[i]) return new int[]{nums[i], i + 1};
}
return null;
}
@ -3766,7 +3766,7 @@ private boolean isEqual(ListNode l1, ListNode l2){
**从链表中删除节点**
[编程之美3.4]()
[ 编程之美3.4]()
![](https://github.com/CyC2018/InterviewNotes/blob/master/pics//2c968ec5-0967-49ce-ac06-f8f5c9ab33bc.jpg)
@ -4022,7 +4022,7 @@ private TreeNode toBST(int[] nums, int sIdx, int eIdx){
/ \
4 5
Return 3, which is the length of the path [4,2,1,3] or [5,2,1,3].
Return 3, which is the length of the path [4, 2, 1, 3] or [5, 2, 1, 3].
```
```java
@ -4494,24 +4494,24 @@ Trie又称前缀树或字典树用于判断字符串是否存在或者是
```java
class Trie {
private class Node{
Node[] childs = new Node[26];
boolean isLeaf;
}
private Node root = new Node();
/** Initialize your data structure here. */
public Trie() {
}
/** Inserts a word into the trie. */
public void insert(String word) {
int idx = word.charAt(0) - 'a';
insert(word, root);
}
private void insert(String word, Node node){
int idx = word.charAt(0) - 'a';
if(node.childs[idx] == null){
@ -4520,12 +4520,12 @@ class Trie {
if(word.length() == 1) node.childs[idx].isLeaf = true;
else insert(word.substring(1), node.childs[idx]);
}
/** Returns if the word is in the trie. */
public boolean search(String word) {
return search(word, root);
return search(word, root);
}
private boolean search(String word, Node node){
if(node == null) return false;
int idx = word.charAt(0) - 'a';
@ -4533,12 +4533,12 @@ class Trie {
if(word.length() == 1) return node.childs[idx].isLeaf;
return search(word.substring(1), node.childs[idx]);
}
/** Returns if there is any word in the trie that starts with the given prefix. */
public boolean startsWith(String prefix) {
return startWith(prefix, root);
}
private boolean startWith(String prefix, Node node){
if(node == null) return false;
if(prefix.length() == 0) return true;
@ -4558,18 +4558,18 @@ class MapSum {
int val;
Map<Character, Trie> childs;
boolean isWord;
Trie() {
childs = new HashMap<>();
}
}
private Trie root;
public MapSum() {
root = new Trie();
}
public void insert(String key, int val) {
Trie cur = root;
for(char c : key.toCharArray()) {
@ -4582,7 +4582,7 @@ class MapSum {
cur.val = val;
cur.isWord = true;
}
public int sum(String prefix) {
Trie cur = root;
for(char c : prefix.toCharArray()) {
@ -4591,7 +4591,7 @@ class MapSum {
}
return dfs(cur);
}
private int dfs(Trie cur) {
int sum = 0;
if(cur.isWord) {
@ -4745,7 +4745,7 @@ public int reverseBits(int n) {
**不用额外变量交换两个整数**
[程序员代码面试指南 P317](#)
[ 程序员代码面试指南 P317](#)
```java
a = a ^ b;
@ -4949,9 +4949,9 @@ public int maxProduct(String[] words) {
# 参考资料
- [Leetcode](https://leetcode.com/problemset/algorithms/?status=Todo)
- Weiss M A, 冯舜玺. 数据结构与算法分析——C 语言描述[J]. 2004.
- Weiss M A, 冯舜玺 . 数据结构与算法分析——C 语言描述 [J]. 2004.
- Sedgewick R. Algorithms[M]. Pearson Education India, 1988.
- 何海涛, 软件工程师. 剑指 Offer: 名企面试官精讲典型编程题[M]. 电子工业出版社, 2014.
- 《编程之美》小组. 编程之美[M]. 电子工业出版社, 2008.
- 左程云. 程序员代码面试指南[M]. 电子工业出版社, 2015.
- 何海涛 , 软件工程师 . 剑指 Offer: 名企面试官精讲典型编程题 [M]. 电子工业出版社 , 2014.
- 《编程之美》小组 . 编程之美 [M]. 电子工业出版社 , 2008.
- 左程云 . 程序员代码面试指南 [M]. 电子工业出版社 , 2015.

View File

@ -118,7 +118,7 @@ info 与 man 类似,但是 info 将文档分成一个个页面,每个页面
**2. shutdown**
```html
# /sbin/shutdown [-krhc] [时间] [警告讯息]
# /sbin/shutdown [-krhc] [ 时间 ] [ 警告讯息 ]
-k 不会关机,只是发送警告讯息,通知所有在线的用户
-r 将系统的服务停掉后就重新启动
-h 将系统的服务停掉后就立即关机
@ -153,7 +153,7 @@ netstat -anp | grep 80
## 运行等级
- 0关机模式
- 1单用户模式可用于破解root密码
- 1单用户模式可用于破解 root 密码)
- 2无网络支持的多用户模式
- 3有网络支持的多用户模式文本模式工作中最常用的模式
- 4保留未使用
@ -210,7 +210,7 @@ MBR 中第一个扇区最重要里面有主要开机记录Master boo
分区表只有 64 bytes最多只能存储 4 个分区,这 4 个分区为主分区Primary和扩展分区Extended。其中扩展分区只有一个它将其它空间用来记录分区表可以记录更多的分区因此通过扩展分区可以分出更多区分这些分区称为逻辑分区。
Linux 也把分区当成文件,分区文件的命名方式为:磁盘文件名+编号,例如 /dev/sda1。注意逻辑分区的编号从 5 开始。
Linux 也把分区当成文件,分区文件的命名方式为:磁盘文件名 + 编号,例如 /dev/sda1。注意逻辑分区的编号从 5 开始。
### 2. GPT
@ -282,7 +282,7 @@ UEFI 相比于 BIOS 来说功能更为全面,也更为安全。
不仅可以修改文件拥有者,也可以修改文件所属群组。
```html
# chown [-R] 用户名:群组名 dirname/filename
# chown [-R] 用户名 : 群组名 dirname/filename
```
### 3. 修改权限
@ -335,7 +335,7 @@ UEFI 相比于 BIOS 来说功能更为全面,也更为安全。
为了使不同 Linux 发行版本的目录结构保持一致性Filesystem Hierarchy Standard (FHS) 规定了 Linux 的目录结构。最基础的三个目录如下:
- / (root, 根目录)
- / (root, 根目录 )
- /usr (unix software resource):所有系统默认软件都会安装到这个目录;
- /var (variable):存放系统或程序运行过程中的数据文件。
@ -378,7 +378,7 @@ cp [-adfilprsu] source destination
-p :连同文件的属性一起复制过去
-r :递归持续复制
-u destination 比 source 旧才更新 destination或 destination 不存在的情况下才复制
--preserve=all :除了 -p 的权限相关参数外,还加入 SELinux 的属性, links, xattr 等也复制了
--preserve=all :除了 -p 的权限相关参数外,还加入 SELinux 的属性 , links, xattr 等也复制了
```
### 3. rm
@ -449,8 +449,8 @@ cp [-adfilprsu] source destination
-a 更新 atime
-c 更新 ctime若该文件不存在则不建立新文件
-m 更新 mtime
-d 后面可以接欲更新的日期而不用当前的日期,也可以使用 --date="日期或时间"
-t :后面可以接欲更新的时间而不用当前的时间,格式为[YYYYMMDDhhmm]
-d 后面可以接欲更新的日期而不用当前的日期,也可以使用 --date=" 日期或时间 "
-t :后面可以接欲更新的时间而不用当前的时间,格式为 [YYYYMMDDhhmm]
```
## 指令与文件搜索
@ -495,8 +495,8 @@ find 可以使用文件的属性和权限进行搜索。
```html
-mtime n :列出在 n 天前的那一天修改过内容的文件
-mtime +n :列出在 n 天之前(不含 n 天本身)修改过内容的文件
-mtime -n :列出在 n 天之内(含 n 天本身)修改过内容的文件
-mtime +n :列出在 n 天之前 ( 不含 n 天本身 ) 修改过内容的文件
-mtime -n :列出在 n 天之内 ( 含 n 天本身 ) 修改过内容的文件
-newer file 列出比 file 更新的文件
```
@ -519,7 +519,7 @@ find 可以使用文件的属性和权限进行搜索。
```html
-name filename
-size [+-]SIZE搜寻比 SIZE 还要大(+)或小(-)的文件。这个 SIZE 的规格有c: 代表 bytek: 代表 1024bytes。所以要找比 50KB 还要大的文件,就是 -size +50k
-size [+-] SIZE搜寻比 SIZE 还要大 (+) 或小 (-) 的文件。这个 SIZE 的规格有c: 代表 bytek: 代表 1024bytes。所以要找比 50KB 还要大的文件,就是 -size +50k
-type TYPE
-perm mode :搜索权限等于 mode 的文件
-perm -mode :搜索权限包含 mode 的文件
@ -556,13 +556,13 @@ inode 中记录了文件内容所在的 block但是每个 block 非常小,
inode 具体包含以下信息:
- 该文件的存取模式(read/write/excute)
- 该文件的拥有者与群组(owner/group)
- 该文件的存取模式 (read/write/excute)
- 该文件的拥有者与群组 (owner/group)
- 该文件的容量;
- 该文件建立或状态改变的时间(ctime)
- 最近一次的读取时间(atime)
- 最近修改的时间(mtime)
- 定义文件特性的旗标(flag),如 SetUID...
- 该文件建立或状态改变的时间 (ctime)
- 最近一次的读取时间 (atime)
- 最近修改的时间 (mtime)
- 定义文件特性的旗标 (flag),如 SetUID...
- 该文件真正内容的指向 (pointer)。
## 目录的 inode 与 block
@ -636,7 +636,7 @@ $ gzip [-cdtv#] filename
-d :解压缩
-t :检验压缩文件是否出错
-v :显示压缩比等信息
-# # 为数字的意思代表压缩等级数字越大压缩比越高默认为6
-# # 为数字的意思,代表压缩等级,数字越大压缩比越高,默认为 6
```
### 2. bzip2
@ -667,16 +667,16 @@ $ xz [-dtlkc#] filename
压缩指令只能对一个文件进行压缩而打包能够将多个文件打包成一个大文件。tar 不仅可以用于打包,也可以使用 gip、bzip2、xz 将打包文件进行压缩。
```html
$ tar [-z|-j|-J] [cv] [-f 新建的tar文件] filename... ==打包压缩
$ tar [-z|-j|-J] [tv] [-f 已有的tar文件] ==查看
$ tar [-z|-j|-J] [xv] [-f 已有的tar文件] [-C 目录] ==解压缩
-z 使用zip
-j 使用bzip2
-J 使用xz
$ tar [-z|-j|-J] [cv] [-f 新建的 tar 文件 ] filename... == 打包压缩
$ tar [-z|-j|-J] [tv] [-f 已有的 tar 文件 ] == 查看
$ tar [-z|-j|-J] [xv] [-f 已有的 tar 文件 ] [-C 目录 ] == 解压缩
-z :使用 zip
-j :使用 bzip2
-J :使用 xz
-c :新建打包文件;
-t :查看打包文件里面有哪些文件;
-x :解打包或解压缩的功能;
-v :在压缩/解压缩的过程中,显示正在处理的文件名;
-v :在压缩 / 解压缩的过程中,显示正在处理的文件名;
-f : filename要处理的文件
-C 目录 在特定目录解压缩。
```
@ -724,7 +724,7 @@ $ echo $var
$ echo ${var}
```
变量内容如果有空格需要使用双引号或者单引号。双引号内的特殊字符可以保留原本特性例如var="lang is \<img src="https://latex.codecogs.com/gif.latex?LANG"则var的值为langiszh_TW.UTF-8而单引号内的特殊字符就是特殊字符本身例如var='langis\"/>LANG',则 var 的值为 lang is \$LANG。
变量内容如果有空格,需要使用双引号或者单引号。双引号内的特殊字符可以保留原本特性,例如 var="lang is \<img src="https://latex.codecogs.com/gif.latex?LANG"则var的值为langiszh_TW.UTF-8而单引号内的特殊字符就是特殊字符本身例如var='langis\"/>LANG',则 var 的值为 lang is \$LANG。
可以使用 \`指令\` 或者 \<img src="https://latex.codecogs.com/gif.latex?(指令)的方式将指令的执行结果赋值给变量。例如version=\"/>(uname -r),则 version 的值为 3.10.0-229.el7.x86_64。
@ -738,7 +738,7 @@ $ declare [-aixr] variable
-a 定义为数组类型
-i 定义为整数类型
-x 定义为环境变量
-r 定义为readonly类型
-r 定义为 readonly 类型
```
使用 [ ] 来对数组进行操作:
@ -761,9 +761,9 @@ $ echo ${array[1]}
重定向就是使用文件代替标准输入、标准输出和标准错误输出。
1. 标准输入(stdin) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:代码为 0 ,使用 < <<
2. 标准输出(stdout)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:代码为 1 ,使用 > 或 >>
3. 标准错误输出(stderr):代码为 2 ,使用 2> 或 2>>
1. 标准输入 (stdin) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:代码为 0 ,使用 < <<
2. 标准输出 (stdout)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:代码为 1 ,使用 > 或 >>
3. 标准错误输出 (stderr):代码为 2 ,使用 2> 或 2>>
其中,有一个箭头的表示以覆盖的方式重定向,而有两个箭头的表示以追加的方式重定向。
@ -815,7 +815,7 @@ declare -x HISTCONTROL="ignoredups"
declare -x HISTSIZE="1000"
declare -x HOME="/home/dmtsai"
declare -x HOSTNAME="study.centos.vbird"
.....(其他省略).....
.....( 其他省略 ).....
$ export | cut -c 12
```
@ -961,7 +961,7 @@ $ grep -n 'the' regular_express.txt
因为 { 与 } 的符号在 shell 是有特殊意义的,因此必须要使用使用转义字符进行转义。
```html
$ grep -n 'go\{2,5\}g' regular_express.txt
$ grep -n 'go\{2, 5\} g' regular_express.txt
```
## printf
@ -980,7 +980,7 @@ $ printf '%10s %5i %5i %5i %8.2f \n' $(cat printf.txt)
## awk
```html
$ awk '条件类型1{动作1} 条件类型2{动作2} ...' filename
$ awk ' 条件类型 1{ 动作 1} 条件类型 2{ 动作 2} ...' filename
```
awk 每次处理一行,处理的最小单位是字段,每个字段的命名方式为:\<img src="https://latex.codecogs.com/gif.latex?nn为字段号从1开始\"/>0 表示一整行。
@ -1036,16 +1036,16 @@ daemon 2
| 命令 | 作用 |
| -- | -- |
| :w | 写入磁盘|
| :w | 写入磁盘 |
| :w! | 当文件为只读时,强制写入磁盘。到底能不能写入,与用户对该文件的权限有关 |
| :q | 离开|
| :q! | 强制离开不保存|
| :wq | 写入磁盘后离开|
| :wq!| 强制写入磁盘后离开|
| :q | 离开 |
| :q! | 强制离开不保存 |
| :wq | 写入磁盘后离开 |
| :wq!| 强制写入磁盘后离开 |
# 参考资料
- 鸟哥. 鸟 哥 的 Linux 私 房 菜 基 础 篇 第 三 版[J]. 2009.
- [Linux 平台上的软件包管理](https://www.ibm.com/developerworks/cn/linux/l-cn-rpmdpkg/index.html)
- 鸟哥 . 鸟 哥 的 Linux 私 房 菜 基 础 篇 第 三 版 [J]. 2009.
- [Linux 平台上的软件包管理 ](https://www.ibm.com/developerworks/cn/linux/l-cn-rpmdpkg/index.html)

View File

@ -1328,7 +1328,7 @@ private int cnt = 0;
public void Insert(Integer num) {
// 插入要保证两个堆存于平衡状态
if(cnt % 2 == 0) {
if(cnt % 2 == 0) {
// 为偶数的情况下插入到最小堆,先经过最大堆筛选,这样就能保证最大堆中的元素都小于最小堆中的元素
maxHeap.add(num);
minHeep.add(maxHeap.poll());

View File

@ -16,7 +16,7 @@
* [2.1 归并方法](#21-归并方法)
* [2.2 自顶向下归并排序](#22-自顶向下归并排序)
* [2.3 自底向上归并排序](#23-自底向上归并排序)
* [3.快速排序](#3快速排序)
* [3. 快速排序](#3-快速排序)
* [3.1 基本算法](#31-基本算法)
* [3.2 切分](#32-切分)
* [3.3 性能分析](#33-性能分析)
@ -371,7 +371,7 @@ public static void busort(Comparable[] a) {
}
```
## 3.快速排序
## 3. 快速排序
### 3.1 基本算法

View File

@ -43,7 +43,7 @@
* [5. 共享内存](#5-共享内存)
* [6. 套接字](#6-套接字)
* [经典同步问题](#经典同步问题)
* [1. 读者-写者问题](#1-读者-写者问题)
* [1. 读者 - 写者问题](#1-读者---写者问题)
* [2. 哲学家进餐问题](#2-哲学家进餐问题)
* [第三章 死锁](#第三章-死锁)
* [死锁的条件](#死锁的条件)
@ -121,7 +121,7 @@
### 1. 外中断
由 CPU 执行指令以外的事件引起,如 I/O 结束中断,表示设备输入/输出处理已经完成,处理器能够发送下一个输入/输出请求。此外还有时钟中断、控制台中断等。
由 CPU 执行指令以外的事件引起,如 I/O 结束中断,表示设备输入 / 输出处理已经完成,处理器能够发送下一个输入 / 输出请求。此外还有时钟中断、控制台中断等。
### 2. 异常
@ -163,7 +163,7 @@
- 系统开销由于创建或撤销进程时系统都要为之分配或回收资源如内存空间、I/O 设备等,因此操作系统所付出的开销远大于创建或撤销线程时的开销。类似地,在进行进程切换时,涉及当前执行进程 CPU 环境的保存及新调度进程 CPU 环境的设置。而线程切换时只需保存和设置少量寄存器内容,开销很小。
- 通信方面:进程间通信 (IPC) 需要进程同步和互斥手段的辅助,以保证数据的一致性,而线程间可以通过直接读/写同一进程中的数据段(如全局变量)来进行通信。
- 通信方面:进程间通信 (IPC) 需要进程同步和互斥手段的辅助,以保证数据的一致性,而线程间可以通过直接读 / 写同一进程中的数据段(如全局变量)来进行通信。
举例QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 HTTP 请求线程、事件响应线程、渲染线程等等,线程的并发执行使得在浏览器中点击一个新链接从而发起 HTTP 请求时,浏览器还可以响应用户的其它事件。
@ -207,7 +207,7 @@ shortest remaining time nextSRTN
除了可以手动赋予优先权之外,还可以把响应比作为优先权,这种调度方式叫做高响应比优先调度算法。
响应比 = (等待时间 + 要求服务时间) / 要求服务时间 = 响应时间 / 要求服务时间
响应比 = ( 等待时间 + 要求服务时间 ) / 要求服务时间 = 响应时间 / 要求服务时间
这种调度算法主要是为了解决 SJF 中长作业可能会饿死的问题,因为随着等待时间的增长,响应比也会越来越高。
@ -269,7 +269,7 @@ down 和 up 操作需要被设计成原语,不可分割,通常的做法是
如果信号量的取值只能为 0 或者 1那么就成为了**互斥量Mutex**0 表示临界区已经加锁1 表示临界区解锁。
```c
typedef int semaphore ;
typedef int semaphore;
semaphore mutex = 1;
void P1() {
down(mutex);
@ -284,7 +284,7 @@ void P2() {
}
```
**使用信号量实现生产者-消费者问题**
**使用信号量实现生产者 - 消费者问题**
使用一个互斥量 mutex 来对临界资源进行访问empty 记录空缓冲区的数量full 记录满缓冲区的数量。
@ -292,7 +292,7 @@ void P2() {
```c
#define N 100
typedef int semaphore ;
typedef int semaphore;
semaphore mutex = 1;
semaphore empty = N;
semaphore full = 0;
@ -324,21 +324,21 @@ void consumer() {
使用信号量机制实现的生产者消费者问题需要客户端代码做很多控制,而管程把控制的代码独立出来,不仅不容易出错,也使得客户端代码调用更容易。
c 语言不支持管程,下面的示例代码使用了类 Pascal 语言来描述管程。示例代码中的管程提供了 insert() 和 remove() 方法,客户端代码通过调用这两个方法来解决生产者-消费者问题。
c 语言不支持管程,下面的示例代码使用了类 Pascal 语言来描述管程。示例代码中的管程提供了 insert() 和 remove() 方法,客户端代码通过调用这两个方法来解决生产者 - 消费者问题。
```pascal
monitor ProducerConsumer
integer i;
condition c;
procedure insert();
begin
end;
procedure remove();
begin
end;
end monitor;
```
@ -347,7 +347,7 @@ end monitor;
管程引入了 **条件变量** 以及相关的操作:**wait()** 和 **signal()** 来实现同步操作。对条件变量执行 wait() 操作会导致调用进程阻塞把管程让出来让另一个进程持有。signal() 操作用于唤醒被阻塞的进程。
**使用管程实现生成者-消费者问题**
**使用管程实现生成者 - 消费者问题**
```pascal
monitor ProducerConsumer
@ -433,7 +433,7 @@ Linux 中管道是通过空文件来实现。
生产者和消费者问题前面已经讨论过。
### 1. 读者-写者问题
### 1. 读者 - 写者问题
允许多个进程同时对数据进行读操作,但是不允许读和写以及写和写操作同时发生。
@ -677,7 +677,7 @@ void philosopher(int i) {
70120304230321201701
进程运行时,先将 7,0,1 三个页面装入内存。当进程要访问页面 2 时,产生缺页中断,会将页面 7 换出,因为页面 7 再次被访问的时间最长。
进程运行时,先将 7, 0, 1 三个页面装入内存。当进程要访问页面 2 时,产生缺页中断,会将页面 7 换出,因为页面 7 再次被访问的时间最长。
### 2. 先进先出FIFO
@ -730,6 +730,6 @@ CSCAN 对 SCAN 进行了改动,要求磁头始终沿着一个方向移动。
# 参考资料
- Tanenbaum A S, Bos H. Modern operating systems[M]. Prentice Hall Press, 2014.
- 汤子瀛, 哲凤屏, 汤小丹. 计算机操作系统[M]. 西安电子科技大学出版社, 2001.
- Bryant, R. E., & OHallaron, D. R. (2004). 深入理解计算机系统.
- [进程间的几种通信方式](http://blog.csdn.net/yufaw/article/details/7409596)
- 汤子瀛 , 哲凤屏 , 汤小丹 . 计算机操作系统 [M]. 西安电子科技大学出版社 , 2001.
- Bryant, R. E., & OHallaron, D. R. (2004). 深入理解计算机系统 .
- [ 进程间的几种通信方式 ](http://blog.csdn.net/yufaw/article/details/7409596)

View File

@ -116,7 +116,7 @@
## 主机之间的通信方式
**1. 客户-服务器C/S**
**1. 客户 - 服务器C/S**
客户是服务的请求方,服务器是服务的提供方。