设备中存有 n
个文件,文件 id
记于数组 documents
。若文件 id
相同,则定义为该文件存在副本。请返回任一存在副本的文件 id
。
示例 1:
输入:documents = [2, 5, 3, 0, 5, 0] 输出:0 或 5
提示:
0 ≤ documents[i] ≤ n-1
2 <= n <= 100000
解法:原地交换(原地哈希)
题目提示,在一个长度为 n 的数组 documents 里的所有数字都在 0 ~ n-1 的范围内 。 此说明含义:数组元素的 索引 和 值 是 一对多 的关系。
class Solution {
public int findRepeatDocument(int[] documents) {
int n = documents.length;
for (int i = 0; i < n; i++) {
int x = documents[i];
while (x != i) {
if (documents[x] == x) {
return x;
}
swap(documents, i, x);
// 此时documents[x]和documents[i]已经交换了,documents[i]需要充值新赋值给x
x = documents[i];
}
}
throw new IllegalArgumentException("illegal argument");
}
private void swap(int[] nums, int i, int j) {
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
}
复杂度分析:
时间复杂度: O(N) , 遍历数组使用 O(N),每轮遍历的判断和交换操作使用 O(1) 。
空间复杂度 :O(1) , 使用常数复杂度的额外空间。