Skip to content

Commit 201daf4

Browse files
committed
Improved tasks 3510, 3515
1 parent 0286efd commit 201daf4

File tree

3 files changed

+182
-167
lines changed

3 files changed

+182
-167
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2105,11 +2105,11 @@
21052105
| 3518 |[Smallest Palindromic Rearrangement II](src/main/kotlin/g3501_3600/s3518_smallest_palindromic_rearrangement_ii)| Hard | String, Hash_Table, Math, Counting, Combinatorics | 27 | 100.00
21062106
| 3517 |[Smallest Palindromic Rearrangement I](src/main/kotlin/g3501_3600/s3517_smallest_palindromic_rearrangement_i)| Medium | String, Sorting, Counting_Sort | 49 | 100.00
21072107
| 3516 |[Find Closest Person](src/main/kotlin/g3501_3600/s3516_find_closest_person)| Easy | Math | 1 | 100.00
2108-
| 3515 |[Shortest Path in a Weighted Tree](src/main/kotlin/g3501_3600/s3515_shortest_path_in_a_weighted_tree)| Hard | Array, Depth_First_Search, Tree, Segment_Tree, Binary_Indexed_Tree | 65 | 100.00
2108+
| 3515 |[Shortest Path in a Weighted Tree](src/main/kotlin/g3501_3600/s3515_shortest_path_in_a_weighted_tree)| Hard | Array, Depth_First_Search, Tree, Segment_Tree, Binary_Indexed_Tree | 45 | 100.00
21092109
| 3514 |[Number of Unique XOR Triplets II](src/main/kotlin/g3501_3600/s3514_number_of_unique_xor_triplets_ii)| Medium | Array, Math, Bit_Manipulation, Enumeration | 778 | 100.00
21102110
| 3513 |[Number of Unique XOR Triplets I](src/main/kotlin/g3501_3600/s3513_number_of_unique_xor_triplets_i)| Medium | Array, Math, Bit_Manipulation | 1 | 100.00
21112111
| 3512 |[Minimum Operations to Make Array Sum Divisible by K](src/main/kotlin/g3501_3600/s3512_minimum_operations_to_make_array_sum_divisible_by_k)| Easy | Array, Math | 1 | 100.00
2112-
| 3510 |[Minimum Pair Removal to Sort Array II](src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii)| Hard | Array, Hash_Table, Heap_Priority_Queue, Simulation, Linked_List, Ordered_Set, Doubly_Linked_List | 219 | 100.00
2112+
| 3510 |[Minimum Pair Removal to Sort Array II](src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii)| Hard | Array, Hash_Table, Heap_Priority_Queue, Simulation, Linked_List, Ordered_Set, Doubly_Linked_List | 172 | 100.00
21132113
| 3509 |[Maximum Product of Subsequences With an Alternating Sum Equal to K](src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k)| Hard | Array, Hash_Table, Dynamic_Programming | 99 | 96.30
21142114
| 3508 |[Implement Router](src/main/kotlin/g3501_3600/s3508_implement_router)| Medium | Array, Hash_Table, Binary_Search, Design, Ordered_Set, Queue | 202 | 100.00
21152115
| 3507 |[Minimum Pair Removal to Sort Array I](src/main/kotlin/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i)| Easy | Array, Hash_Table, Heap_Priority_Queue, Simulation, Linked_List, Ordered_Set, Doubly_Linked_List | 2 | 100.00

src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/readme.md

Lines changed: 97 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -45,112 +45,118 @@ The array `nums` is already sorted.
4545
## Solution
4646

