🌓

967. Numbers With Same Consecutive Differences

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution {
public int[] numsSameConsecDiff(int n, int k) {
List<Integer> ans = new ArrayList<>();
for (int i = 1; i < 10; i++) {
backtrack(ans, i, 2, i + k, n, k);
if (k != 0) {
backtrack(ans, i, 2, i - k, n, k);
}
}
int[] res = new int[ans.size()];
for (int i = 0; i < ans.size(); i++) {
res[i] = ans.get(i);
}
return res;
}

private void backtrack(List<Integer> ans, int num, int pos, int currDigit, int n, int k) {
if (currDigit < 0 || currDigit > 9) {
return;
}
int currNum = num * 10 + currDigit;
if (pos == n) {
ans.add(currNum);
return;
}
backtrack(ans, currNum, pos + 1, currDigit + k, n, k);
if (k != 0) {
backtrack(ans, currNum, pos + 1, currDigit - k, n, k);
}
}
}

Read More

912. Sort an Array

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
class Solution {
public int[] sortArray(int[] nums) {
mergeSort(nums, nums.clone(), 0, nums.length - 1);
return nums;
}

private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}

// Bubble Sort 最大值到最后一个位置, 次大到倒数第二个...
public void bubbleSort(int[] nums) {
int inPlaceCount = 0;
// We have nums.length numbers to process in order to let each of them be in
// the right place
for (int i = 0; i < nums.length - 1; i++) {
boolean isSorted = true;
// We don't bother the nums that are in place which is the last
// "inPlaceCount" nums.
for (int j = 0; j < nums.length - inPlaceCount - 1; j++) {
if (nums[j] > nums[j + 1]) {
isSorted = false;
swap(nums, j, j + 1);
}
}
// End the outer for loop earlier.
if (isSorted)
break;
inPlaceCount += 1;
}
return nums;
}

// Selection Sort 第0个位置最小的坐,第1个位置次小的坐...
public void selectionSort(int[] nums) {
for (int i = 0; i < nums.length - 1; i++) {
int minIdx = i;
for (int j = i; j < nums.length; j++) {
if (nums[j] < nums[minIdx]) {
minIdx = j;
}
}
swap(nums, minIdx, i);
}
return nums;
}

// Insertion Sort 当前位置的值比前一个小,那就换到前面,一直到换不动为止
public void insertionSort(int[] nums) {
for (int i = 1; i < nums.length; i++) {
for (int j = i; j > 0; j--) {
if (nums[j] < nums[j - 1]) {
swap(nums, j, j - 1);
} else {
break;
}
}
}
return nums;
}

// Quick Sort
private void quickSort(int[] nums, int start, int end) {
if (start >= end) {
return;
}
int pivot = start, left = start + 1, right = end;
while (left <= right) {
if (nums[left] > nums[pivot] && nums[right] < nums[pivot]) {
swap(nums, left, right);
left += 1;
right -= 1;
continue;
}
if (nums[left] <= nums[pivot]) {
left += 1;
}
if (nums[right] >= nums[pivot]) {
right -= 1;
}
}
swap(nums, pivot, right);
boolean isLeftShorter = right - start <= end - right ? true : false;
if (isLeftShorter) {
quickSort(nums, start, right - 1);
quickSort(nums, right + 1, end);
} else {
quickSort(nums, right + 1, end);
quickSort(nums, start, right - 1);
}
}

// Merge Sort 给一个范围, 能把这个范围内的数字给sort好. 注意nums和aux往下传递的时候要颠倒位置.
private void mergeSort(int[] nums, int[] aux, int start, int end) {
if (start >= end) {
return;
}
int mid = start + (end - start) / 2;
mergeSort(aux, nums, start, mid);
mergeSort(aux, nums, mid + 1, end);
merge(nums, aux, start, mid, end);
}

