Divide and Conquer
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
public ListNode mergeKLists(ListNode[] lists) {
int k = lists.length;
if (k == 0) {
return null;
}
int interval = 1;
while (interval < k) {
for (int i = 0; i + interval < k; i += interval * 2) {
lists[i] = mergeTwoLists(lists[i], lists[i + interval]);
}
interval *= 2;
}
return lists[0];
}
private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode head = new ListNode(0), curr = head;
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
curr.next = l1;
l1 = l1.next;
} else {
curr.next = l2;
l2 = l2.next;
}
curr = curr.next;
}
curr.next = l1 == null ? l2 : l1;
return head.next;
}
Another solution is to add all nodes to a min heap.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public int nthSuperUglyNumber(int n, int[] primes) {
long[] ugly = new long[n];
ugly[0] = 1;
int m = primes.length;
int[] indices = new int[m];
for (int i = 1; i < n; i++) {
ugly[i] = Integer.MAX_VALUE;
for (int j = 0; j < m; j++) {
// moves the pointer of the last "base" ugly number forward
if (ugly[indices[j]] * primes[j] == ugly[i - 1]) {
indices[j]++;
}
// finds and assigns the min value to the current ugly number
ugly[i] = Math.min(ugly[i], ugly[indices[j]] * primes[j]);
}
}
return (int)ugly[n - 1];
}
To find the minimum of ugly[indices[j]] * primes[j]
, we can also use Priority Queue for less time complexity.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public String longestNiceSubstring(String s) {
if (s.length() < 2) {
return "";
}
Set<Character> set = new HashSet<>();
for (char c: s.toCharArray()) {
set.add(c);
}
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (set.contains(Character.toUpperCase(c)) && set.contains(Character.toLowerCase(c))) {
continue;
}
String s1 = longestNiceSubstring(s.substring(0, i));
String s2 = longestNiceSubstring(s.substring(i + 1));
return s1.length() >= s2.length() ? s1 : s2;
}
return s;
}
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
public int[] beautifulArray(int n) {
List<Integer> list = new ArrayList<>();
list.add(1);
// properties:
// if A is a beautiful array, then
// - A + c is a beautiful array
// - c * A is a beautiful array
// - deletion: A is still a beautiful array after deleting some elements in it
while (list.size() < n) {
List<Integer> tmp = new ArrayList<>();
// divide and conquer
// divides the numbers into two parts: odd + even, because odd + even = odd != 2 * x
for (int i : list) {
if (i * 2 - 1 <= n) {
tmp.add(i * 2 - 1);
}
}
for (int i : list) {
if (i * 2 <= n) {
tmp.add(i * 2);
}
}
list = tmp;
}
return list.stream().mapToInt(i -> i).toArray();
}
1
2
3
4
5
6
7
n = 10
[1]
[1,2]
[1,3,2,4]
[1,5,3,7,2,6,4,8]
[1,9,5,3,7,2,10,6,4,8]
It’s easy to come up with a recursive version.
Another solution is bit reverse (br) sort. It can be proven that if i + k = j * 2
, then br(j)
is either less than or greater than both br(i)
and br(k)
. Thus the algorithm is to sort the numbers based on their bit reverse. Credit to @Aging.
This post is licensed under CC BY 4.0 by the author.