剑指offer:数组中重复数字

剑指offer:数组中重复的数字

题目:一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些
数字时重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。
请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},
那么对应输出的重复的数字是2或3。

思路:
1.先将数组进行排序,然后从排序的数组中找出重复的数字。排序:O(nlogn)
2.hash table:从头到尾扫描数组的每个数字,每扫到一个数字,都可以用O(1)
的时间判断hash table中是否有该数字。若hash table中没有,就将其加入,如果
hash table中已经存在该数字,就找到了一个重复的数字。
该算法的时间复杂度是:O(n),但以一个大小为O(n)的hash table为代价
3.从头到尾扫描数组中的每个数字。当扫描到下标为i的数字时,首先比较这个数字
(用m表示)是否等于i。如果时,则接着扫描下一个数字;如果不是,则拿它和第m个数字
进行比较。如果它和第m个数字相等,就找到了一个重复的数字(该数字在下标为i和m的位置都出现)
如果它和第m个数字不相等,就把第i个数字和第m个数字进行交换,把m放到属于它的位置。接下
重复直到发现一个重复的数字。

实现:

注:所有的代码牛客网通过,可以直接提交。希望在本地调试的见:如何进行本地调试

使用插入排序

相应的可以换成时间复杂度更低的快速排序(O(nlogn))

class Solution {
public:
    // Parameters:
    //        numbers:     an array of integers
    //        length:      the length of array numbers
    //        duplication: (Output) the duplicated number in the array number
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    void Insert_sort(int array[], int length){
        for (int i = 0; i < length; i++)
        {
            for (int j = i; j >= 0; j--)
            {
                if (less(array[j], array[j - 1]))
                {
                    exch(&array[j], &array[j - 1]);
                }
            }
        }
        
    }
    void exch(int* a, int* b){
        int temp;
        temp = *a;
        *a = *b;
        *b = temp;
    }
    bool less(int a, int b){
        if (a <= b) return true;
        else return false;
    }
    bool duplicate(int numbers[], int length, int* duplication) {
        if (numbers == NULL)
        {
            return false;
        }
        Insert_sort(numbers, length);
        int candidate = numbers[0];
        for (int i = 1; i < length; i++)
        {
            if (numbers[i] == candidate)
            {
             *duplication = numbers[i];
                return true;
            }
            else 
            {
                candidate = numbers[i];
            }
        }
        return false;
    }
};
指针复习

指针理解
指针没有初始化时,它所指向的内存是不存在的。所以不可以建立指针变量p1而不进行初始化,就直接传入函数duplicate; 或者可以建立 int 型变量 p2,然后直接传入 &p2。

sizeof 函数:sizeof(对象)返回的是对象自身的类型的大小。在这里插入图片描述
要注意数组作为函数的参数进行传递时,会自动退化为对应类型的指针。

使用hash table

public:
    // Parameters:
    //        numbers:     an array of integers
    //        length:      the length of array numbers
    //        duplication: (Output) the duplicated number in the array number
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false	
	bool duplicate(int numbers[], int length, int* duplication) {
		if (numbers == NULL) return false;
	  	int temp[length];
	  	for (int i = 0; i < length; i++){
	   		temp[i] = -1;
	 	 } 
	  	for (int j = 0; j < length; j++)
	  	{
	   		if (temp[numbers[j]] == -1) temp[numbers[j]] = 1;
	   		else 
	  		 {
	    			*duplication = numbers[j];
	   			 return true;
	   		} 
	 	 }
	 	 return false;
	 }
};

使用方法三

class Solution {
public:
    // Parameters:
    //        numbers:     an array of integers
    //        length:      the length of array numbers
    //        duplication: (Output) the duplicated number in the array number
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    
    //采用方法三: 	
 	void exch(int *a, int *b)
 	{
 	 int temp;
 	 temp = *a;
  	 *a = *b;
  	 *b = temp;
 	 }
 	bool duplicate(int numbers[], int length, int* duplication) {
  		if (numbers == NULL) return false;
 		for (int i = 0; i < length; i++)
 		{
  			int m =numbers[i];
  	 		if (i == m) continue;
   			else 
   			{
    				if (numbers[m] == m) 
    				{
     					*duplication = m;
     					return true;
    				}
    				else 
    				{
     					exch(&m, &numbers[m]);
   	 			}
   			}
  		} 
  		return false;
 	}
};

注意:加上额外的判断,因为题目中要求0~n-1,所以不再这个范围的都要返回false。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值