Skip to content

Commit ea640f0

Browse files
committed
feat: add solutions to lc problem: No.1505
No.1505.Minimum Possible Integer After at Most K Adjacent Swaps On Digits
1 parent 2fed9aa commit ea640f0

File tree

6 files changed

+704
-1
lines changed

6 files changed

+704
-1
lines changed

solution/1500-1599/1505.Minimum Possible Integer After at Most K Adjacent Swaps On Digits/README.md

+254-1
Original file line numberDiff line numberDiff line change
@@ -68,22 +68,275 @@
6868

6969
<!-- 这里可写通用的实现逻辑 -->
7070

71+
**方法一:贪心算法 + 树状数组**
72+
73+
树状数组,也称作“二叉索引树”(Binary Indexed Tree)或 Fenwick 树。 它可以高效地实现如下两个操作:
74+
75+
1. **单点更新** `update(x, delta)`: 把序列 x 位置的数加上一个值 delta;
76+
1. **前缀和查询** `query(x)`:查询序列 `[1,...x]` 区间的区间和,即位置 x 的前缀和。
77+
78+
这两个操作的时间复杂度均为 `O(log n)`
79+
80+
对于本题,要想得到在 k 次交换内字典序最小整数,我们可以「贪心」地从 num 的最高位开始考虑,即希望 num 的最高位尽可能小。我们可以依次枚举 `0~9`,对于当前枚举到的数位 x,判断是否可以将某个位置上的 x 通过最多 k 次交换移动到最高位。由于每一次交换只能交换相邻位置的两个数字,因此将一个距离最高位为 s 的数位移动到最高位,需要 s 次交换操作。例如当 `num = 97620` 时,0 与最高位的距离为 4,我们可以通过 4 次交换操作把 0 移动到最高位。
81+
82+
这样的交换操作相当于把 0 移动到最高位,同时将 0 之前的所有数位向后移动了一位。
83+
84+
我们接下来考虑次高位。与最高位类似,我们选择最小的数位 x,使得它与次高位的距离不超过 k',其中 k' 是 k 扣除最高位交换后的剩余次数。
85+
86+
考虑上面 `num = 97620` 的例子,此时我们应当选择 x=2 交换至次高位。然而我们发现,经过第一次的交换操作,2 所在的位置发生了变化!在 num 中,2 与次高位的距离为 2,而将 0 交换至最高位后,2 与次高位的距离增加了 1,变为 3。这是因为 0 从 2 的后面「转移」到了 2 的前面,使得 2 向后移动了一位。因此,x 实际所在的位置,等于 x 初始时在 num 中的位置,加上 x 后面发生交换的数位个数。这里的「x 后面发生交换的数位个数」,就可以使用**树状数组**进行维护。
87+
88+
解题思路如下:
89+
90+
1.`pos[x]` 按照高位到低位的顺序,存放所有 x 在 num 中出现的位置;
91+
1. 从高到低遍历每一个位置。对于位置 i,我们从小到大枚举交换的数位 x。`pos[x]` 中的首个元素即为与当前位置距离最近的 x 的位置:
92+
- 记 j 为 `pos[x]` 中的首元素,那么 `num[j]`(也即是 x)当前实际所在的位置,等于 j 加上 j 后面发现交换的数位个数。我们使用树状数组查询区间 `[j + 1, n]`,那么 num[j] 与位置 i 的实际距离 dist 为:`tree.query(n) - tree.query(j) + j - i`
93+
- 如果 dist 小于等于 k,那么我们可以将 x 交换至位置 i。我们使用树状数组更新单点 j,将对应的值增加 1,表示该位置的数位发生了变换。随后更新 k 值,以及将 j 从 `pos[x]` 中移除。
94+
1. 遍历结束后,我们就得到了答案。
95+
7196
<!-- tabs:start -->
7297

7398
### **Python3**
7499

75100
<!-- 这里可写当前语言的特殊实现逻辑 -->
76101

77102
```python
78-
103+
class BinaryIndexedTree:
104+
def __init__(self, n):
105+
self.n = n
106+
self.c = [0] * (n + 1)
107+
108+
@staticmethod
109+
def lowbit(x):
110+
return x & -x
111+
112+
def update(self, x, delta):
113+
while x <= self.n:
114+
self.c[x] += delta
115+
x += BinaryIndexedTree.lowbit(x)
116+
117+
def query(self, x):
118+
s = 0
119+
while x:
120+
s += self.c[x]
121+
x -= BinaryIndexedTree.lowbit(x)
122+
return s
123+
124+
125+
class Solution:
126+
def minInteger(self, num: str, k: int) -> str:
127+
pos = defaultdict(deque)
128+
for i, v in enumerate(num, 1):
129+
pos[int(v)].append(i)
130+
ans = []
131+
n = len(num)
132+
tree = BinaryIndexedTree(n)
133+
for i in range(1, n + 1):
134+
for v in range(10):
135+
q = pos[v]
136+
if q:
137+
j = q[0]
138+
dist = tree.query(n) - tree.query(j) + j - i
139+
if dist <= k:
140+
k -= dist
141+
q.popleft()
142+
ans.append(str(v))
143+
tree.update(j, 1)
144+
break
145+
return ''.join(ans)
79146
```
80147

81148
### **Java**
82149

83150
<!-- 这里可写当前语言的特殊实现逻辑 -->
84151

