Skip to content

Commit acfe55f

Browse files
committed
Add: Add 2025/1/25
1 parent d517778 commit acfe55f

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# 2948. Make Lexicographically Smallest Array by Swapping Elements
2+
3+
You are given a 0-indexed array of positive integers `nums` and a positive integer `limit`.
4+
5+
In one operation, you can choose any two indices `i` and `j` and swap `nums[i]` and `nums[j]`
6+
if `|nums[i] - nums[j]| <= limit`.
7+
8+
Return the lexicographically smallest array that can be obtained by performing the operation any number of times.
9+
10+
An array `a` is lexicographically smaller than an array `b`
11+
if in the first position where `a` and `b` differ,
12+
array `a` has an element that is less than the corresponding element in `b`.
13+
For example, the array `[2,10,3]` is lexicographically smaller than the array `[10,2,3]` because
14+
they differ at index `0` and `2 < 10`.
15+
16+
## 基礎思路
17+
我們可以觀測到,最理想情況是由小排到大。
18+
但是因為有 limit 的限制,能被交換不得超過 limit。
19+
那麼我們將 nums 可進行交換的分組,對每個分組進行排序,最後再寫回該分組位置。
20+
21+
> Tips
22+
> 這題也是非常容易炸掉 Time Limit 的題目,所以我們需要找到一個最佳解法。
23+
> 一個有效解決這種分組組內排序的方法是使用 "已排序的索引" 來進行排序。
24+
25+
## 解題步驟
26+
27+
### Step 1: 紀錄長度 n
28+
29+
```typescript
30+
const n: number = nums.length;
31+
```
32+
33+
### Step 2: 將 nums 進行索引排序
34+
35+
```typescript
36+
const sortedIndices: number[] = Array.from({ length: n }, (_, index) => index);
37+
sortedIndices.sort((a, b) => nums[a] - nums[b]);
38+
```
39+
這是透過 `sortedIndices` 來紀錄以數值排序後的原始陣列索引。
40+
41+
### Step 3: 依照 limit 進行分組
42+
43+
```typescript
44+
let groupStart: number = 0;
45+
while (groupStart < n) {
46+
47+
}
48+
```
49+
終止條件式我們已經移動到最後一個索引。
50+
51+
### Step 3.1 找到分組結束索引
52+
53+
```typescript
54+
let groupStart: number = 0;
55+
while (groupStart < n) {
56+
// 初始化分組結束索引
57+
let groupEnd: number = groupStart + 1;
58+
59+
// 找到分組結束索引
60+
// 這需要滿足不超出陣列範圍 `n` 且差值不超過 limit
61+
// 我們從較小的數字開始,利用索引表持續找尋直到不符合條件,代表該分組結束,此時 groupEnd 即為分組結束索引
62+
while (groupEnd < n && nums[sortedIndices[groupEnd]] - nums[sortedIndices[groupEnd - 1]] <= limit) {
63+
groupEnd++;
64+
}
65+
}
66+
```
67+
68+
### Step 3.2 對分組進行排序
69+
70+
```typescript
71+
// Process each group of indices with values within the "limit" difference
72+
let groupStart: number = 0;
73+
while (groupStart < n) {
74+
// 3.1 找到分組結束索引
75+
76+
// 我們取得分組的索引
77+
const groupIndices: number[] = sortedIndices
78+
.slice(groupStart, groupEnd)
79+
.sort((a, b) => a - b);
80+
81+
// 我們僅對分組進行排序
82+
const sortedValues: number[] = groupIndices
83+
.map(index => nums[index])
84+
.sort((a, b) => a - b);
85+
}
86+
```
87+
88+
### Step 3.3 將排序後的值寫回原始陣列
89+
90+
```typescript
91+
// Process each group of indices with values within the "limit" difference
92+
let groupStart: number = 0;
93+
while (groupStart < n) {
94+
// 3.1 找到分組結束索引
95+
96+
// 3.2 對分組進行排序
97+
98+
// 將排序後的值寫到結果陣列
99+
for (let i = 0; i < groupIndices.length; i++) {
100+
result[groupIndices[i]] = sortedValues[i];
101+
}
102+
103+
// 我們移動到下一個分組起始索引,繼續檢查其他的分組
104+
groupStart = groupEnd;
105+
}
106+
```
107+
108+
## 時間複雜度
109+
- 排序索引的操作耗費 $O(n \log n)$
110+
- 分組和結果更新共耗費 $O(n)$
111+
- 分組內排序耗費 $O(n \log n)$
112+
- 總時間複雜度為 $O(n \log n)$。
113+
114+
115+
> $O(n \log n)$
116+
117+
## 空間複雜度
118+
- 額外空間包含排序操作的臨時數據 ($O(n)$)
119+
- 結果陣列 ($O(n)$)
120+
- 分組索引與值的臨時存儲 ($O(n)$)
121+
- 總空間複雜度為 $O(n)$。
122+
123+
> $O(n)$
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
function lexicographicallySmallestArray(nums: number[], limit: number): number[] {
2+
const n: number = nums.length;
3+
4+
// Create an array of indices and sort them by their corresponding values in nums
5+
const sortedIndices: number[] = Array.from({ length: n }, (_, index) => index);
6+
sortedIndices.sort((a, b) => nums[a] - nums[b]);
7+
8+
// Initialize the result array
9+
const result: number[] = Array(n).fill(0);
10+
11+
// Process each group of indices with values within the "limit" difference
12+
let groupStart: number = 0;
13+
while (groupStart < n) {
14+
let groupEnd: number = groupStart + 1;
15+
16+
// Expand the group while the difference between consecutive values is <= limit
17+
while (groupEnd < n && nums[sortedIndices[groupEnd]] - nums[sortedIndices[groupEnd - 1]] <= limit) {
18+
groupEnd++;
19+
}
20+
21+
// Extract and sort the current group of indices
22+
const groupIndices: number[] = sortedIndices
23+
.slice(groupStart, groupEnd)
24+
.sort((a, b) => a - b);
25+
26+
// Sort the values of the group and place them into the result array
27+
const sortedValues: number[] = groupIndices
28+
.map(index => nums[index])
29+
.sort((a, b) => a - b);
30+
31+
// Write the sorted values back to the result array
32+
for (let i = 0; i < groupIndices.length; i++) {
33+
result[groupIndices[i]] = sortedValues[i];
34+
}
35+
36+
// Move to the next group
37+
groupStart = groupEnd;
38+
}
39+
40+
return result;
41+
}

0 commit comments

Comments
 (0)