leetcode287:寻找重复数

题目链接

leetcode

题目描述

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。
假设 nums 只有 一个重复的整数 ,返回 这个重复的数
你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。

C++ 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include <iostream>
#include <vector>
using namespace std;

/*
二分查找

在 [1, n] 范围内进行二分查找;
对于中间值 mid,统计数组中小于等于 mid 的元素个数;
若个数 > mid,则说明 [1, mid] 区间内存在重复的元素;
否则,在 [mid+1, n] 区间查找。

时间复杂度:O(nlogn)
其中 n 为数组的长度。
空间复杂度:O(1)
*/
class Solution_0 {
public:
int findDuplicate(vector<int>& nums) {
int l = 1, r = nums.size()-1;
while (l < r) {
int mid = l + (r - l) / 2;
int count = 0;

for (int num : nums) {
if (num <= mid) {
count++;
}
}

if (count > mid) {
r = mid;
} else {
l = mid + 1;
}
}

return l;
}
};

/*
快慢指针

nums 数组建图,每个位置 i 连一条边 i 到 nums[i]。
存在重复的数字 target, target 这个位置一定有两条指向它的边,
这张图一定存在环,找到的 target 就是这个环的入口。

时间复杂度:O(n)
空间复杂度:O(1)
*/
class Solution {
public:
int findDuplicate(vector<int>& nums) {
// 使用快慢指针找到相遇点
int slow = 0, fast = 0;

while (true) {
slow = nums[slow]; // 慢指针走一步
fast = nums[nums[fast]]; // 快指针走两步
if (slow == fast) {
break;
}
}

// 找到环的入口点
slow = 0;
while (slow != fast) {
slow = nums[slow];
fast = nums[fast];
}

return slow;
}
};

// 辅助函数:打印数组
void printArray(const vector<int>& nums) {
cout << "[";
for (size_t i = 0; i < nums.size(); i++) {
cout << nums[i];
if (i != nums.size() - 1) cout << ",";
}
cout << "]";
}

int main() {
Solution solution;
vector<vector<int>> nums_cases = {
{1,3,4,2,2},
{3,1,3,4,2},
{3,3,3,3,3}
};

for (auto & nums : nums_cases) {
cout << "Input: ";
printArray(nums);
cout << endl;
int result = solution.findDuplicate(nums);
cout << "Output: " << result << endl;
}

return 0;
}

leetcode287:寻找重复数
https://lcf163.github.io/2024/05/06/leetcode287:寻找重复数/
作者
乘风的小站
发布于
2024年5月6日
许可协议