剑指Offer03.数组中重复的数字

数组中重复的数字


题目链接: 数组中重复的数字

有关题目

找出数组中重复的数字。

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

输入:
[2, 3, 1, 0, 2, 5, 3]
输出:23 
限制:
2 <= n <= 100000

题解

法一:冒泡排序(注:超时)

void My_Bubble (int* nums,int numsSize)
{
   
    for (int i = 0; i < numsSize - 1; i++)
    {
        for (int j = 0; j < numsSize - 1 - i; j++)
        {
            if (nums[j] > nums[j + 1])
            {
                int tmp = nums[j + 1];
                nums[j + 1] = nums[j];
                nums[j] = tmp;
            }
        }
    }
}
int findRepeatNumber(int *nums, int numsSize)
{
	My_Bubble(nums,numsSize);
	for (int i = 0; i < numsSize - 1; i++)
	{
		if(nums[i] == nums [i + 1])
			return nums[i];
	}
    return -1;
}

法二:额外空间

int findRepeatNumber(int *nums, int numsSize)
{
//当然你也可以
//char *tmp = (char*)calloc(numsSize, sizeof(char));
//calloc的作用之一就是初始化字符为0
	char Tem[numsSize];
	Tem = memset ( Tem, 0 , numsSize * sizeof(char))
	for (int i = 0; i < numsSize; i++)
	{
	//根据优先级也可以 if(++count[nums[i]] >= 1)
	//return nums[i];
		if (Tem[nums[i]] == 1)
			return nums[i];
		else
			Tem[nums[i]] = 1;
	}
	return -1;
}

在这里插入图片描述
时间复杂度为O(n)
空间复杂度为O(n)
法三:哈希表

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        unordered_map<int, bool> mp;
        for (auto& num : nums){
            if (mp[num]) return num;
            mp[num] = true;
        }
        return -1;
    }
};

法四:原地置换
代码一:

int findRepeatNumber(int* nums, int numsSize){
    for (int i = 0; i < numsSize; i++)
    {//2 1 3 1
    //2 1 -1 1
    //2 -3 -1 1
    //2 -3 -1 -3
        int k = nums[i];
        if (k < 0) k += numsSize;//由于题干给我们nums中所有的元素都在
        //0 ~ n - 1 范围内
       //在下面的减等操作里里面,再进行标记,找到负数,若出现两次则返回。
        if (nums[k] < 0) return k;
        nums[k] -= numsSize;
    }
    return -1;
}

时间复杂度为O(n)
空间复杂度为O(1)
在这里插入图片描述
代码二:

思路:
结合数组中元素的范围为0 ~ n - 1,再加上有重复的元素,故存在
下标 i 对应多个值 ,即nums[i] = i, 
一次遍历中,第一次遇到数字 x 时,将其交换至索引 x 处;
而当第二次遇到数字 x 时,一定有 nums[x]=x ,
此时即可得到一组重复数字。
void swap(int* a, int* b){
    int x = *a;
    *a = *b, *b = x;
}

int findRepeatNumber(int* nums, int n){
    for (int i = 0; i < n; i++){
        while(nums[i] != i){
            if (nums[nums[i]] == nums[i]){
                return nums[i];
            } 
            else {
                swap(&nums[nums[i]], &nums[i]);
            }
        }
    }
    return -1;
}

代码三:

void swap(int* a, int* b){
    int x = *a;
    *a = *b, *b = x;
}

int findRepeatNumber(int* nums, int n){
    int i = 0;
    while(i < n){
        if (nums[i] == i){
            ++i;
            continue;
        }
        if (nums[nums[i]] == nums[i]) return nums[i];
        swap(&nums[nums[i]], &nums[i]);
    }
    return -1;
}

时间复杂度为O(n)
空间复杂度为O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值