本文主要是介绍LeetCode 442. 数组中重复的数据(原地改变),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
给定一个整数数组 a,其中1 ≤ a[i] ≤ n (n为数组长度), 其中有些元素出现两次而其他元素出现一次。
找到所有出现两次的元素。
你可以不用到任何额外空间并在O(n)时间复杂度内解决这个问题吗?
示例:
输入:
[4,3,2,7,8,2,3,1]
输出:
[2,3]
思路:
条件非常苛刻,要保证O(n)和无额外空间,因此只能想到利用数组本身的空间。注意到 1 ≤ a [ i ] ≤ n 1≤a[i]≤n 1≤a[i]≤n,这就是个突破口
- 首先默认下标为0,所以将所有数字减一。将每个数字对应自己位置上数加上 n n n,数字mod n得到的就是原始数。重复数字对应位置上的数肯定大于等于 2 ∗ n 2*n 2∗n。
class Solution {
public:vector<int> findDuplicates(vector<int>& nums) {int n = nums.size();vector<int>ans;for(int i = 0;i < n;i++) nums[i]--;for(int i = 0;i < n;i++) {nums[nums[i] % n] += n;if(nums[nums[i] % n] >= 2 * n) {ans.push_back(nums[i] % n + 1);}}return ans;}
};
- 交换下标法,一直交换 n u m s [ i ] nums[i] nums[i]和 n u m s [ n u m s [ i ] ] nums[nums[i]] nums[nums[i]]的值,相当于把每个数字归位。直到 i = n u m s [ i ] i=nums[i] i=nums[i]或者 n u m s [ i ] = n u m s [ n u m s [ i ] ] nums[i]=nums[nums[i]] nums[i]=nums[nums[i]]。这样重复的数会出现在这个数字对应的下标位置和另一个位置,for一遍就可以得到答案。由于每个数字归位只需要一次,所以复杂度是 O ( n ) O(n) O(n)。
class Solution {
public:vector<int> findDuplicates(vector<int>& nums) {int n = nums.size();vector<int>ans;for(int i = 0;i < n;i++) nums[i]--;for(int i = 0;i < n;i++) {while(i != nums[i] && nums[i] != nums[nums[i]]) {swap(nums[i], nums[nums[i]]);}}for(int i = 0;i < n;i++) {if(i != nums[i] && nums[i] == nums[nums[i]]) {ans.push_back(nums[i] + 1);}}return ans;}
};
这篇关于LeetCode 442. 数组中重复的数据(原地改变)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!