Skip to content

Commit 6c274c4

Browse files
committed
auto commit
1 parent ae1e140 commit 6c274c4

File tree

3 files changed

+126
-82
lines changed

3 files changed

+126
-82
lines changed

notes/Leetcode 题解.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ Output: 1
263263

264264
```java
265265
public int findMin(int[] nums) {
266-
int l = 0, h = nums.length;
266+
int l = 0, h = nums.length - 1;
267267
while (l < h) {
268268
int m = l + (h - l) / 2;
269269
if (nums[m] <= nums[h]) h = m;

notes/剑指 offer 题解.md

Lines changed: 124 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -909,15 +909,15 @@ public ListNode deleteNode(ListNode head, ListNode tobeDelete) {
909909

910910
```java
911911
public ListNode deleteDuplication(ListNode pHead) {
912-
if (pHead == null) return null;
912+
if (pHead == null || pHead.next == null) return pHead;
913913
ListNode next = pHead.next;
914-
if (next == null) return pHead;
915914
if (pHead.val == next.val) {
916915
while (next != null && pHead.val == next.val) next = next.next;
917916
return deleteDuplication(next);
917+
} else {
918+
pHead.next = deleteDuplication(pHead.next);
919+
return pHead;
918920
}
919-
pHead.next = deleteDuplication(pHead.next);
920-
return pHead;
921921
}
922922
```
923923

@@ -2256,6 +2256,8 @@ private int height(TreeNode root) {
22562256

22572257
## 题目描述
22582258

2259+
[NowCoder](https://www.nowcoder.com/practice/e02fdb54d7524710a7d664d082bb7811?tpId=13&tqId=11193&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
2260+
22592261
一个整型数组里除了两个数字之外,其他的数字都出现了两次,找出这两个数。
22602262

22612263
## 解题思路
@@ -2267,73 +2269,91 @@ private int height(TreeNode root) {
22672269
diff &= -diff 得到出 diff 最右侧不为 0 的位,也就是不存在重复的两个元素在位级表示上最右侧不同的那一位,利用这一位就可以将两个元素区分开来。
22682270

22692271
```java
2270-
public void FindNumsAppearOnce(int[] array, int num1[], int num2[]) {
2271-
int diff = 0;
2272-
for (int num : array) diff ^= num;
2273-
// 得到最右一位
2274-
diff &= -diff;
2275-
for (int num : array) {
2276-
if ((num & diff) == 0) num1[0] ^= num;
2277-
else num2[0] ^= num;
2272+
public void FindNumsAppearOnce(int[] nums, int num1[], int num2[]) {
2273+
int diff = 0;
2274+
for (int num : nums) {
2275+
diff ^= num;
2276+
}
2277+
// 得到最右一位
2278+
diff &= -diff;
2279+
for (int num : nums) {
2280+
if ((num & diff) == 0) {
2281+
num1[0] ^= num;
2282+
} else {
2283+
num2[0] ^= num;
2284+
}
2285+
}
22782286
}
2279-
}
22802287
```
22812288

22822289
# 57.1 和为 S 的两个数字
22832290

22842291
## 题目描述
22852292

2293+
[NowCoder](https://www.nowcoder.com/practice/390da4f7a00f44bea7c2f3d19491311b?tpId=13&tqId=11195&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
2294+
22862295
输入一个递增排序的数组和一个数字 S,在数组中查找两个数,使得他们的和正好是 S,如果有多对数字的和等于 S,输出两个数的乘积最小的。
22872296

22882297
## 解题思路
22892298

22902299
使用双指针,一个指针指向元素较小的值,一个指针指向元素较大的值。指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。
22912300

2292-
如果两个指针指向元素的和 sum == target,那么得到要求的结果;如果 sum > target,移动较大的元素,使 sum 变小一些;如果 sum < target,移动较小的元素,使 sum 变大一些。
2301+
- 如果两个指针指向元素的和 sum == target,那么得到要求的结果;
2302+
- 如果 sum > target,移动较大的元素,使 sum 变小一些;
2303+
- 如果 sum < target,移动较小的元素,使 sum 变大一些。
22932304

22942305
```java
22952306
public ArrayList<Integer> FindNumbersWithSum(int[] array, int sum) {
22962307
int i = 0, j = array.length - 1;
22972308
while (i < j) {
22982309
int cur = array[i] + array[j];
2299-
if (cur == sum) return new ArrayList<Integer>(Arrays.asList(array[i], array[j]));
2300-
else if (cur < sum) i++;
2310+
if (cur == sum) return new ArrayList<>(Arrays.asList(array[i], array[j]));
2311+
if (cur < sum) i++;
23012312
else j--;
23022313
}
2303-
return new ArrayList<Integer>();
2314+
return new ArrayList<>();
23042315
}
23052316
```
23062317

23072318
# 57.2 和为 S 的连续正数序列
23082319

23092320
## 题目描述
23102321

2311-
和为 100 的连续序列有 18, 19, 20, 21, 22。
2322+
[NowCoder](https://www.nowcoder.com/practice/c451a3fd84b64cb19485dad758a55ebe?tpId=13&tqId=11194&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
2323+
2324+
输出所有和为 S 的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
2325+
2326+
例如和为 100 的连续序列有:
2327+
2328+
```
2329+
[9, 10, 11, 12, 13, 14, 15, 16]
2330+
[18, 19, 20, 21, 22]。
2331+
```
23122332

23132333
## 解题思路
23142334

23152335
```java
23162336
public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
23172337
ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
2318-
int first = 1, last = 2;
2338+
int start = 1, end = 2;
23192339
int curSum = 3;
2320-
while (first <= sum / 2 && last < sum) {
2340+
while (end < sum) {
23212341
if (curSum > sum) {
2322-
curSum -= first;
2323-
first++;
2342+
curSum -= start;
2343+
start++;
23242344
} else if (curSum < sum) {
2325-
last++;
2326-
curSum += last;
2345+
end++;
2346+
curSum += end;
23272347
} else {
23282348
ArrayList<Integer> list = new ArrayList<>();
2329-
for (int i = first; i <= last; i++) {
2349+
for (int i = start; i <= end; i++) {
23302350
list.add(i);
23312351
}
23322352
ret.add(list);
2333-
curSum -= first;
2334-
first++;
2335-
last++;
2336-
curSum += last;
2353+
curSum -= start;
2354+
start++;
2355+
end++;
2356+
curSum += end;
23372357
}
23382358
}
23392359
return ret;
@@ -2350,11 +2370,14 @@ public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
23502370

23512371
## 解题思路
23522372

2353-
题目应该有一个隐含条件,就是不能用额外的空间。虽然 Java 的题目输入参数为 String 类型,需要先创建一个字符数组使得空间复杂度为 O(n),但是正确的参数类型应该和原书一样,为字符数组,并且只能使用该字符数组的空间。任何使用了额外空间的解法在面试时都会大打折扣,包括递归解法。正确的解法应该是和书上一样,先旋转每个单词,再旋转整个字符串。
2373+
[NowCoder](https://www.nowcoder.com/practice/3194a4f4cf814f63919d0790578d51f3?tpId=13&tqId=11197&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
2374+
2375+
题目应该有一个隐含条件,就是不能用额外的空间。虽然 Java 的题目输入参数为 String 类型,需要先创建一个字符数组使得空间复杂度为 O(N),但是正确的参数类型应该和原书一样,为字符数组,并且只能使用该字符数组的空间。任何使用了额外空间的解法在面试时都会大打折扣,包括递归解法。
2376+
2377+
正确的解法应该是和书上一样,先旋转每个单词,再旋转整个字符串。
23542378

23552379
```java
23562380
public String ReverseSentence(String str) {
2357-
if (str.length() == 0) return str;
23582381
int n = str.length();
23592382
char[] chars = str.toCharArray();
23602383
int i = 0, j = 0;
@@ -2370,58 +2393,73 @@ public String ReverseSentence(String str) {
23702393
}
23712394

23722395
private void reverse(char[] c, int i, int j) {
2373-
while(i < j) {
2374-
char t = c[i]; c[i] = c[j]; c[j] = t;
2375-
i++; j--;
2396+
while (i < j) {
2397+
swap(c, i++, j--);
23762398
}
23772399
}
2400+
2401+
private void swap(char[] c, int i, int j) {
2402+
char t = c[i];
2403+
c[i] = c[j];
2404+
c[j] = t;
2405+
}
23782406
```
23792407

23802408
# 58.2 左旋转字符串
23812409

23822410
## 题目描述
23832411

2412+
[NowCoder](https://www.nowcoder.com/practice/12d959b108cb42b1ab72cef4d36af5ec?tpId=13&tqId=11196&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
2413+
23842414
对于一个给定的字符序列 S,请你把其循环左移 K 位后的序列输出。例如,字符序列 S=”abcXYZdef”, 要求输出循环左移 3 位后的结果,即“XYZdefabc”。
23852415

23862416
## 解题思路
23872417

2418+
将 "abcXYZdef" 旋转左移三位,可以先将 "abc" 和 "XYZdef" 分别旋转,得到 "cbafedZYX",然后再把整个字符串旋转得到 "XYZdefabc"。
2419+
23882420
```java
23892421
public String LeftRotateString(String str, int n) {
2390-
if(str.length() == 0) return "";
2391-
char[] c = str.toCharArray();
2392-
reverse(c, 0, n - 1);
2393-
reverse(c, n, c.length - 1);
2394-
reverse(c, 0, c.length - 1);
2395-
return new String(c);
2422+
if (n >= str.length()) return str;
2423+
char[] chars = str.toCharArray();
2424+
reverse(chars, 0, n - 1);
2425+
reverse(chars, n, chars.length - 1);
2426+
reverse(chars, 0, chars.length - 1);
2427+
return new String(chars);
23962428
}
23972429

2398-
private void reverse(char[] c, int i, int j) {
2399-
while(i < j) {
2400-
char t = c[i]; c[i] = c[j]; c[j] = t;
2401-
i++; j--;
2430+
private void reverse(char[] chars, int i, int j) {
2431+
while (i < j) {
2432+
swap(chars, i++, j--);
24022433
}
24032434
}
2435+
2436+
private void swap(char[] chars, int i, int j) {
2437+
char t = chars[i];
2438+
chars[i] = chars[j];
2439+
chars[j] = t;
2440+
}
24042441
```
24052442

24062443
# 59. 滑动窗口的最大值
24072444

24082445
## 题目描述
24092446

2447+
[NowCoder](https://www.nowcoder.com/practice/1624bc35a45c42c0bc17d17fa0cba788?tpId=13&tqId=11217&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
2448+
24102449
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组 {2, 3, 4, 2, 6, 2, 5, 1} 及滑动窗口的大小 3,那么一共存在 6 个滑动窗口,他们的最大值分别为 {4, 4, 6, 6, 6, 5}。
24112450

24122451
## 解题思路
24132452

24142453
```java
24152454
public ArrayList<Integer> maxInWindows(int[] num, int size) {
24162455
ArrayList<Integer> ret = new ArrayList<>();
2417-
if (size > num.length || size < 1) return ret;
2418-
// 构建最大堆,即堆顶元素是堆的最大值。
24192456
PriorityQueue<Integer> heap = new PriorityQueue<Integer>((o1, o2) -> o2 - o1);
2457+
if (size > num.length || size < 1) return ret;
24202458
for (int i = 0; i < size; i++) heap.add(num[i]);
24212459
ret.add(heap.peek());
2422-
for (int i = 1; i + size - 1 < num.length; i++) {
2460+
for (int i = 1, j = i + size - 1; j < num.length; i++, j++) {
24232461
heap.remove(num[i - 1]);
2424-
heap.add(num[i + size - 1]);
2462+
heap.add(num[j]);
24252463
ret.add(heap.peek());
24262464
}
24272465
return ret;
@@ -2432,35 +2470,39 @@ public ArrayList<Integer> maxInWindows(int[] num, int size) {
24322470

24332471
## 题目描述
24342472

2473+
[Lintcode](https://www.lintcode.com/en/problem/dices-sum/)
2474+
24352475
把 n 个骰子仍在地上,求点数和为 s 的概率。
24362476

24372477
## 解题思路
24382478

24392479
### 动态规划解法
24402480

2481+
使用一个二维数组 dp 存储点数出现的次数,其中 dp[i][j] 表示前 i 个骰子产生点数 j 的次数。
2482+
24412483
空间复杂度:O(N<sup>2</sup>)
24422484

24432485
```java
2444-
private static int face = 6;
2445-
2446-
public double countProbability(int n, int s) {
2447-
if (n < 1 || s < n) return 0.0;
2448-
int pointNum = face * n;
2449-
int[][] dp = new int[n][pointNum];
2450-
for (int i = 0; i < face; i++) {
2451-
dp[0][i] = 1;
2486+
public List<Map.Entry<Integer, Double>> dicesSum(int n) {
2487+
final int face = 6;
2488+
final int pointNum = face * n;
2489+
long[][] dp = new long[n + 1][pointNum + 1];
2490+
for (int i = 1; i <= face; i++) {
2491+
dp[1][i] = 1;
24522492
}
2453-
for (int i = 1; i < n; i++) {
2454-
for (int j = i; j < pointNum; j++) { // 使用 i 个骰子最小点数为 i
2455-
for (int k = 1; k <= face; k++) {
2456-
if (j - k >= 0) {
2457-
dp[i][j] += dp[i - 1][j - k];
2458-
}
2493+
for (int i = 2; i <= n; i++) {
2494+
for (int j = i; j <= pointNum; j++) { // 使用 i 个骰子最小点数为 i
2495+
for (int k = 1; k <= face && k <= j; k++) {
2496+
dp[i][j] += dp[i - 1][j - k];
24592497
}
24602498
}
24612499
}
2462-
int totalNum = (int) Math.pow(6, n);
2463-
return (double) dp[n - 1][s - 1] / totalNum;
2500+
final double totalNum = Math.pow(6, n);
2501+
List<Map.Entry<Integer, Double>> ret = new ArrayList<>();
2502+
for (int i = n; i <= pointNum; i++) {
2503+
ret.add(new AbstractMap.SimpleEntry<>(i, dp[n][i] / totalNum));
2504+
}
2505+
return ret;
24642506
}
24652507
```
24662508

@@ -2469,28 +2511,30 @@ public double countProbability(int n, int s) {
24692511
空间复杂度:O(N)
24702512

24712513
```java
2472-
private static int face = 6;
2473-
2474-
public double countProbability(int n, int s) {
2475-
if (n < 1 || s < n) return 0.0;
2476-
int pointNum = face * n;
2477-
int[][] dp = new int[2][pointNum];
2478-
for (int i = 0; i < face; i++) {
2514+
public List<Map.Entry<Integer, Double>> dicesSum(int n) {
2515+
final int face = 6;
2516+
final int pointNum = face * n;
2517+
long[][] dp = new long[2][pointNum + 1];
2518+
for (int i = 1; i <= face; i++) {
24792519
dp[0][i] = 1;
24802520
}
24812521
int flag = 1;
2482-
for (int i = 1; i < n; i++) {
2483-
for (int j = i; j < pointNum; j++) { // 使用 i 个骰子最小点数为 i
2484-
for (int k = 1; k <= face; k++) {
2485-
if (j - k >= 0) {
2486-
dp[flag][j] += dp[1 - flag][j - k];
2487-
}
2522+
for (int i = 2; i <= n; i++, flag = 1 - flag) {
2523+
for (int j = 0; j <= pointNum; j++) {
2524+
dp[flag][j] = 0; // 旋转数组清零
2525+
}
2526+
for (int j = i; j <= pointNum; j++) { // 使用 i 个骰子最小点数为 i
2527+
for (int k = 1; k <= face && k <= j; k++) {
2528+
dp[flag][j] += dp[1 - flag][j - k];
24882529
}
24892530
}
2490-
flag = 1 - flag;
24912531
}
2492-
int totalNum = (int) Math.pow(6, n);
2493-
return (double) dp[flag][s - 1] / totalNum;
2532+
final double totalNum = Math.pow(6, n);
2533+
List<Map.Entry<Integer, Double>> ret = new ArrayList<>();
2534+
for (int i = n; i <= pointNum; i++) {
2535+
ret.add(new AbstractMap.SimpleEntry<>(i, dp[1 - flag][i] / totalNum));
2536+
}
2537+
return ret;
24942538
}
24952539
```
24962540

notes/正则表达式.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ aBCd
328328

329329
# 九、前后查找
330330

331-
前后查找规定了匹配的内容首尾应该匹配的内容,但是又不包含首尾匹配的内容。向前查找用 **?=** 来定义,它规定了尾部匹配的内容,这个匹配的内容在 ?= 之后定义。所谓向前查找,就是规定了一个匹配的内容,然后以这个内容为尾部向前面查找需要匹配的内容。向后匹配用 ?<= 定义(注:javaScript不支持向后匹配,java对其支持也不完善)。
331+
前后查找规定了匹配的内容首尾应该匹配的内容,但是又不包含首尾匹配的内容。向前查找用 **?=** 来定义,它规定了尾部匹配的内容,这个匹配的内容在 ?= 之后定义。所谓向前查找,就是规定了一个匹配的内容,然后以这个内容为尾部向前面查找需要匹配的内容。向后匹配用 ?<= 定义(注: javaScript 不支持向后匹配, java 对其支持也不完善)。
332332

333333
**应用**
334334

0 commit comments

Comments
 (0)