Skip to content

Commit 79fbd9d

Browse files
committed
Improved task 3470
1 parent 4912d12 commit 79fbd9d

File tree

1 file changed

+58
-55
lines changed
  • src/main/kotlin/g3401_3500/s3470_permutations_iv

1 file changed

+58
-55
lines changed
Lines changed: 58 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,73 @@
11
package g3401_3500.s3470_permutations_iv
22

33
// #Hard #Array #Math #Enumeration #Combinatorics
4-
// #2025_03_06_Time_3_ms_(100.00%)_Space_46.15_MB_(6.45%)
4+
// #2025_03_06_Time_4_ms_(96.77%)_Space_45.40_MB_(9.68%)
55

66
class Solution {
7+
private val maxFac = 100_000_000L
8+
79
fun permute(n: Int, k: Long): IntArray {
8-
val perm = LongArray(n + 1)
9-
perm[1] = 1L
10-
for (i in 2..n) {
11-
if (perm[i - 1] > 10_000_000_000_000_000) {
12-
perm[i] = perm[i - 1]
13-
} else {
14-
perm[i] = ((i + 2) / 2) * perm[i - 1]
15-
}
10+
var res = IntArray(n)
11+
var k = k - 1
12+
var i = 0
13+
val sqrtK = sqrt(k.toDouble()).toLong()
14+
val fac = LongArray(n / 2 + 1)
15+
fac[0] = 1
16+
for (i in 1..n / 2) {
17+
fac[i] = fac[i - 1] * i
18+
if (fac[i] >= maxFac) { fac[i] = maxFac }
1619
}
17-
val used = BooleanArray(n + 1)
18-
val result = IntArray(n)
19-
var index = 0
20-
// Deal with the edge cases first
21-
if (n < 3) {
22-
if (k > n) return intArrayOf()
23-
if (k == 2L) return intArrayOf(2, 1)
24-
if (n == 1) return intArrayOf(1)
25-
return intArrayOf(1, 2)
26-
}
27-
val firstCycle = (((k.toLong() - 1L) / perm[n - 2]).toInt()) + 1
28-
var odd = 2
29-
if (n % 2 == 0) {
30-
if (firstCycle > n) return intArrayOf()
31-
result[index++] = firstCycle
32-
used[firstCycle] = true
33-
if (firstCycle % 2 == 0) {
34-
odd = 1
35-
}
36-
} else {
37-
val first = firstCycle * 2 - 1
38-
if (first > n) {
39-
return intArrayOf()
20+
var evenNum = n / 2
21+
var oddNum = n - evenNum
22+
var evens = mutableListOf<Int>()
23+
var odds = mutableListOf<Int>()
24+
for (i in 1..n) {
25+
if (i % 2 == 0) {
26+
evens.add(i)
27+
} else {
28+
odds.add(i)
4029
}
41-
result[index++] = first
42-
used[first] = true
4330
}
44-
var rem = ((k - 1L) % perm[n - 2]) + 1L
45-
fun findNum(start: Int, nth: Int): Int {
46-
var toFind = nth
47-
for (i in start..n step 2) {
48-
if (used[i] == false) {
49-
toFind--
50-
if (toFind == 0) {
51-
return i
31+
for (i in 0..<n) {
32+
if (i == 0) {
33+
if (n % 2 == 0) {
34+
val trailCombs = fac[evenNum] * fac[evenNum - 1]
35+
val leadIdx = (k / trailCombs).toInt()
36+
if (leadIdx + 1 > n) return IntArray(0)
37+
res[i] = leadIdx + 1
38+
if ((leadIdx + 1) % 2 == 0) {
39+
evens.remove(leadIdx + 1)
40+
} else {
41+
odds.remove(leadIdx + 1)
5242
}
43+
k = k % trailCombs
44+
} else {
45+
val trailCombs = fac[oddNum - 1] * fac[evenNum]
46+
val leadIdx = (k / trailCombs).toInt()
47+
if (leadIdx >= odds.size) return IntArray(0)
48+
val num = odds.removeAt(leadIdx)
49+
res[i] = num
50+
k = k % trailCombs
51+
}
52+
} else {
53+
if (res[i - 1] % 2 == 0) {
54+
val trailCombs = fac[evenNum] * fac[oddNum - 1]
55+
val leadIdx = (k / trailCombs).toInt()
56+
val num = odds.removeAt(leadIdx)
57+
res[i] = num
58+
k = k % trailCombs
59+
} else {
60+
val trailCombs = fac[evenNum - 1] * fac[oddNum ]
61+
val leadIdx = (k / trailCombs).toInt()
62+
val num = evens.removeAt(leadIdx)
63+
res[i] = num
64+
k = k % trailCombs
5365
}
5466
}
55-
return -1
56-
}
57-
for (i in n - 3 downTo 1) {
58-
val nextNum = ((rem - 1) / perm[i]).toInt()
59-
val nextDigit = findNum(odd, nextNum + 1)
60-
result[index++] = nextDigit
61-
used[nextDigit] = true
62-
rem = ((rem - 1L) % perm[i]) + 1L
63-
odd = 3 - odd
67+
if (res[i] % 2 == 0) {
68+
evenNum--
69+
} else { oddNum-- }
6470
}
65-
result[index++] = findNum(odd, 1)
66-
odd = 3 - odd
67-
result[index] = findNum(odd, 1)
68-
return result
71+
return res
6972
}
7073
}

0 commit comments

Comments
 (0)