private void merge(int[] nums, int[] aux, int left, int middle, int right) {
int ptr = left, ptrOne = left, ptrTwo = middle + 1;
while (ptrOne <= middle && ptrTwo <= right) {
if (aux[ptrOne] <= aux[ptrTwo]) {
nums[ptr++] = aux[ptrOne++];
} else {
nums[ptr++] = aux[ptrTwo++];
}
}
while (ptrOne <= middle) {
nums[ptr++] = aux[ptrOne++];
}
while (ptrTwo <= right) {
nums[ptr++] = aux[ptrTwo++];
}
}
}

Read More

737. Sentence Similarity II

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Solution {
public boolean areSentencesSimilarTwo(String[] sentence1, String[] sentence2, List<List<String>> similarPairs) {
if (sentence1.length != sentence2.length) {
return false;
}
Map<String, Set<String>> wordsSimilarSet = new HashMap<>();
for (List<String> pair : similarPairs) {
wordsSimilarSet.putIfAbsent(pair.get(0), new HashSet<>());
wordsSimilarSet.get(pair.get(0)).add(pair.get(1));
wordsSimilarSet.putIfAbsent(pair.get(1), new HashSet<>());
wordsSimilarSet.get(pair.get(1)).add(pair.get(0));
}
for (int i = 0; i < sentence1.length; i++) {
if (sentence1[i].equals(sentence2[i])) {
continue;
}
if (!wordsSimilarSet.containsKey(sentence1[i]) || !wordsSimilarSet.containsKey(sentence2[i])) {
return false;
}
if (!dfs(wordsSimilarSet, sentence1[i], sentence2[i], new HashSet<>())) {
return false;
}
}
return true;
}

private boolean dfs(Map<String, Set<String>> wordsSimilarSet, String word1, String word2, Set<String> visited) {
if (wordsSimilarSet.get(word1).contains(word2)) {
return true;
}
for (String child : wordsSimilarSet.get(word1)) {
if (visited.add(child) && dfs(wordsSimilarSet, child, word2, visited)) {
return true;
}
}
return false;
}
}

Read More

547. Number of Provinces

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class Solution {
private int[] cityParent;
private int[] rank;

private void initialize() {
for (int i = 1; i < cityParent.length; i++) {
cityParent[i] = i;
rank[i] = 1;
}
}

private int find(int city) {
if (city == cityParent[city]) {
return city;
}
return cityParent[city] = find(cityParent[city]);
}

private void union(int city1, int city2) {
int city1Root = find(city1);
int city2Root = find(city2);
if (city1Root != city2Root) {
if (rank[city1Root] < rank[city2Root]) {
cityParent[city1Root] = city2Root;
} else if (rank[city1Root] > rank[city2Root]) {
cityParent[city2Root] = city1Root;
} else {
cityParent[city2Root] = city1Root;
rank[city1Root] += 1;
}
}
}

public int findCircleNum(int[][] isConnected) {
int numOfCities = isConnected.length;
cityParent = new int[numOfCities + 1];
rank = new int[numOfCities + 1];
initialize();
for (int i = 0; i < isConnected.length; i++) {
for (int j = 0; j < isConnected[0].length; j++) {
if (isConnected[i][j] == 1) {
union(i + 1, j + 1);
}
}
}
Set<Integer> rootCities = new HashSet<>();
for (int i = 1; i <= numOfCities; i++) {
rootCities.add(find(i));
}
return rootCities.size();
}
}

Read More

453. Minimum Moves to Equal Array Elements

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public int minMoves(int[] nums) {
int ans = 0;
int min = Integer.MAX_VALUE;
for (int i = 0; i < nums.length; i++) {
min = Math.min(nums[i], min);
}
for (int i = 0; i < nums.length; i++) {
ans += nums[i] - min;
}
return ans;
}
}

Read More

429. N-ary Tree Level Order Traversal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> ans = new ArrayList<>();
helper(root, ans, 0);
return ans;
}

private void helper(Node node, List<List<Integer>> ans, int level) {
if (node == null) {
return;
}
if (level == ans.size()) {
ans.add(new ArrayList<>());
}
ans.get(level).add(node.val);
for (Node child : node.children) {
helper(child, ans, level + 1);
}
}
}

