Skip to content

Commit ba8eb19

Browse files
authored
Added tasks 1977, 1979, 1980, 1981, 1982.
1 parent 1366e29 commit ba8eb19

File tree

15 files changed

+746
-0
lines changed

15 files changed

+746
-0
lines changed
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
package g1901_2000.s1977_number_of_ways_to_separate_numbers;
2+
3+
// #Hard #String #Dynamic_Programming #Suffix_Array
4+
// #2022_05_21_Time_150_ms_(94.52%)_Space_101.1_MB_(90.41%)
5+
6+
import java.util.Arrays;
7+
8+
public class Solution {
9+
private static final int P = 1_000_000_007;
10+
11+
public int numberOfCombinations(String num) {
12+
int n = num.length();
13+
if (num.charAt(0) == '0') {
14+
return 0;
15+
}
16+
if (n == 1) {
17+
return 1;
18+
}
19+
20+
int[] arr = new int[n];
21+
for (int i = 0; i < n; i++) {
22+
arr[i] = num.charAt(i) - '0' + 1;
23+
}
24+
25+
int[] suffixArray = new SuffixArrayTools().buildSuffixArray(arr);
26+
int[] invSuffixArray = new SuffixArrayTools().inverseSuffixArray(suffixArray);
27+
int[] lcp =
28+
SuffixArrayTools.buildLongestCommonPrefixArray(arr, suffixArray, invSuffixArray);
29+
int[][] lcpMat = new int[n - 1][n - 1];
30+
for (int i = 0; i < n - 1; i++) {
31+
lcpMat[i][i] = lcp[i];
32+
}
33+
for (int i = 0; i < n - 2; i++) {
34+
for (int j = i + 1; j < n - 1; j++) {
35+
lcpMat[i][j] = Math.min(lcpMat[i][j - 1], lcpMat[j][j]);
36+
}
37+
}
38+
39+
long[] prev = new long[n + 1];
40+
long[] next = new long[n + 1];
41+
long[] tmp;
42+
prev[0] = 1;
43+
next[0] = 1;
44+
45+
for (int d = 1; d <= n; d++) {
46+
System.arraycopy(prev, 1, next, 1, n);
47+
for (int j1 = 0, i1 = j1 - d, j2 = j1 + d; j2 <= n; j1++, j2++, i1++) {
48+
if (arr[j1] != 1) {
49+
if (i1 < 0 || arr[i1] != 1 && ok(i1, j1, d, invSuffixArray, lcpMat)) {
50+
next[j2] += next[j1];
51+
} else {
52+
next[j2] += prev[j1];
53+
}
54+
if (next[j2] >= P) {
55+
next[j2] -= P;
56+
}
57+
}
58+
}
59+
tmp = prev;
60+
prev = next;
61+
next = tmp;
62+
}
63+
return (int) prev[n];
64+
}
65+
66+
private boolean ok(int start1, int start2, int len, int[] inv, int[][] lcpMat) {
67+
return inv[start1] < inv[start2] || lcpMat[inv[start2]][inv[start1] - 1] >= len;
68+
}
69+
70+
static class SuffixArrayTools {
71+
int[] buildSuffixArray(int[] arr) {
72+
int n = arr.length;
73+
int[] s = Arrays.copyOf(arr, n + 3);
74+
int[] sa = new int[n];
75+
suffixArray(s, sa, n, 10);
76+
return sa;
77+
}
78+
79+
private int[] inverseSuffixArray(int[] suffixArray) {
80+
int n = suffixArray.length;
81+
int[] ans = new int[n];
82+
for (int i = 0; i < n; i++) {
83+
ans[suffixArray[i]] = i;
84+
}
85+
return ans;
86+
}
87+
88+
static int[] buildLongestCommonPrefixArray(
89+
int[] arr, int[] suffixArray, int[] invSuffixArray) {
90+
int n = arr.length;
91+
int[] lcp = new int[n - 1];
92+
int k = 0;
93+
for (int i = 0; i < n; i++) {
94+
if (k > 0) {
95+
k--;
96+
}
97+
if (invSuffixArray[i] == n - 1) {
98+
k = 0;
99+
} else {
100+
int j = suffixArray[invSuffixArray[i] + 1];
101+
while (i + k < n && j + k < n && arr[i + k] == arr[j + k]) {
102+
k++;
103+
}
104+
lcp[invSuffixArray[i]] = k;
105+
}
106+
}
107+
return lcp;
108+
}
109+
110+
private boolean leq(int a1, int a2, int b1, int b2) {
111+
return (a1 < b1 || (a1 == b1 && a2 <= b2));
112+
}
113+
114+
private boolean leq(int a1, int a2, int a3, int b1, int b2, int b3) {
115+
return (a1 < b1 || (a1 == b1 && leq(a2, a3, b2, b3)));
116+
}
117+
118+
private void suffixArray(int[] s, int[] sa, int n, int k) {
119+
int n0 = (n + 2) / 3;
120+
int n1 = (n + 1) / 3;
121+
int n2 = n / 3;
122+
int n02 = n0 + n2;
123+
int[] s12 = new int[n02 + 3];
124+
int[] sa12 = new int[n02 + 3];
125+
int[] s0 = new int[n0];
126+
int[] sa0 = new int[n0];
127+
int i = 0;
128+
int j = 0;
129+
while (i < n + (n0 - n1)) {
130+
if (i % 3 != 0) {
131+
s12[j++] = i;
132+
}
133+
i++;
134+
}
135+
136+
radixPass(s12, sa12, s, 2, n02, k);
137+
radixPass(sa12, s12, s, 1, n02, k);
138+
radixPass(s12, sa12, s, 0, n02, k);
139+
140+
int name = 0;
141+
int c0 = -1;
142+
int c1 = -1;
143+
int c2 = -1;
144+
for (i = 0; i < n02; i++) {
145+
if (s[sa12[i]] != c0 || s[sa12[i] + 1] != c1 || s[sa12[i] + 2] != c2) {
146+
name++;
147+
c0 = s[sa12[i]];
148+
c1 = s[sa12[i] + 1];
149+
c2 = s[sa12[i] + 2];
150+
}
151+
if (sa12[i] % 3 == 1) {
152+
s12[sa12[i] / 3] = name;
153+
} else {
154+
s12[sa12[i] / 3 + n0] = name;
155+
}
156+
}
157+
158+
if (name < n02) {
159+
suffixArray(s12, sa12, n02, name);
160+
for (i = 0; i < n02; i++) {
161+
s12[sa12[i]] = i + 1;
162+
}
163+
} else {
164+
for (i = 0; i < n02; i++) {
165+
sa12[s12[i] - 1] = i;
166+
}
167+
}
168+
i = 0;
169+
j = 0;
170+
while (i < n02) {
171+
if (sa12[i] < n0) {
172+
s0[j++] = 3 * sa12[i];
173+
}
174+
i++;
175+
}
176+
radixPass(s0, sa0, s, 0, n0, k);
177+
int p = 0;
178+
int t = n0 - n1;
179+
int i1 = 0;
180+
while (i1 < n) {
181+
i = getI(sa12, n0, t);
182+
j = sa0[p];
183+
if (sa12[t] < n0
184+
? leq(s[i], s12[sa12[t] + n0], s[j], s12[j / 3])
185+
: leq(
186+
s[i],
187+
s[i + 1],
188+
s12[sa12[t] - n0 + 1],
189+
s[j],
190+
s[j + 1],
191+
s12[j / 3 + n0])) {
192+
sa[i1] = i;
193+
t++;
194+
if (t == n02) {
195+
i1++;
196+
while (p < n0) {
197+
sa[i1] = sa0[p];
198+
p++;
199+
i1++;
200+
}
201+
}
202+
} else {
203+
sa[i1] = j;
204+
p++;
205+
if (p == n0) {
206+
i1++;
207+
while (t < n02) {
208+
sa[i1] = getI(sa12, n0, t);
209+
t++;
210+
i1++;
211+
}
212+
}
213+
}
214+
i1++;
215+
}
216+
}
217+
218+
private int getI(int[] sa12, int n0, int t) {
219+
return sa12[t] < n0 ? sa12[t] * 3 + 1 : (sa12[t] - n0) * 3 + 2;
220+
}
221+
222+
private void radixPass(int[] a, int[] b, int[] r, int shift, int n, int k) {
223+
int[] c = new int[k + 1];
224+
for (int i = 0; i < n; i++) {
225+
c[r[a[i] + shift]]++;
226+
}
227+
int i = 0;
228+
int sum = 0;
229+
while (i <= k) {
230+
int t = c[i];
231+
c[i] = sum;
232+
sum += t;
233+
i++;
234+
}
235+
for (i = 0; i < n; i++) {
236+
b[c[r[a[i] + shift]]++] = a[i];
237+
}
238+
}
239+
}
240+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
1977\. Number of Ways to Separate Numbers
2+
3+
Hard
4+
5+
You wrote down many **positive** integers in a string called `num`. However, you realized that you forgot to add commas to seperate the different numbers. You remember that the list of integers was **non-decreasing** and that **no** integer had leading zeros.
6+
7+
Return _the **number of possible lists of integers** that you could have written down to get the string_ `num`. Since the answer may be large, return it **modulo** <code>10<sup>9</sup> + 7</code>.
8+
9+
**Example 1:**
10+
11+
**Input:** num = "327"
12+
13+
**Output:** 2
14+
15+
**Explanation:** You could have written down the numbers: 3, 27 327
16+
17+
**Example 2:**
18+
19+
**Input:** num = "094"
20+
21+
**Output:** 0
22+
23+
**Explanation:** No numbers can have leading zeros and all numbers must be positive.
24+
25+
**Example 3:**
26+
27+
**Input:** num = "0"
28+
29+
**Output:** 0
30+
31+
**Explanation:** No numbers can have leading zeros and all numbers must be positive.
32+
33+
**Constraints:**
34+
35+
* `1 <= num.length <= 3500`
36+
* `num` consists of digits `'0'` through `'9'`.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package g1901_2000.s1979_find_greatest_common_divisor_of_array;
2+
3+
// #Easy #Array #Math #Number_Theory #2022_05_21_Time_5_ms_(10.46%)_Space_43.6_MB_(61.12%)
4+
5+
import java.util.Arrays;
6+
7+
public class Solution {
8+
public int findGCD(int[] nums) {
9+
Arrays.sort(nums);
10+
return getGcd(nums[0], nums[nums.length - 1]);
11+
}
12+
13+
private int getGcd(int a, int b) {
14+
return b == 0 ? a : getGcd(b, a % b);
15+
}
16+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
1979\. Find Greatest Common Divisor of Array
2+
3+
Easy
4+
5+
Given an integer array `nums`, return _the **greatest common divisor** of the smallest number and largest number in_ `nums`.
6+
7+
The **greatest common divisor** of two numbers is the largest positive integer that evenly divides both numbers.
8+
9+
**Example 1:**
10+
11+
**Input:** nums = [2,5,6,9,10]
12+
13+
**Output:** 2
14+
15+
**Explanation:**
16+
17+
The smallest number in nums is 2.
18+
19+
The largest number in nums is 10.
20+
21+
The greatest common divisor of 2 and 10 is 2.
22+
23+
**Example 2:**
24+
25+
**Input:** nums = [7,5,6,8,3]
26+
27+
**Output:** 1
28+
29+
**Explanation:**
30+
31+
The smallest number in nums is 3.
32+
33+
The largest number in nums is 8.
34+
35+
The greatest common divisor of 3 and 8 is 1.
36+
37+
**Example 3:**
38+
39+
**Input:** nums = [3,3]
40+
41+
**Output:** 3
42+
43+
**Explanation:**
44+
45+
The smallest number in nums is 3.
46+
47+
The largest number in nums is 3.
48+
49+
The greatest common divisor of 3 and 3 is 3.
50+
51+
**Constraints:**
52+
53+
* `2 <= nums.length <= 1000`
54+
* `1 <= nums[i] <= 1000`
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package g1901_2000.s1980_find_unique_binary_string;
2+
3+
// #Medium #Array #String #Backtracking #2022_05_21_Time_7_ms_(31.88%)_Space_42_MB_(59.01%)
4+
5+
import java.util.Arrays;
6+
import java.util.HashSet;
7+
import java.util.Set;
8+
9+
public class Solution {
10+
public String findDifferentBinaryString(String[] nums) {
11+
Set<String> set = new HashSet<>(Arrays.asList(nums));
12+
int len = nums[0].length();
13+
StringBuilder sb = new StringBuilder();
14+
int i = 0;
15+
while (i < len) {
16+
sb.append(1);
17+
i++;
18+
}
19+
int max = Integer.parseInt(sb.toString(), 2);
20+
for (int num = 0; num <= max; num++) {
21+
String binary = Integer.toBinaryString(num);
22+
if (binary.length() < len) {
23+
sb.setLength(0);
24+
sb.append(binary);
25+
while (sb.length() < len) {
26+
sb.insert(0, "0");
27+
}
28+
binary = sb.toString();
29+
}
30+
if (!set.contains(binary)) {
31+
return binary;
32+
}
33+
}
34+
return null;
35+
}
36+
}

0 commit comments

Comments
 (0)