【题目描述】
给你一个下标从 0 开始的整数数组
nums
,表示一些石块的初始位置。再给你两个长度 相等 下标从 0 开始的整数数组moveFrom
和moveTo
。在
moveFrom.length
次操作内,你可以改变石块的位置。在第i
次操作中,你将位置在moveFrom[i]
的所有石块移到位置moveTo[i]
。完成这些操作后,请你按升序返回所有 有 石块的位置。
注意:
- 如果一个位置至少有一个石块,我们称这个位置 有 石块。
- 一个位置可能会有多个石块。
示例 1:
输入:nums = [1,6,7,8], moveFrom = [1,7,2], moveTo = [2,9,5] 输出:[5,6,8,9] 解释:一开始,石块在位置 1,6,7,8 。 第 i = 0 步操作中,我们将位置 1 处的石块移到位置 2 处,位置 2,6,7,8 有石块。 第 i = 1 步操作中,我们将位置 7 处的石块移到位置 9 处,位置 2,6,8,9 有石块。 第 i = 2 步操作中,我们将位置 2 处的石块移到位置 5 处,位置 5,6,8,9 有石块。 最后,至少有一个石块的位置为 [5,6,8,9] 。示例 2:
输入:nums = [1,1,3,3], moveFrom = [1,3], moveTo = [2,2] 输出:[2] 解释:一开始,石块在位置 [1,1,3,3] 。 第 i = 0 步操作中,我们将位置 1 处的石块移到位置 2 处,有石块的位置为 [2,2,3,3] 。 第 i = 1 步操作中,我们将位置 3 处的石块移到位置 2 处,有石块的位置为 [2,2,2,2] 。 由于 2 是唯一有石块的位置,我们返回 [2] 。提示:
1 <= nums.length <= 105
1 <= moveFrom.length <= 105
moveFrom.length == moveTo.length
1 <= nums[i], moveFrom[i], moveTo[i] <= 109
- 测试数据保证在进行第
i
步操作时,moveFrom[i]
处至少有一个石块。
【题目链接】:. - 力扣(LeetCode)
【解题代码】
package array;
import dp.MaxProfit2;
import java.util.*;
import java.util.stream.Collectors;
public class RelocateMarbles {
public static void main(String[] args) {
//int[] nums = {1, 6, 7, 8}, moveFrom = {1, 7, 2}, moveTo = {2, 9, 5};
//int[] nums = {1, 1, 3, 3}, moveFrom = {1, 3}, moveTo = {2, 2};
int[] nums = {4, 6, 6, 9, 18}, moveFrom = {18, 6, 17, 4, 9, 19, 2}, moveTo = {23, 17, 20, 19, 11, 2, 20};
List result = new RelocateMarbles().relocateMarbles(nums, moveFrom, moveTo);
System.out.println("计算结果:" + result);
}
public List<Integer> relocateMarbles(int[] nums, int[] moveFrom, int[] moveTo) {
Set<Integer> numSet = new HashSet<>(Arrays.stream(nums).boxed().collect(Collectors.toList()));
for (int i = 0; i < moveFrom.length; i++) {
numSet.remove(moveFrom[i]);
numSet.add(moveTo[i]);
}
List<Integer> result = new ArrayList<>(numSet);
result.sort(Comparator.naturalOrder());
return result;
}
}
【解题思路】
根据题目描述,思索了一会,感觉可以用HashSet来处理这个问题,先用nums数组初始化下HashSet,然后依次将moveFrom数据删除,并同时添加 moveTo数据,按照这个思路很快完成代码编写
public List<Integer> relocateMarbles(int[] nums, int[] moveFrom, int[] moveTo) {
Set<Integer> numSet = new HashSet<>();
for (int num : nums) {
numSet.add(num);
}
for (int i = 0; i < moveFrom.length; i++) {
numSet.remove(moveFrom[i]);
numSet.add(moveTo[i]);
}
return new ArrayList<>(numSet);
}
点击“运行”成功,但提交之后出现报错:
原来数据没有按从大到小排序,于是将数据结构从HashSet改成默认带排序的TreeSet,代码提交成功
但是感觉性能不是很好,改回到使用HashSet,然后自行排序效果如何呢?按照这个思路,再次修改代码,提交成功,性能果然有不小的提升
【解题步骤】
- 创建一个HashSet对象,并使用数组num对其初始化;
Set<Integer> numSet = new HashSet<>(Arrays.stream(nums).boxed().collect(Collectors.toList()));
- 依次从HashSet删除moveFrom数据,同时添加moveTo数据;
for (int i = 0; i < moveFrom.length; i++) { numSet.remove(moveFrom[i]); numSet.add(moveTo[i]); }
- 将处理完的HashSet数据导入一个链表;
List<Integer> result = new ArrayList<>(numSet);
- 对链表进行缺失的从大到小排序
result.sort(Comparator.naturalOrder());
- 返回此链表
return result;
【思考总结】
- 这道题的关键点就是采用Set来处理数据;
- 采用HashSet然后自行排序的性能要好于直接使用带排序的TreeSet
- LeetCode解题之前,一定不要看题解,看了就“破功”了!