85152
```java
153+
class Solution {
154+
public String minInteger(String num, int k) {
155+
Queue<Integer>[] pos = new Queue[10];
156+
for (int i = 0; i < 10; ++i) {
157+
pos[i] = new ArrayDeque<>();
158+
}
159+
int n = num.length();
160+
for (int i = 0; i < n; ++i) {
161+
pos[num.charAt(i) - '0'].offer(i + 1);
162+
}
163+
StringBuilder ans = new StringBuilder();
164+
BinaryIndexedTree tree = new BinaryIndexedTree(n);
165+
for (int i = 1; i <= n; ++i) {
166+
for (int v = 0; v < 10; ++v) {
167+
if (!pos[v].isEmpty()) {
168+
Queue<Integer> q = pos[v];
169+
int j = q.peek();
170+
int dist = tree.query(n) - tree.query(j) + j - i;
171+
if (dist <= k) {
172+
k -= dist;
173+
q.poll();
174+
ans.append(v);
175+
tree.update(j, 1);
176+
break;
177+
}
178+
}
179+
}
180+
}
181+
return ans.toString();
182+
}
183+
}
184+
185+
class BinaryIndexedTree {
186+
private int n;
187+
private int[] c;
188+
189+
public BinaryIndexedTree(int n) {
190+
this.n = n;
191+
c = new int[n + 1];
192+
}
193+
194+
public void update(int x, int delta) {
195+
while (x <= n) {
196+
c[x] += delta;
197+
x += lowbit(x);
198+
}
199+
}
200+
201+
public int query(int x) {
202+
int s = 0;
203+
while (x > 0) {
204+
s += c[x];
205+
x -= lowbit(x);
206+
}
207+
return s;
208+
}
209+
210+
public static int lowbit(int x) {
211+
return x & -x;
212+
}
213+
}
214+
```
215+
216+
### **C++**
217+
218+
```cpp
219+
class BinaryIndexedTree {
220+
public:
221+
int n;
222+
vector<int> c;
223+
224+
BinaryIndexedTree(int _n): n(_n), c(_n + 1){}
225+
226+
void update(int x, int delta) {
227+
while (x <= n)
228+
{
229+
c[x] += delta;
230+
x += lowbit(x);
231+
}
232+
}
233+
234+
int query(int x) {
235+
int s = 0;
236+
while (x > 0)
237+
{
238+
s += c[x];
239+
x -= lowbit(x);
240+
}
241+
return s;
242+
}
243+
244+
int lowbit(int x) {
245+
return x & -x;
246+
}
247+
};
248+
249+
class Solution {
250+
public:
251+
string minInteger(string num, int k) {
252+
vector<queue<int>> pos(10);
253+
int n = num.size();
254+
for (int i = 0; i < n; ++i) pos[num[i] - '0'].push(i + 1);
255+
BinaryIndexedTree* tree = new BinaryIndexedTree(n);
256+
string ans = "";
257+
for (int i = 1; i <= n; ++i)
258+
{
259+
for (int v = 0; v < 10; ++v)
260+
{
261+
auto& q = pos[v];
262+
if (!q.empty())
263+
{
264+
int j = q.front();
265+
int dist = tree->query(n) - tree->query(j) + j - i;
266+
if (dist <= k)
267+
{
268+
k -= dist;
269+
q.pop();
270+
ans += (v + '0');
271+
tree->update(j, 1);
272+
break;
273+
}
274+
}
275+
}
276+
}
277+
return ans;
278+
}
279+
};
280+
```
86281
282+
### **Go**
283+
284+
```go
285+
type BinaryIndexedTree struct {
286+
n int
287+
c []int
288+
}
289+
290+
func newBinaryIndexedTree(n int) *BinaryIndexedTree {
291+
c := make([]int, n+1)
292+
return &BinaryIndexedTree{n, c}
293+
}
294+
295+
func (this *BinaryIndexedTree) lowbit(x int) int {
296+
return x & -x
297+
}
298+
299+
func (this *BinaryIndexedTree) update(x, delta int) {
300+
for x <= this.n {
301+
this.c[x] += delta
302+
x += this.lowbit(x)
303+
}
304+
}
305+
306+
func (this *BinaryIndexedTree) query(x int) int {
307+
s := 0
308+
for x > 0 {
309+
s += this.c[x]
310+
x -= this.lowbit(x)
311+
}
312+
return s
313+
}
314+
315+
func minInteger(num string, k int) string {
316+
pos := make([][]int, 10)
317+
for i, c := range num {
318+
pos[c-'0'] = append(pos[c-'0'], i+1)
319+
}
320+
n := len(num)
321+
tree := newBinaryIndexedTree(n)
322+
var ans strings.Builder
323+
for i := 1; i <= n; i++ {
324+
for v := 0; v < 10; v++ {
325+
if len(pos[v]) > 0 {
326+
j := pos[v][0]
327+
dist := tree.query(n) - tree.query(j) + j - i
328+
if dist <= k {
329+
k -= dist
330+
pos[v] = pos[v][1:]
331+
ans.WriteByte(byte(v + '0'))
332+
tree.update(j, 1)
333+
break
334+
}
335+
}
336+
}
337+
}
338+
return ans.String()
339+
}
87340
```
88341

89342
### **...**

0 commit comments

Comments
 (0)