首页 > 其他分享 >《剑指Offer》-3-数组中重复的数字

《剑指Offer》-3-数组中重复的数字

时间:2023-02-06 12:34:28浏览次数:45  
标签:遍历 数字 映射 nums 重复 Offer 数组

我觉得这道题完全可以出难一点,可以返回有哪些数字重复了,分别重复了几次

经评论区提醒,或许考察的是与面试官的沟通能力,对不同解法的衡量取舍:

比如时间优先可以用 set 轻松解决,也只需要一次遍历,如果是进阶要求可以用hashmap记录次数,再遍历map输出

O(1)空间复杂度就原地排序,然后再遍历一遍输出第一个重复的,我第一个想到的是快排,当然也可以直接sort()

《剑指Offer》上给出的巧妙解法是利用数组下标和交换,当然这里的前提是所有数字都在 0~n-1 的范围内

长度为 n 的数组,且所有数字的范围都在 0~n-1范围内,在没有重复的情况下,那么正好可以将每个数字和下标建立映射关系:数字==下标,且正好一一对应
但是,题目中是存在重复数字的,而且不知道有几个数字是重复的,也不知道每个数字重复几次
所以,如果仍旧按照原本的映射关系来看,必然是有位置映射为空,有的位置映射2个或者2个以上

我们这么做:

  1. 遍历整个数组,通过交换位置来将映射关系建立起来,使数字一一归位
  2. 检查 i 与 nums[i],如果相等说明i已经之它应在的位置了
  3. 如果不相等,说明需要移动,再检查 nums[i] 和 nums[nums[i]]
  4. 如果不相等,就交换,将i归位,放到他应该在的地方
  5. 如果相等,说明它应该在的位置已经有元素了,(而且不能是它本身),即:重复了

看起来效果很棒

	int findRepeatNumber(vector<int>& nums) {
		int res = nums[0];
		int i = 0;
		while (i < nums.size()) {
			if (i != nums[i]) {
				if (nums[nums[i]] != nums[i]) {
					swap(nums[i], nums[nums[i]]);
				}
				else {
					res = nums[i];
					break;
				}
			}
			else i++;
		}
		return res;
	}

标签:遍历,数字,映射,nums,重复,Offer,数组
From: https://www.cnblogs.com/yaocy/p/17095012.html

相关文章