Skip to content

Commit 07faa29

Browse files
Added LC solutions for 351 and 1573
1 parent d3c9afa commit 07faa29

5 files changed

+191
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ Happy to accept any contributions to this in any langugage.
6060
25. [Leet Code 1647 - Minimum Deletions to Make Character Frequency Unique](https://leetcode.com/problems/minimum-deletions-to-make-character-frequencies-unique/) | [Solution](level_medium/LeetCode_1647_Min_Deletions_For_Unique_Freq.ts)
6161
26. [Microsoft OA - Max Sum of Numbers with Equal Sum Digits](https://leetcode.com/discuss/interview-question/915683/) | [Solution](./level_medium/MaxSumOfNumbersWithEqualSumOfDigit.ts)
6262
27. [Microsoft OA - Min Moves to Make String without 3 Identical Chars](https://molchevskyi.medium.com/microsoft-interview-tasks-min-moves-to-make-string-without-3-identical-consecutive-letters-abe61ed51a10) | [Solution](./level_medium/MinMovesToMakeStringWithout3IdenticalChars.ts)
63+
28. [Android Unlock Patterns](https://leetcode.com/problems/android-unlock-patterns/) | [Solution 1](./level_medium/LeetCode_351_Android_Unlock.ts) | [Solution 2](/level_medium/LeetCode_351_Android_Unlock_1.ts)
64+
29. [Leet Code 1573 - Number of Ways to Split a String](https://leetcode.com/problems/number-of-ways-to-split-a-string/) | [Solution 1](./level_medium/LeetCode_1573_Number_Of_Ways_To_Split_String_1.ts) | [Solution](./level_medium/LeetCode_1573_Number_Of_Ways_To_Split_String.ts)
6365

6466

6567
## Hard
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
function numWays(s: string): number {
2+
let ways = 0;
3+
for (let pivot1 = 1; pivot1 <= s.length - 2; pivot1++) {
4+
for (let pivot2 = pivot1 + 1; pivot2 <= s.length - 1; pivot2++) {
5+
const bounds1 = [0, pivot1 - 1]
6+
const bounds2 = [pivot1, pivot2 - 1]
7+
const bounds3 = [pivot2, s.length - 1]
8+
if (haveEqualOnes(s, bounds1, bounds2, bounds3)) ways++
9+
}
10+
}
11+
12+
return ways;
13+
};
14+
15+
function haveEqualOnes(s: string, str1: number[], str2: number[], str3: number[]) {
16+
const countStr1 = countOnes(s, str1)
17+
const countStr2 = countOnes(s, str2)
18+
const countStr3 = countOnes(s, str3)
19+
return countStr1 === countStr2 && countStr2 === countStr3
20+
}
21+
22+
function countOnes(s: string, bounds: number[]) {
23+
let count = 0;
24+
for (let idx = bounds[0]; idx <= bounds[1]; idx++) {
25+
if (s[idx] === '1') count++
26+
}
27+
return count
28+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Leet Code 1573
3+
*
4+
* Solution is essentially a combination problem. The string can be divied into 3 sections with the help of 2 pointers/cuts.
5+
* Each cut can only be created such that the number of 1s are equal, so essentially at a min requiring the needed 1s, while
6+
* at maximum requiring the needed 1s. This creates a combinatory choice of choosing the cut point. For each possible
7+
* cut point in 1st, we can choose a cut point in 2nd.
8+
*
9+
* Time: O(n) since the scan is required only linearly.
10+
* Space: O(1) since no other space is needed.
11+
*
12+
* @param s
13+
*/
14+
function numWays(s: string): number {
15+
const onesCount = countOnes(s);
16+
const mod = 10 ** 9 + 7;
17+
18+
// If the equal partition cannot be made.
19+
if (onesCount % 3 !== 0) return 0;
20+
21+
// If the counts are 0, we have to make combinations for the central array, assuming 0 and 0 at ends.
22+
// So, we have 1 + 2 + 3 + .............. + (n-1) + (n-2), leading the sum range.
23+
if (onesCount === 0) {
24+
return ((s.length - 2) * (s.length - 1) / 2) % mod;
25+
}
26+
27+
// Else, find all possible split positions for split 1 and split 2.
28+
let ones = 0, possStr1 = 0, possStr2 = 0, curr = 0, maxOnes = onesCount/3;
29+
for (let idx = 0; idx < s.length; idx++) {
30+
ones += s[idx] === '1' ? 1 : 0;
31+
if (ones === maxOnes) possStr1++;
32+
else if (ones === 2*maxOnes) possStr2++;
33+
}
34+
35+
return possStr1 * possStr2 % mod;
36+
};
37+
38+
function countOnes(s: string): number {
39+
let total = 0;
40+
for (let idx = 0; idx < s.length; idx++) {
41+
if (s[idx] === '1') total++;
42+
}
43+
return total;
44+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* Leet Code 351
3+
*
4+
* This is a backtracking problem, since all the possible permutations of elements needs to be figured out. However,
5+
* each solution space is bound by few constraints which do not allow the solution to succeed. This is where we backtrack
6+
* the solution space.
7+
*
8+
* Time: O(n!) where n is at max 9, since all the possible permutations of that length is required.
9+
* Space: O(n) since that is the max stack size.
10+
*
11+
* @param m
12+
* @param n
13+
*/
14+
function numberOfPatterns(m: number, n: number): number {
15+
const result: {total: number} = {total: 0};
16+
const used: boolean[] = Array(10).fill(false)
17+
for (let stIdx = 1; stIdx <= 9; stIdx++) {
18+
used[stIdx] = true
19+
findNumberOfPatterns(m, n, stIdx, 1, used, result)
20+
used[stIdx] = false
21+
}
22+
return result.total;
23+
};
24+
25+
function findNumberOfPatterns(m: number, n: number, last: number, size: number, used: boolean[], result: {total: number}) {
26+
27+
// If we have created a length in the target range, add to result.
28+
if (size >= m && size <= n) result.total++
29+
30+
// Terminating the branch if the total length exceeds.
31+
if (size >= n) return
32+
33+
for (let next = 1; next <= 9; next++) {
34+
// if the next index is not used already and a valid move
35+
if (!used[next] && isValid(last, next, used)) {
36+
used[next] = true
37+
findNumberOfPatterns(m, n, next, size + 1, used, result)
38+
used[next] = false
39+
}
40+
}
41+
}
42+
43+
const JUMP_TABLE: number[][] = Array.from({length: 10}, () => Array(10))
44+
JUMP_TABLE[1][3] = JUMP_TABLE[3][1] = 2
45+
JUMP_TABLE[4][6] = JUMP_TABLE[6][4] = 5
46+
JUMP_TABLE[7][9] = JUMP_TABLE[9][7] = 8
47+
JUMP_TABLE[1][7] = JUMP_TABLE[7][1] = 4
48+
JUMP_TABLE[2][8] = JUMP_TABLE[8][2] = 5
49+
JUMP_TABLE[3][9] = JUMP_TABLE[9][3] = 6
50+
JUMP_TABLE[1][9] = JUMP_TABLE[9][1] = JUMP_TABLE[7][3] = JUMP_TABLE[3][7] = 5
51+
52+
function isValid(last: number, next: number, used: boolean[]) {
53+
const jump = JUMP_TABLE[next][last]
54+
return jump === undefined || used[jump] === true
55+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* Leet Code 351
3+
*
4+
* This is a backtracking problem, since all the possible permutations of elements needs to be figured out. However,
5+
* each solution space is bound by few constraints which do not allow the solution to succeed. This is where we backtrack
6+
* the solution space.
7+
*
8+
* Optimization over the existing backtracking solution is that we are not computing the result for each position. Rather,
9+
* the solution is only calculated for few positions and multiplied for symmetry.
10+
*
11+
* Time: O(n!) where n is at max 9, since all the possible permutations of that length is required.
12+
* Space: O(n) since that is the max stack size.
13+
*
14+
* @param m
15+
* @param n
16+
*/
17+
function numberOfPatterns(m: number, n: number): number {
18+
let total = 0
19+
const used: boolean[] = Array(10).fill(false)
20+
total += 4 * findNumberOfPatterns(m, n, 1, 1, used)
21+
total += 4 * findNumberOfPatterns(m, n, 2, 1, used)
22+
total += findNumberOfPatterns(m, n, 5, 1, used)
23+
return total;
24+
};
25+
26+
function findNumberOfPatterns(m: number, n: number, last: number, size: number, used: boolean[]) {
27+
28+
used[last] = true
29+
let total = 0;
30+
31+
// If we have created a length in the target range, add to result.
32+
if (size >= m && size <= n) total++
33+
34+
// Terminating the branch if the total length exceeds.
35+
if (size >= n) return total
36+
37+
for (let next = 1; next <= 9; next++) {
38+
// if the next index is not used already and a valid move
39+
if (!used[next] && isValid(last, next, used)) {
40+
used[next] = true
41+
total += findNumberOfPatterns(m, n, next, size + 1, used)
42+
used[next] = false
43+
}
44+
}
45+
46+
used[last] = false
47+
return total
48+
}
49+
50+
const JUMP_TABLE: number[][] = Array.from({length: 10}, () => Array(10))
51+
JUMP_TABLE[1][3] = JUMP_TABLE[3][1] = 2
52+
JUMP_TABLE[4][6] = JUMP_TABLE[6][4] = 5
53+
JUMP_TABLE[7][9] = JUMP_TABLE[9][7] = 8
54+
JUMP_TABLE[1][7] = JUMP_TABLE[7][1] = 4
55+
JUMP_TABLE[2][8] = JUMP_TABLE[8][2] = 5
56+
JUMP_TABLE[3][9] = JUMP_TABLE[9][3] = 6
57+
JUMP_TABLE[1][9] = JUMP_TABLE[9][1] = JUMP_TABLE[7][3] = JUMP_TABLE[3][7] = 5
58+
59+
function isValid(last: number, next: number, used: boolean[]) {
60+
const jump = JUMP_TABLE[next][last]
61+
return jump === undefined || used[jump] === true
62+
}

0 commit comments

Comments
 (0)