Skip to content

Commit 4912d12

Browse files
committed
Improved task 3470
1 parent 13dad5e commit 4912d12

File tree

1 file changed

+53
-98
lines changed
  • src/main/kotlin/g3401_3500/s3470_permutations_iv

1 file changed

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

33
// #Hard #Array #Math #Enumeration #Combinatorics
4-
// #2025_03_06_Time_21_ms_(25.81%)_Space_47.38_MB_(6.45%)
4+
// #2025_03_06_Time_3_ms_(100.00%)_Space_46.15_MB_(6.45%)
55

66
class Solution {
7-
private fun helper(a: Int, b: Int): Long {
8-
var res: Long = 1
9-
for (i in 0..<b) {
10-
res *= (a - i).toLong()
11-
if (res > INF) {
12-
return INF
7+
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]
1315
}
1416
}
15-
return res
16-
}
17-
18-
private fun solve(odd: Int, even: Int, r: Int, req: Int): Long {
19-
if (r == 0) {
20-
return 1
21-
}
22-
val nOdd: Int
23-
val nEven: Int
24-
if (req == 1) {
25-
nOdd = (r + 1) / 2
26-
nEven = r / 2
27-
} else {
28-
nEven = (r + 1) / 2
29-
nOdd = r / 2
30-
}
31-
if (odd < nOdd || even < nEven) {
32-
return 0
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)
3326
}
34-
val oddWays = helper(odd, nOdd)
35-
val evenWays = helper(even, nEven)
36-
var total = oddWays
37-
if (evenWays == 0L || total > INF / evenWays) {
38-
total = INF
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+
}
3936
} else {
40-
total *= evenWays
41-
}
42-
return total
43-
}
44-
45-
fun permute(n: Int, k: Long): IntArray {
46-
var k = k
47-
val ans: MutableList<Int> = ArrayList<Int>()
48-
var first = false
49-
val used = BooleanArray(n + 1)
50-
var odd = (n + 1) / 2
51-
var even = n / 2
52-
var last = -1
53-
for (i in 1..n) {
54-
if (!used[i]) {
55-
var odd2 = odd
56-
var even2 = even
57-
val cp = i and 1
58-
val next = (if (cp == 1) 0 else 1)
59-
if (cp == 1) {
60-
odd2--
61-
} else {
62-
even2--
63-
}
64-
val r = n - 1
65-
val cnt = solve(odd2, even2, r, next)
66-
if (k > cnt) {
67-
k -= cnt
68-
} else {
69-
ans.add(i)
70-
used[i] = true
71-
odd = odd2
72-
even = even2
73-
last = cp
74-
first = true
75-
break
76-
}
37+
val first = firstCycle * 2 - 1
38+
if (first > n) {
39+
return intArrayOf()
7740
}
41+
result[index++] = first
42+
used[first] = true
7843
}
79-
if (!first) {
80-
return IntArray(0)
81-
}
82-
for (z in 1..<n) {
83-
for (j in 1..n) {
84-
if (!used[j] && ((j and 1) != last)) {
85-
var odd2 = odd
86-
var even2 = even
87-
val cp = j and 1
88-
if (cp == 1) {
89-
odd2--
90-
} else {
91-
even2--
92-
}
93-
val r = n - (z + 1)
94-
val next = (if (cp == 1) 0 else 1)
95-
val cnt2 = solve(odd2, even2, r, next)
96-
if (k > cnt2) {
97-
k -= cnt2
98-
} else {
99-
ans.add(j)
100-
used[j] = true
101-
odd = odd2
102-
even = even2
103-
last = cp
104-
break
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
10552
}
10653
}
10754
}
55+
return -1
10856
}
109-
return ans.stream().mapToInt { i: Int? -> i!! }.toArray()
110-
}
111-
112-
companion object {
113-
private const val INF = 1000000000000000000L
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
64+
}
65+
result[index++] = findNum(odd, 1)
66+
odd = 3 - odd
67+
result[index] = findNum(odd, 1)
68+
return result
11469
}
11570
}

0 commit comments

Comments
 (0)