Skip to content

Commit 1912cd0

Browse files
committed
feat: add solutions to lc problem: No.2059
No.2059.Minimum Operations to Convert Number
1 parent 2072d62 commit 1912cd0

File tree

2 files changed

+418
-2
lines changed

2 files changed

+418
-2
lines changed

solution/2000-2099/2059.Minimum Operations to Convert Number/README.md

+224-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,37 @@
8989

9090
<!-- 这里可写通用的实现逻辑 -->
9191

92-
BFS 最小步数模型。
92+
BFS 最小步数模型。本题搜索空间不大,可以直接使用朴素 BFS,以下题解中还提供了双向 BFS 的题解代码,仅供参考。
93+
94+
双向 BFS 是 BFS 常见的一个优化方法,主要实现思路如下:
95+
96+
1. 创建两个队列 q1, q2 分别用于“起点 -> 终点”、“终点 -> 起点”两个方向的搜索;
97+
2. 创建两个哈希表 m1, m2 分别记录访问过的节点以及对应的扩展次数(步数);
98+
3. 每次搜索时,优先选择元素数量较少的队列进行搜索扩展,如果在扩展过程中,搜索到另一个方向已经访问过的节点,说明找到了最短路径;
99+
4. 只要其中一个队列为空,说明当前方向的搜索已经进行不下去了,说明起点到终点不连通,无需继续搜索。
100+
101+
```python
102+
while q1 and q2:
103+
if len(q1) <= len(q2):
104+
# 优先选择较少元素的队列进行扩展
105+
extend(m1, m2, q1)
106+
else:
107+
extend(m2, m1, q2)
108+
def extend(m1, m2, q):
109+
# 新一轮扩展
110+
for _ in range(len(q), 0, -1):
111+
p = q.popleft()
112+
step = m1[p]
113+
for t in next(p):
114+
if t in m1:
115+
# 此前已经访问过
116+
continue
117+
if t in m2:
118+
# 另一个方向已经搜索过,说明找到了一条最短的连通路径
119+
return step + 1 + m2[t]
120+
q.append(t)
121+
m1[t] = step + 1
122+
```
93123

94124
<!-- tabs:start -->
95125

@@ -146,6 +176,42 @@ class Solution:
146176
return -1
147177
```
148178

179+
双向 BFS:
180+
181+
```python
182+
class Solution:
183+
def minimumOperations(self, nums: List[int], start: int, goal: int) -> int:
184+
def next(x):
185+
res = []
186+
for num in nums:
187+
res.append(x + num)
188+
res.append(x - num)
189+
res.append(x ^ num)
190+
return res
191+
192+
def extend(m1, m2, q):
193+
for _ in range(len(q), 0, -1):
194+
x = q.popleft()
195+
step = m1[x]
196+
for y in next(x):
197+
if y in m1:
198+
continue
199+
if y in m2:
200+
return step + 1 + m2[y]
201+
if 0 <= y <= 1000:
202+
m1[y] = step + 1
203+
q.append(y)
204+
return -1
205+
206+
m1, m2 = {start: 0}, {goal: 0}
207+
q1, q2 = deque([start]), deque([goal])
208+
while q1 and q2:
209+
t = extend(m1, m2, q1) if len(q1) <= len(q2) else extend(m2, m1, q2)
210+
if t != -1:
211+
return t
212+
return -1
213+
```
214+
149215
### **Java**
150216

151217
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -218,6 +284,63 @@ class Solution {
218284
}
219285
```
220286

