@@ -489,7 +489,7 @@ A partition like "ababcbacadefegde", "hijhklij" is incorrect, because it splits
489
489
490
490
``` java
491
491
public List<Integer > partitionLabels(String S ) {
492
- List<Integer > ret = new ArrayList<> ();
492
+ List<Integer > partitions = new ArrayList<> ();
493
493
int [] lastIndexs = new int [26 ];
494
494
for (int i = 0 ; i < S . length(); i++ ) {
495
495
lastIndexs[S . charAt(i) - ' a' ] = i;
@@ -502,10 +502,10 @@ public List<Integer> partitionLabels(String S) {
502
502
if (index == i) continue ;
503
503
if (index > lastIndex) lastIndex = index;
504
504
}
505
- ret . add(lastIndex - firstIndex + 1 );
505
+ partitions . add(lastIndex - firstIndex + 1 );
506
506
firstIndex = lastIndex + 1 ;
507
507
}
508
- return ret ;
508
+ return partitions ;
509
509
}
510
510
```
511
511
@@ -564,9 +564,9 @@ Input: numbers={2, 7, 11, 15}, target=9
564
564
Output: index1=1, index2=2
565
565
```
566
566
567
- 题目描述:从一个已经排序的数组中找出两个数 ,使它们的和为 0。
567
+ 题目描述:在有序数组中找出两个数 ,使它们的和为 0。
568
568
569
- 使用双指针,一个指针指向元素较小的值,一个指针指向元素较大的值 。指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。
569
+ 使用双指针,一个指针指向值较小的元素,一个指针指向值较大的元素 。指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。
570
570
571
571
如果两个指针指向元素的和 sum == target,那么得到要求的结果;如果 sum > target,移动较大的元素,使 sum 变小一些;如果 sum < target,移动较小的元素,使 sum 变大一些。
572
572
@@ -583,6 +583,31 @@ public int[] twoSum(int[] numbers, int target) {
583
583
}
584
584
```
585
585
586
+ ** 两数平方和**
587
+
588
+ [ Leetcode : 633. Sum of Square Numbers (Easy)] ( https://leetcode.com/problems/sum-of-square-numbers/description/ )
589
+
590
+ ``` html
591
+ Input: 5
592
+ Output: True
593
+ Explanation: 1 * 1 + 2 * 2 = 5
594
+ ```
595
+
596
+ 题目描述:判断一个数是否为两个数的平方和,例如 5 = 1<sup >2</sup > + 2<sup >2</sup >。
597
+
598
+ ``` java
599
+ public boolean judgeSquareSum(int c) {
600
+ int i = 0 , j = (int ) Math . sqrt(c);
601
+ while (i <= j) {
602
+ int powSum = i * i + j * j;
603
+ if (powSum == c) return true ;
604
+ if (powSum > c) j-- ;
605
+ else i++ ;
606
+ }
607
+ return false ;
608
+ }
609
+ ```
610
+
586
611
** 反转字符串中的元音字符**
587
612
588
613
[ Leetcode : 345. Reverse Vowels of a String (Easy)] ( https://leetcode.com/problems/reverse-vowels-of-a-string/description/ )
@@ -597,54 +622,24 @@ Given s = "leetcode", return "leotcede".
597
622
private HashSet<Character > vowels = new HashSet<> (Arrays . asList(' a' , ' e' , ' i' , ' o' , ' u' , ' A' , ' E' , ' I' , ' O' , ' U' ));
598
623
599
624
public String reverseVowels(String s) {
600
- if (s. length() == 0 ) return s;
601
625
int i = 0 , j = s. length() - 1 ;
602
626
char [] result = new char [s. length()];
603
627
while (i <= j) {
604
628
char ci = s. charAt(i);
605
629
char cj = s. charAt(j);
606
630
if (! vowels. contains(ci)) {
607
- result[i] = ci;
608
- i++ ;
631
+ result[i++ ] = ci;
609
632
} else if (! vowels. contains(cj)) {
610
- result[j] = cj;
611
- j-- ;
633
+ result[j-- ] = cj;
612
634
} else {
613
- result[i] = cj;
614
- result[j] = ci;
615
- i++ ;
616
- j-- ;
635
+ result[i++ ] = cj;
636
+ result[j-- ] = ci;
617
637
}
618
638
}
619
639
return new String (result);
620
640
}
621
641
```
622
642
623
- ** 两数平方和**
624
-
625
- [ Leetcode : 633. Sum of Square Numbers (Easy)] ( https://leetcode.com/problems/sum-of-square-numbers/description/ )
626
-
627
- ``` html
628
- Input: 5
629
- Output: True
630
- Explanation: 1 * 1 + 2 * 2 = 5
631
- ```
632
-
633
- 题目描述:判断一个数是否为两个数的平方和,例如 5 = 1<sup >2</sup > + 2<sup >2</sup >。
634
-
635
- ``` java
636
- public boolean judgeSquareSum(int c) {
637
- int i = 0 , j = (int ) Math . sqrt(c);
638
- while (i <= j) {
639
- int powSum = i * i + j * j;
640
- if (powSum == c) return true ;
641
- if (powSum > c) j-- ;
642
- else i++ ;
643
- }
644
- return false ;
645
- }
646
- ```
647
-
648
643
** 回文字符串**
649
644
650
645
[ Leetcode : 680. Valid Palindrome II (Easy)] ( https://leetcode.com/problems/valid-palindrome-ii/description/ )
@@ -659,20 +654,20 @@ Explanation: You could delete the character 'c'.
659
654
660
655
``` java
661
656
public boolean validPalindrome(String s) {
662
- int i = 0 , j = s. length() - 1 ;
663
- while (i < j) {
657
+ int i = - 1 , j = s. length();
658
+ while (++ i < -- j) {
664
659
if (s. charAt(i) != s. charAt(j)) {
665
660
return isPalindrome(s, i, j - 1 ) || isPalindrome(s, i + 1 , j);
666
661
}
667
- i++ ;
668
- j-- ;
669
662
}
670
663
return true ;
671
664
}
672
665
673
- private boolean isPalindrome(String s, int l, int r) {
674
- while (l < r) {
675
- if (s. charAt(l++ ) != s. charAt(r-- )) return false ;
666
+ private boolean isPalindrome(String s, int i, int j) {
667
+ while (i < j) {
668
+ if (s. charAt(i++ ) != s. charAt(j-- )) {
669
+ return false ;
670
+ }
676
671
}
677
672
return true ;
678
673
}
@@ -682,6 +677,14 @@ private boolean isPalindrome(String s, int l, int r) {
682
677
683
678
[ Leetcode : 88. Merge Sorted Array (Easy)] ( https://leetcode.com/problems/merge-sorted-array/description/ )
684
679
680
+ ``` html
681
+ Input:
682
+ nums1 = [1,2,3,0,0,0], m = 3
683
+ nums2 = [2,5,6], n = 3
684
+
685
+ Output: [1,2,2,3,5,6]
686
+ ```
687
+
685
688
题目描述:把归并结果存到第一个数组上。
686
689
687
690
``` java
@@ -708,10 +711,9 @@ public void merge(int[] nums1, int m, int[] nums2, int n) {
708
711
public boolean hasCycle(ListNode head) {
709
712
if (head == null ) return false ;
710
713
ListNode l1 = head, l2 = head. next;
711
- while (l1 != null && l2 != null ) {
714
+ while (l1 != null && l2 != null && l2 . next != null ) {
712
715
if (l1 == l2) return true ;
713
716
l1 = l1. next;
714
- if (l2. next == null ) break ;
715
717
l2 = l2. next. next;
716
718
}
717
719
return false ;
@@ -734,18 +736,28 @@ Output:
734
736
735
737
``` java
736
738
public String findLongestWord(String s, List<String > d) {
737
- String ret = " " ;
738
- for (String str : d) {
739
- for (int i = 0 , j = 0 ; i < s. length() && j < str. length(); i++ ) {
740
- if (s. charAt(i) == str. charAt(j)) j++ ;
741
- if (j == str. length()) {
742
- if (ret. length() < str. length() || (ret. length() == str. length() && ret. compareTo(str) > 0 )) {
743
- ret = str;
744
- }
745
- }
739
+ String longestWord = " " ;
740
+ for (String target : d) {
741
+ int l1 = longestWord. length(), l2 = target. length();
742
+ if (l1 > l2 || (l1 == l2 && longestWord. compareTo(target) < 0 )) {
743
+ continue ;
744
+ }
745
+ if (isValid(s, target)) {
746
+ longestWord = target;
746
747
}
747
748
}
748
- return ret;
749
+ return longestWord;
750
+ }
751
+
752
+ private boolean isValid(String s, String target) {
753
+ int i = 0 , j = 0 ;
754
+ while (i < s. length() && j < target. length()) {
755
+ if (s. charAt(i) == target. charAt(j)) {
756
+ j++ ;
757
+ }
758
+ i++ ;
759
+ }
760
+ return j == target. length();
749
761
}
750
762
```
751
763
@@ -913,7 +925,7 @@ public String frequencySort(String s) {
913
925
914
926
<div align =" center " > <img src =" ../pics//4ff355cf-9a7f-4468-af43-e5b02038facc.jpg " /> </div ><br >
915
927
916
- 广度优先搜索的搜索过程有点像一层一层地进行遍历,每层遍历都以上一层遍历的结果作为起点,遍历一个长度 。需要注意的是,遍历过的节点不能再次被遍历。
928
+ 广度优先搜索的搜索过程有点像一层一层地进行遍历,每层遍历都以上一层遍历的结果作为起点,遍历一个距离能访问到的所有节点 。需要注意的是,遍历过的节点不能再次被遍历。
917
929
918
930
第一层:
919
931
@@ -931,11 +943,11 @@ public String frequencySort(String s) {
931
943
- 4 -> {}
932
944
- 3 -> {}
933
945
934
- 可以看到,每一轮遍历的节点都与根节点路径长度相同 。设 d<sub >i</sub > 表示第 i 个节点与根节点的路径长度 ,推导出一个结论:对于先遍历的节点 i 与后遍历的节点 j,有 d<sub >i</sub ><=d<sub >j</sub >。利用这个结论,可以求解最短路径等 ** 最优解** 问题:第一次遍历到目的节点,其所经过的路径为最短路径。
946
+ 可以看到,每一轮遍历的节点都与根节点距离相同 。设 d<sub >i</sub > 表示第 i 个节点与根节点的距离 ,推导出一个结论:对于先遍历的节点 i 与后遍历的节点 j,有 d<sub >i</sub ><=d<sub >j</sub >。利用这个结论,可以求解最短路径等 ** 最优解** 问题:第一次遍历到目的节点,其所经过的路径为最短路径。
935
947
936
948
在程序实现 BFS 时需要考虑以下问题:
937
949
938
- - 队列:用来存储每一轮遍历的节点 ;
950
+ - 队列:用来存储每一轮遍历得到的节点 ;
939
951
- 标记:对于遍历过的节点,应该将它标记,防止重复遍历。
940
952
941
953
** 计算在网格中从原点到特定点的最短路径长度**
@@ -947,34 +959,38 @@ public String frequencySort(String s) {
947
959
[1,0,1,1]]
948
960
```
949
961
950
- 1 表示可以经过某个位置。
962
+ 题目描述: 1 表示可以经过某个位置,求解从 (0, 0) 位置到 (tr, tc) 位置的最短路径长度 。
951
963
952
964
``` java
953
965
public int minPathLength(int [][] grids, int tr, int tc) {
954
- int [][] next = {{1 , 0 }, {- 1 , 0 }, {0 , 1 }, {0 , - 1 }};
966
+ int [][] direction = {{1 , 0 }, {- 1 , 0 }, {0 , 1 }, {0 , - 1 }};
955
967
int m = grids. length, n = grids[0 ]. length;
956
968
Queue<Position > queue = new LinkedList<> ();
957
- queue. add(new Position (0 , 0 , 1 ));
969
+ queue. add(new Position (0 , 0 ));
970
+ int pathLength = 0 ;
958
971
while (! queue. isEmpty()) {
959
- Position pos = queue. poll();
960
- for (int i = 0 ; i < 4 ; i++ ) {
961
- Position nextPos = new Position (pos. r + next[i][0 ], pos. c + next[i][1 ], pos. length + 1 );
962
- if (nextPos. r < 0 || nextPos. r >= m || nextPos. c < 0 || nextPos. c >= n) continue ;
963
- if (grids[nextPos. r][nextPos. c] != 1 ) continue ;
964
- grids[nextPos. r][nextPos. c] = 0 ; // 标记已经访问过
965
- if (nextPos. r == tr && nextPos. c == tc) return nextPos. length;
966
- queue. add(nextPos);
972
+ int size = queue. size();
973
+ pathLength++ ;
974
+ while (size-- > 0 ) {
975
+ Position cur = queue. poll();
976
+ for (int [] d : direction) {
977
+ Position next = new Position (cur. r + d[0 ], cur. c + d[1 ]);
978
+ if (next. r < 0 || next. r >= m || next. c < 0 || next. c >= n) continue ;
979
+ grids[next. r][next. c] = 0 ;
980
+ if (next. r == tr && next. c == tc) return pathLength;
981
+ queue. add(next);
982
+ }
967
983
}
968
984
}
969
985
return - 1 ;
970
986
}
971
987
972
988
private class Position {
973
- int r, c, length;
974
- Position (int r , int c , int length ) {
989
+ int r, c;
990
+
991
+ Position (int r , int c ) {
975
992
this . r = r;
976
993
this . c = c;
977
- this . length = length;
978
994
}
979
995
}
980
996
```
@@ -1082,8 +1098,8 @@ private void dfs(char[][] grid, int i, int j) {
1082
1098
return ;
1083
1099
}
1084
1100
grid[i][j] = ' 0' ;
1085
- for (int k = 0 ; k < direction. length; k ++ ) {
1086
- dfs(grid, i + direction[k][ 0 ], j + direction[k] [1 ]);
1101
+ for (int [] d : direction) {
1102
+ dfs(grid, i + d[ 0 ], j + d [1 ]);
1087
1103
}
1088
1104
}
1089
1105
```
@@ -1256,12 +1272,12 @@ private void dfs(int r, int c, boolean[][] canReach) {
1256
1272
Backtracking(回溯)属于 DFS。
1257
1273
1258
1274
- 普通 DFS 主要用在 ** 可达性问题** ,这种问题只需要执行到特点的位置然后返回即可。
1259
- - 而 Backtracking 主要用于求解 ** 排列组合** 问题,例如有 { 'a','b','c' } 三个字符,求解所有由这三个字符排列得到的字符串,这种问题在执行到特定的位置返回时,在返回之后还会继续执行求解过程 。
1275
+ - 而 Backtracking 主要用于求解 ** 排列组合** 问题,例如有 { 'a','b','c' } 三个字符,求解所有由这三个字符排列得到的字符串,这种问题在执行到特定的位置返回之后还会继续执行求解过程 。
1260
1276
1261
1277
因为 Backtracking 不是立即就返回,而要继续求解,因此在程序实现时,需要注意对元素的标记问题:
1262
1278
1263
1279
- 在访问一个新元素进入新的递归调用时,需要将新元素标记为已经访问,这样才能在继续递归调用时不用重复访问该元素;
1264
- - 但是在递归返回时,需要将该元素标记为未访问 ,因为只需要保证在一个递归链中不同时访问一个元素,可以访问已经访问过但是不在当前递归链中的元素。
1280
+ - 但是在递归返回时,需要将元素标记为未访问 ,因为只需要保证在一个递归链中不同时访问一个元素,可以访问已经访问过但是不在当前递归链中的元素。
1265
1281
1266
1282
** 数字键盘组合**
1267
1283
@@ -1365,13 +1381,13 @@ public boolean exist(char[][] board, String word) {
1365
1381
boolean [][] visited = new boolean [m][n];
1366
1382
for (int i = 0 ; i < m; i++ ) {
1367
1383
for (int j = 0 ; j < n; j++ ) {
1368
- if (dfs (board, visited, word, 0 , i, j)) return true ;
1384
+ if (backtracking (board, visited, word, 0 , i, j)) return true ;
1369
1385
}
1370
1386
}
1371
1387
return false ;
1372
1388
}
1373
1389
1374
- private boolean dfs (char [][] board, boolean [][] visited, String word, int start, int r, int c) {
1390
+ private boolean backtracking (char [][] board, boolean [][] visited, String word, int start, int r, int c) {
1375
1391
if (start == word. length()) {
1376
1392
return true ;
1377
1393
}
@@ -1380,7 +1396,7 @@ private boolean dfs(char[][] board, boolean[][] visited, String word, int start,
1380
1396
}
1381
1397
visited[r][c] = true ;
1382
1398
for (int [] d : direction) {
1383
- if (dfs (board, visited, word, start + 1 , r + d[0 ], c + d[1 ])) {
1399
+ if (backtracking (board, visited, word, start + 1 , r + d[0 ], c + d[1 ])) {
1384
1400
return true ;
1385
1401
}
1386
1402
}
@@ -1394,11 +1410,11 @@ private boolean dfs(char[][] board, boolean[][] visited, String word, int start,
1394
1410
[ Leetcode : 257. Binary Tree Paths (Easy)] ( https://leetcode.com/problems/binary-tree-paths/description/ )
1395
1411
1396
1412
``` html
1397
- 1
1413
+ 1
1398
1414
/ \
1399
1415
2 3
1400
- \
1401
- 5
1416
+ \
1417
+ 5
1402
1418
```
1403
1419
1404
1420
``` html
@@ -1410,18 +1426,18 @@ public List<String> binaryTreePaths(TreeNode root) {
1410
1426
List<String > paths = new ArrayList ();
1411
1427
if (root == null ) return paths;
1412
1428
List<Integer > values = new ArrayList<> ();
1413
- dfs (root, values, paths);
1429
+ backtracking (root, values, paths);
1414
1430
return paths;
1415
1431
}
1416
1432
1417
- private void dfs (TreeNode node, List<Integer > values, List<String > paths) {
1433
+ private void backtracking (TreeNode node, List<Integer > values, List<String > paths) {
1418
1434
if (node == null ) return ;
1419
1435
values. add(node. val);
1420
1436
if (isLeaf(node)) {
1421
1437
paths. add(buildPath(values));
1422
1438
} else {
1423
- dfs (node. left, values, paths);
1424
- dfs (node. right, values, paths);
1439
+ backtracking (node. left, values, paths);
1440
+ backtracking (node. right, values, paths);
1425
1441
}
1426
1442
values. remove(values. size() - 1 );
1427
1443
}
@@ -1492,7 +1508,7 @@ private void backtracking(List<Integer> permuteList, boolean[] visited, int[] nu
1492
1508
[[1,1,2], [1,2,1], [2,1,1]]
1493
1509
```
1494
1510
1495
- 题目描述:数组元素可能含有相同的元素,进行排列时就有可能出现 重复的排列 ,要求重复的排列只返回一个。
1511
+ 题目描述:数组元素可能含有相同的元素,进行排列时就有可能出现重复的排列 ,要求重复的排列只返回一个。
1496
1512
1497
1513
在实现上,和 Permutations 不同的是要先排序,然后在添加一个元素时,判断这个元素是否等于前一个元素,如果等于,并且前一个元素还未访问,那么就跳过这个元素。
1498
1514
0 commit comments