Read More

317. Shortest Distance from All Buildings

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class Solution {
private int[][] DIRECTIONS = new int[][] { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };

public int shortestDistance(int[][] grid) {
int[][][] gridSumCount = new int[grid.length][grid[0].length][2];
Deque<int[]> buildings = new ArrayDeque<>();
int buildingCount = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (grid[i][j] == 1) {
buildings.offer(new int[] { i, j });
buildingCount += 1;
}
}
}
while (!buildings.isEmpty()) {
int[] currBuilding = buildings.poll();
Deque<int[]> possibleSites = new ArrayDeque<>();
possibleSites.offer(currBuilding);
boolean[][] visited = new boolean[grid.length][grid[0].length];
visited[currBuilding[0]][currBuilding[1]] = true;
int steps = 1;
while (!possibleSites.isEmpty()) {
int size = possibleSites.size();
for (int i = 0; i < size; i++) {
int[] currPos = possibleSites.poll();
for (int[] direction : DIRECTIONS) {
int newRow = currPos[0] + direction[0];
int newCol = currPos[1] + direction[1];
if (!isOutOfBound(grid, newRow, newCol) && grid[newRow][newCol] == 0
&& !visited[newRow][newCol]) {
gridSumCount[newRow][newCol][0] += steps;
gridSumCount[newRow][newCol][1] += 1;
visited[newRow][newCol] = true;
possibleSites.offer(new int[] { newRow, newCol });
}
}
}
steps += 1;
}
}
int ans = Integer.MAX_VALUE;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (grid[i][j] == 0 && gridSumCount[i][j][1] == buildingCount) {
ans = Math.min(ans, gridSumCount[i][j][0]);
}
}
}
return ans == Integer.MAX_VALUE ? -1 : ans;
}

private boolean isOutOfBound(int[][] grid, int row, int col) {
return row < 0 || row >= grid.length || col < 0 || col >= grid[0].length;
}
}

Read More

187. Repeated DNA Sequences

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class Solution {
public List<String> findRepeatedDnaSequences(String s) {
if (s.length() <= 10) {
return new ArrayList<>();
}
int left = 0, right = 0, hash = 0;
// Initialize the winodw
for (right = 0; right < 10; right++) {
int currDigit = getDigit(s.charAt(right));
hash = hash * 10 + currDigit;
}
Map<Integer, Integer> visited = new HashMap<>();
visited.put(hash, 1);
List<String> ans = new ArrayList<>();
int msbOffset = 1000000000;
while (right < s.length()) {
hash = (hash - msbOffset * (getDigit(s.charAt(left)))) * 10 + getDigit(s.charAt(right));
if (visited.containsKey(hash) && visited.get(hash) == 1) {
ans.add(s.substring(left + 1, right + 1));
}
visited.put(hash, visited.getOrDefault(hash, 0) + 1);
left += 1;
right += 1;
}
return ans;
}

private int getDigit(char c) {
int currDigit = 0;
switch (c) {
case 'A':
currDigit = 1;
break;
case 'C':
currDigit = 2;
break;
case 'G':
currDigit = 3;
break;
case 'T':
currDigit = 4;
break;
default:
currDigit = 0;
break;
}
return currDigit;
}
}

Read More

Union Find

Union Find Template (union by rank + path compression). Both techniques are used to optimize find method.
The below implementation is from LC disjoint set tutorial.

Read More

875. Koko Eating Bananas

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public int minEatingSpeed(int[] piles, int h) {
int left = 1, right = piles[0];
for (int i = 1; i < piles.length; i++) {
right = Math.max(right, piles[i]);
}
int ans = right;
while (left <= right) {
int mid = left + (right - left) / 2;
long count = 0;
for (int pile : piles) {
count += pile / mid;
count += pile % mid == 0 ? 0 : 1;
// count += Math.ceil((double) pile / mid);
}
if (count <= h) {
ans = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return ans;
}
}

Read More