287+
双向 BFS:
288+
289+
```java
290+
class Solution {
291+
private int[] nums;
292+
293+
public int minimumOperations(int[] nums, int start, int goal) {
294+
this.nums = nums;
295+
Map<Integer, Integer> m1 = new HashMap<>();
296+
Map<Integer, Integer> m2 = new HashMap<>();
297+
Deque<Integer> q1 = new ArrayDeque<>();
298+
Deque<Integer> q2 = new ArrayDeque<>();
299+
m1.put(start, 0);
300+
m2.put(goal, 0);
301+
q1.offer(start);
302+
q2.offer(goal);
303+
while (!q1.isEmpty() && !q2.isEmpty()) {
304+
int t = q1.size() <= q2.size() ? extend(m1, m2, q1) : extend(m2, m1, q2);
305+
if (t != -1) {
306+
return t;
307+
}
308+
}
309+
return -1;
310+
}
311+
312+
private int extend(Map<Integer, Integer> m1, Map<Integer, Integer> m2, Deque<Integer> q) {
313+
for (int i = q.size(); i > 0; --i) {
314+
int x = q.poll();
315+
int step = m1.get(x);
316+
for (int y : next(x)) {
317+
if (m1.containsKey(y)) {
318+
continue;
319+
}
320+
if (m2.containsKey(y)) {
321+
return step + 1 + m2.get(y);
322+
}
323+
if (y >= 0 && y <= 1000) {
324+
m1.put(y, step + 1);
325+
q.offer(y);
326+
}
327+
}
328+
}
329+
return -1;
330+
}
331+
332+
private List<Integer> next(int x) {
333+
List<Integer> res = new ArrayList<>();
334+
for (int num : nums) {
335+
res.add(x + num);
336+
res.add(x - num);
337+
res.add(x ^ num);
338+
}
339+
return res;
340+
}
341+
}
342+
```
343+
221344
### **C++**
222345

223346
```cpp
@@ -295,6 +418,59 @@ public:
295418
};
296419
```
297420

421+
双向 BFS:
422+
423+
```cpp
424+
class Solution {
425+
public:
426+
int minimumOperations(vector<int>& nums, int start, int goal) {
427+
unordered_map<int, int> m1;
428+
unordered_map<int, int> m2;
429+
m1[start] = 0;
430+
m2[goal] = 0;
431+
queue<int> q1{{start}};
432+
queue<int> q2{{goal}};
433+
while (!q1.empty() && !q2.empty())
434+
{
435+
int t = q1.size() <= q2.size() ? extend(m1, m2, q1, nums) : extend(m2, m1, q2, nums);
436+
if (t != -1) return t;
437+
}
438+
return -1;
439+
}
440+
441+
int extend(unordered_map<int, int>& m1, unordered_map<int, int>& m2, queue<int>& q, vector<int>& nums) {
442+
for (int i = q.size(); i > 0; --i)
443+
{
444+
int x = q.front();
445+
int step = m1[x];
446+
q.pop();
447+
for (int y : next(nums, x))
448+
{
449+
if (m1.count(y)) continue;
450+
if (m2.count(y)) return step + 1 + m2[y];
451+
if (y >= 0 && y <= 1000)
452+
{
453+
m1[y] = step + 1;
454+
q.push(y);
455+
}
456+
}
457+
}
458+
return -1;
459+
}
460+
461+
vector<int> next(vector<int>& nums, int x) {
462+
vector<int> res;
463+
for (int num : nums)
464+
{
465+
res.push_back(x + num);
466+
res.push_back(x - num);
467+
res.push_back(x ^ num);
468+
}
469+
return res;
470+
}
471+
};
472+
```
473+
298474
### **Go**
299475
300476
```go
@@ -364,6 +540,53 @@ func minimumOperations(nums []int, start int, goal int) int {
364540
}
365541
```
366542

543+
双向 BFS:
544+
545+
```go
546+
func minimumOperations(nums []int, start int, goal int) int {
547+
next := func(x int) []int {
548+
var res []int
549+
for _, num := range nums {
550+
res = append(res, []int{x + num, x - num, x ^ num}...)
551+
}
552+
return res
553+
}
554+
m1, m2 := map[int]int{start: 0}, map[int]int{goal: 0}
555+
q1, q2 := []int{start}, []int{goal}
556+
extend := func() int {
557+
for i := len(q1); i > 0; i-- {
558+
x := q1[0]
559+
q1 = q1[1:]
560+
step, _ := m1[x]
561+
for _, y := range next(x) {
562+
if _, ok := m1[y]; ok {
563+
continue
564+
}
565+
if v, ok := m2[y]; ok {
566+
return step + 1 + v
567+
}
568+
if y >= 0 && y <= 1000 {
569+
m1[y] = step + 1
570+
q1 = append(q1, y)
571+
}
572+
}
573+
}
574+
return -1
575+
}
576+
for len(q1) > 0 && len(q2) > 0 {
577+
if len(q1) > len(q2) {
578+
m1, m2 = m2, m1
579+
q1, q2 = q2, q1
580+
}
581+
t := extend()
582+
if t != -1 {
583+
return t
584+
}
585+
}
586+
return -1
587+
}
588+
```
589+
367590
### **TypeScript**
368591

369592
```ts

0 commit comments

Comments
 (0)