Leet-Code 剑指 Offer 03. 数组中重复的数字

找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

原题:
数组中的重复数字
或直转到:
https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/

我的题解:

int findRepeatNumber(int* nums, int numsSize){
	
	int mynums[numsSize];
	int i,j;
	for(i=0;i<numsSize;i++){
		mynums[i]=0;
	}
	for(i=0;i<numsSize;i++){
		mynums[nums[i]]++;
	}//for
	for(j=0;j<numsSize;j++){
		if(mynums[j]>1){
			break;
		}
	}
	//以下代码块为耻辱代码块
    /*int i,j;
    int temp=*nums;
    int repeatNum;
	if(numsSize<50000){
		for(i=0;i<numsSize;i++){
			for(j=0;j<numsSize-i;j++){
				if(*(nums+i)>*(nums+j)){
					temp=*(nums+i);
					*(nums+i)=*(nums+j);
					*(nums+j)=temp;
				}
			}
		} 
	}
	for(i=0;i<numsSize;i++){
		if(*(nums+i)!=i){
			repeatNum=*(nums+i);
		}
	}
	*/ 
	
	return j;
}//Func_findRepeatNumber

真是一道看似简答实则暗藏杀鸡的题

  • 我原来的想法:
    100000个数字,咱cpu不至于这么拉吧。我先来一个泡沫排序,然后相邻比较,perfect。结果超时,沃日。前方泡沫排序时间复杂度太高了,就算相邻比较消耗不了 多少,整体还是超时了。那我就思考怎样在这种情况下不超时呢?我先尝试了前五万用泡沫排序后五万直接比较,后全部用比较,真是纯纯的傻,时间复杂度和泡沫排序一个样。我真的傻了,想不出来怎么写。

  • 偷窥了一下别的大佬想法
    先创建一个数组,全部以0初始化,遍历一般原来存储数字的数组。由于题干给出限定项,数组的大小同时也限制了数组元素的大小。我们可以把原来数组中的元素当做新创建数组的角标,要是有对应角标,则进行++,最后检查超过1的数组内空间,由于数组是线性的,肯定也是哪个最靠近num[0]哪个就return。时间复杂度为n,太妙了。不需要进行排序,这个好像和字典好像,真后悔当初没好好学C#,直接上手了unity
    好兄弟,要回宿舍了,教学楼要关门了,等我躺床山再补一个别的大神思路。22:31

  • 大佬码中我想不到的hash

int findRepeatNumber(int* nums, int numsSize){
    int *hash = (int *)calloc(numsSize, sizeof(int));
    for(int i = 0; i < numsSize; i++){
        if(hash[nums[i]] == 1){
            return nums[i];
        } else {
            hash[nums[i]]++;
        }
    }
    return -1;
}
我发现整体思路和上一个一样,不一样的是这个调用了动态内存管理而不是直接创建同大小数组。根据calloc特性可以知道创建后数组内都要进行初始化。整型数组初始化结果为0.
也就是说同样创建了一个大小为numsSize的数组,思路是一样的,就是创建数组的方式不一样。可见我写的程序就是利用创建数组实现了哈希表,这个则是直接利用calloc进行创建。
其实还有一个好处,就是如果题例若没有出现重复项这个直接就可以判断,而我写的方法还要加一段代码。
坏处就是貌似malloc的内存消耗比较大,只是代码量小罢了,也不失一种方法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
探险家小扣的行动轨迹,都将保存在记录仪。expeditions[i] 表示小扣第 i 次探险记录,用一个字符串数组表示。其的每个「营地」由大小写字母组成,通过子串 -> 连接。例:"Leet->code->Campsite",表示到访了 "Leet"、"code"、"Campsite" 三个营地。expeditions[0] 包含了初始小扣已知的所有营地;对于之后的第 i 次探险(即 expeditions[i] 且 i > 0),如果记录包含了之前均没出现的营地,则表示小扣 新发现 的营地。 请你找出小扣发现新营地最多且索引最小的那次探险,并返回对应的记录索引。如果所有探险记录都没有发现新的营地,返回 -1。注意: 大小写不同的营地视为不同的营地; 营地的名称长度均大于 0。用python实现。给你几个例子:示例 1: 输入:expeditions = ["leet->code","leet->code->Campsite->Leet","leet->code->leet->courier"] 输出:1 解释: 初始已知的所有营地为 "leet" 和 "code" 第 1 次,到访了 "leet"、"code"、"Campsite"、"Leet",新发现营地 2 处:"Campsite"、"Leet" 第 2 次,到访了 "leet"、"code"、"courier",新发现营地 1 处:"courier" 第 1 次探险发现的新营地数量最多,因此返回 1。示例 2: 输入:expeditions = ["Alice->Dex","","Dex"] 输出:-1 解释: 初始已知的所有营地为 "Alice" 和 "Dex" 第 1 次,未到访任何营地; 第 2 次,到访了 "Dex",未新发现营地; 因为两次探险均未发现新的营地,返回 -1
04-23

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值