leetcode:287. 寻找重复数
题目
给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。
假设 nums 只有 一个重复的整数(即只有一个整数出现两次或多次 ,其余整数均只出现一次) ,返回 这个重复的数 。
你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。
示例:
输入:nums = [1,3,4,2,2]输出:2
输入:nums = [3,1,3,4,2]输出:3
进阶:你可以设计一个线性级时间复杂度 O(n) 的解决方案吗?
解答 & 代码
解法 0:原地哈希
该解法不合题意,因为题目要求不修改数组 **nums**
让数组 nums 变成一个“哈希表”:
- 下标
idx对应的元素nums[idx]如果是负数,则说明idx这个数字已经存在; 否则,如果下标
idx对应的元素nums[idx]是正数,则说明idx这个数字不存在class Solution {public:int findDuplicate(vector<int>& nums) {for(int i = 0; i < nums.size(); ++i){int num = abs(nums[i]);// 如果哈希表中 num 这个数已存在,则 num 是重复数,直接返回if(nums[num] < 0)return num;// 如果哈希表中 num 这个数不存在,则插入(将对应的元素置为负数)elsenums[num] = -nums[num];}return -1;}};
复杂度分析:
时间复杂度 O(n)
- 空间复杂度 O(1)
执行结果:
执行结果:通过执行用时:84 ms, 在所有 C++ 提交中击败了 78.48% 的用户内存消耗:59.7 MB, 在所有 C++ 提交中击败了 79.69% 的用户
解法一:快慢指针
参考环形链表寻找入环节点的做法:
[中等] 142. 环形链表 II
对 nums 数组建图,每个位置 i 的 next 节点位置为 nums[i],得到一个环形链表(因为重复数字 target 至少出现两次,因此至少有两个节点都指向下标为 target 的节点,因此图中一定存在环)
入环节点的下标就是重复的数。
class Solution {public:int findDuplicate(vector<int>& nums) {int fast = 0; // 快指针int slow = 0; // 慢指针while(fast != nums.size() && nums[fast] != nums.size()){fast = nums[nums[fast]];slow = nums[slow];if(fast == slow)break;}fast = 0;while(fast != slow){fast = nums[fast];slow = nums[slow];}return fast; // 入环节点的下标就是重复数字}};
复杂度分析:
- 时间复杂度 O(n)
- 空间复杂度 O(1)
执行结果:
执行结果:通过执行用时:80 ms, 在所有 C++ 提交中击败了 87.16% 的用户内存消耗:59.7 MB, 在所有 C++ 提交中击败了 71.85% 的用户
