重新放置石块
难度:
标签:
题目描述
You are given a 0-indexed integer array nums
representing the initial positions of some marbles. You are also given two 0-indexed integer arrays moveFrom
and moveTo
of equal length.
Throughout moveFrom.length
steps, you will change the positions of the marbles. On the ith
step, you will move all marbles at position moveFrom[i]
to position moveTo[i]
.
After completing all the steps, return the sorted list of occupied positions.
Notes:
- We call a position occupied if there is at least one marble in that position.
- There may be multiple marbles in a single position.
Example 1:
Input: nums = [1,6,7,8], moveFrom = [1,7,2], moveTo = [2,9,5] Output: [5,6,8,9] Explanation: Initially, the marbles are at positions 1,6,7,8. At the i = 0th step, we move the marbles at position 1 to position 2. Then, positions 2,6,7,8 are occupied. At the i = 1st step, we move the marbles at position 7 to position 9. Then, positions 2,6,8,9 are occupied. At the i = 2nd step, we move the marbles at position 2 to position 5. Then, positions 5,6,8,9 are occupied. At the end, the final positions containing at least one marbles are [5,6,8,9].
Example 2:
Input: nums = [1,1,3,3], moveFrom = [1,3], moveTo = [2,2] Output: [2] Explanation: Initially, the marbles are at positions [1,1,3,3]. At the i = 0th step, we move all the marbles at position 1 to position 2. Then, the marbles are at positions [2,2,3,3]. At the i = 1st step, we move all the marbles at position 3 to position 2. Then, the marbles are at positions [2,2,2,2]. Since 2 is the only occupied position, we return [2].
Constraints:
1 <= nums.length <= 105
1 <= moveFrom.length <= 105
moveFrom.length == moveTo.length
1 <= nums[i], moveFrom[i], moveTo[i] <= 109
- The test cases are generated such that there is at least a marble in
moveFrom[i]
at the moment we want to apply theith
move.
代码结果
运行时间: 77 ms, 内存: 34.6 MB
/*
* 思路:
* 1. 使用Java Stream API来处理石块的位置变换。
* 2. 用Map记录石块的初始位置。
* 3. 使用IntStream处理moveFrom和moveTo数组,更新石块位置。
* 4. 收集有石块的位置,按升序返回结果。
*/
import java.util.*;
import java.util.stream.*;
public class Solution {
public List<Integer> relocateStones(int[] nums, int[] moveFrom, int[] moveTo) {
Map<Integer, Integer> stoneMap = Arrays.stream(nums)
.boxed()
.collect(Collectors.toMap(k -> k, v -> 1, Integer::sum));
IntStream.range(0, moveFrom.length).forEach(i -> {
int from = moveFrom[i];
int to = moveTo[i];
if (stoneMap.containsKey(from)) {
stoneMap.put(to, stoneMap.getOrDefault(to, 0) + stoneMap.get(from));
stoneMap.remove(from);
}
});
return stoneMap.keySet().stream().sorted().collect(Collectors.toList());
}
}
解释
方法:
这个解决方案使用了一个集合(Set)来跟踪所有石块的位置。初始时,将 nums 数组中所有的位置加入到集合中,代表石块的初始位置。然后,通过遍历 moveFrom 和 moveTo 数组,对于每一对操作(从 moveFrom[i] 移动到 moveTo[i]),先从集合中移除 moveFrom[i](因为石块从此位置移走),然后将 moveTo[i] 加入到集合中(石块移动到新位置)。因为集合自动处理重复的元素,所以即使多次移动到同一个位置也不会有问题。最后,将集合转换为有序数组后返回,这样可以得到所有有石块的位置的升序列表。
时间复杂度:
O(n + m + k log k)
空间复杂度:
O(n + m)
代码细节讲解
🦆
在算法中,为什么在移动石块后从集合中删除moveFrom[i]位置,即使可能还有其他石块留在那里?
▷🦆
如果moveFrom数组中的某个位置在nums中不存在,该怎么处理?这种情况会影响最终的输出结果吗?
▷🦆
算法中提到的‘集合自动处理重复元素’是如何确保在多次移动到同一个位置时不会出现问题的?具体是如何操作的?
▷🦆
将集合转换成有序数组的操作,为什么选择了排序而不是其他可能更高效的方法?
▷