问题背景
给你一个 从 000 开始的排列 numsnumsnums(下标也从000开始)。请你构建一个 同样长度 的数组 ansansans,其中,对于每个 iii( 0≤i<nums.length0 \le i < nums.length0≤i<nums.length ),都满足 ans[i]=nums[nums[i]]ans[i] = nums[nums[i]]ans[i]=nums[nums[i]]。返回构建好的数组 ansansans。
从 000 开始的排列 numsnumsnums 是一个由 000 到 nums.length−1nums.length - 1nums.length−1( 000 和 nums.length−1nums.length - 1nums.length−1 也包含在内)的不同整数组成的数组。
数据约束
- 1≤nums.length≤10001 \le nums.length \le 10001≤nums.length≤1000
- 0≤nums[i]<nums.length0 \le nums[i] < nums.length0≤nums[i]<nums.length
- numsnumsnums中的元素 互不相同
解题过程
其实直接照做就能解决问题,果不其然题目要求不使用额外空间,其实完全没必要,鉴定为屎山换空间。
空间复杂度 O(1)O(1)O(1) 的做法,和 轮转数组 直接做的方法很类似,不断操作总会回到初始位置,这时候流程结束,过程中用一个额外的变量记录下一个元素防止覆盖即可。
已经完成迁移的位置用一个负数来标记,取反运算可以将任意非负数变成负数。
具体实现
直接照做
class Solution {
public int[] buildArray(int[] nums) {
int n = nums.length;
int[] res = new int[n];
for (int i = 0; i < n; i++) {
res[i] = nums[nums[i]];
}
return res;
}
}
迁移元素
class Solution {
public int[] buildArray(int[] nums) {
for (int i = 0; i < nums.length; i++) {
int item = nums[i];
if (item < 0) {
continue;
}
int cur = i;
while (nums[cur] != i) {
int next = nums[cur];
nums[cur] = ~nums[next];
cur = next;
}
nums[cur] = ~item;
}
for (int i = 0; i < nums.length; i++) {
nums[i] = ~nums[i];
}
return nums;
}
}