4747
```kotlin
48+
import kotlin.math.ceil
49+
import kotlin.math.ln
50+
import kotlin.math.min
51+
import kotlin.math.pow
52+
4853
class Solution {
49-
private class Segment {
50-
private val start: Int
51-
private val end: Int
52-
private var left: Segment? = null
53-
private var right: Segment? = null
54-
private var lIdx: Int = 0
55-
private var lNum: Long = 0
56-
private var rIdx: Int = 0
57-
private var rNum: Long = 0
58-
var ok: Boolean = false
59-
var minSum: Long = 0
60-
var li: Int = 0
61-
var ri: Int = 0
62-
63-
companion object {
64-
fun init(arr: IntArray): Segment {
65-
return Segment(arr, 0, arr.size - 1)
66-
}
54+
fun minimumPairRemoval(nums: IntArray): Int {
55+
if (nums.size == 1) {
56+
return 0
6757
}
68-
69-
constructor(arr: IntArray, s: Int, e: Int) {
70-
start = s
71-
end = e
72-
if (s >= e) {
73-
lIdx = s
74-
rIdx = s
75-
lNum = arr[s].toLong()
76-
rNum = arr[s].toLong()
77-
minSum = Long.MAX_VALUE
78-
ok = true
79-
return
58+
val size = 2.0.pow(ceil(ln(nums.size - 1.0) / ln(2.0))).toInt()
59+
val segment = LongArray(size * 2 - 1)
60+
segment.fill(Long.Companion.MAX_VALUE)
61+
val lefts = IntArray(size * 2 - 1)
62+
val rights = IntArray(size * 2 - 1)
63+
val sums = LongArray(nums.size)
64+
sums.fill(Long.Companion.MAX_VALUE / 2)
65+
val arrIdxToSegIdx: Array<IntArray> = Array(nums.size) { IntArray(0) }
66+
sums[0] = nums[0].toLong()
67+
var count = 0
68+
arrIdxToSegIdx[0] = intArrayOf(-1, size - 1)
69+
for (i in 1..<nums.size) {
70+
if (nums[i] < nums[i - 1]) {
71+
count++
8072
}
81-
val mid = s + ((e - s) shr 1)
82-
left = Segment(arr, s, mid)
83-
right = Segment(arr, mid + 1, e)
84-
merge()
73+
lefts[size + i - 2] = i - 1
74+
rights[size + i - 2] = i
75+
segment[size + i - 2] = nums[i - 1] + nums[i].toLong()
76+
arrIdxToSegIdx[i] = intArrayOf(size + i - 2, size + i - 1)
77+
sums[i] = nums[i].toLong()
8578
}
86-
87-
private fun merge() {
88-
left?.let { left ->
89-
right?.let { right ->
90-
lIdx = left.lIdx
91-
lNum = left.lNum
92-
rIdx = right.rIdx
93-
rNum = right.rNum
94-
ok = left.ok && right.ok && left.rNum <= right.lNum
95-
minSum = left.minSum
96-
li = left.li
97-
ri = left.ri
98-
if (left.rNum + right.lNum < minSum) {
99-
minSum = left.rNum + right.lNum
100-
li = left.rIdx
101-
ri = right.lIdx
102-
}
103-
if (right.minSum < minSum) {
104-
minSum = right.minSum
105-
li = right.li
106-
ri = right.ri
107-
}
108-
}
109-
}
79+
arrIdxToSegIdx[nums.size - 1][1] = -1
80+
for (i in size - 2 downTo 0) {
81+
val l = 2 * i + 1
82+
val r = 2 * i + 2
83+
segment[i] = min(segment[l], segment[r])
11084
}
85+
return getRes(count, segment, lefts, rights, sums, arrIdxToSegIdx)
86+
}
11187

112-
fun update(i: Int, n: Long) {
113-
if (start <= i && end >= i) {
114-
if (start >= end) {
115-
lNum = n
116-
rNum = n
88+
private fun getRes(
89+
count: Int,
90+
segment: LongArray,
91+
lefts: IntArray,
92+
rights: IntArray,
93+
sums: LongArray,
94+
arrIdxToSegIdx: Array<IntArray>,
95+
): Int {
96+
var count = count
97+
var res = 0
98+
while (count > 0) {
99+
var segIdx = 0
100+
while (2 * segIdx + 1 < segment.size) {
101+
val l = 2 * segIdx + 1
102+
val r = 2 * segIdx + 2
103+
segIdx = if (segment[l] <= segment[r]) {
104+
l
117105
} else {
118-
left?.update(i, n)
119-
right?.update(i, n)
120-
merge()
106+
r
121107
}
122108
}
123-
}
124-
125-
fun remove(i: Int): Segment? {
126-
if (start > i || end < i) {
127-
return this
128-
} else if (start >= end) {
129-
return null
109+
val arrIdxL = lefts[segIdx]
110+
val arrIdxR = rights[segIdx]
111+
val numL = sums[arrIdxL]
112+
val numR = sums[arrIdxR]
113+
if (numL > numR) {
114+
count--
130115
}
131-
left = left?.remove(i)
132-
right = right?.remove(i)
133-
if (left == null) {
134-
return right
135-
} else if (right == null) {
136-
return left
116+
sums[arrIdxL] = sums[arrIdxL] + sums[arrIdxR]
117+
val newSum = sums[arrIdxL]
118+
val leftPointer = arrIdxToSegIdx[arrIdxL]
119+
val rightPointer = arrIdxToSegIdx[arrIdxR]
120+
val prvSegIdx = leftPointer[0]
121+
val nextSegIdx = rightPointer[1]
122+
leftPointer[1] = nextSegIdx
123+
if (prvSegIdx != -1) {
124+
val l = lefts[prvSegIdx]
125+
if (sums[l] > numL && sums[l] <= newSum) {
126+
count--
127+
} else if (sums[l] <= numL && sums[l] > newSum) {
128+
count++
129+
}
130+
modify(segment, prvSegIdx, sums[l] + newSum)
131+
}
132+
if (nextSegIdx != -1) {
133+
val r = rights[nextSegIdx]
134+
if (numR > sums[r] && newSum <= sums[r]) {
135+
count--
136+
} else if (numR <= sums[r] && newSum > sums[r]) {
137+
count++
138+
}
139+
modify(segment, nextSegIdx, newSum + sums[r])
140+
lefts[nextSegIdx] = arrIdxL
137141
}
138-
merge()
139-
return this
142+
modify(segment, segIdx, Long.Companion.MAX_VALUE)
143+
res++
140144
}
145+
return res
141146
}
142147

143-
fun minimumPairRemoval(nums: IntArray): Int {
144-
var root = Segment.init(nums)
145-
var res = 0
146-
while (!root.ok) {
147-
val l = root.li
148-
val r = root.ri
149-
root.update(l, root.minSum)
150-
root = root.remove(r) ?: break
151-
res++
148+
private fun modify(segment: LongArray, idx: Int, num: Long) {
149+
var idx = idx
150+
if (segment[idx] == num) {
151+
return
152+
}
153+
segment[idx] = num
154+
while (idx != 0) {
155+
idx = (idx - 1) / 2
156+
val l = 2 * idx + 1
157+
val r = 2 * idx + 2
158+
segment[idx] = min(segment[l], segment[r])
152159
}
153-
return res
154160
}
155161
}
156162
```

0 commit comments

Comments
 (0)