zoukankan      html  css  js  c++  java
  • 找出数组中的重复元素

    一个大小为n的数组,里面的数都属于范围[0, n-1],有不确定的重复元素,找到至少一个重复元素,要求O(1)空间和O(n)时间。

    这个题目要求用O(n)的时间复杂度,这意味着只能遍历数组 k(有限)次。同时还要寻找重复元素,很容易想到建立哈希表来完成,遍历数组时将每个元素映射到哈希表中,如果哈希表中已经存在这个元素则说明这就是个重复元素。但在空间复杂度上有限制——要求为O(1)的空间。因此采用哈希表这种解法肯定在空间复杂度上是不符合要求的。但可以沿着哈希法的思路继续思考,另辟蹊径。

    方法一

    #include <stdio.h>  
    const int NO_REPEAT_FLAG = -1;
    void Swap(int &x, int &y)
    {
    	int t = x;
    	x = y;
    	y = t;
    }
    
    void PrintfArray(int a[], int n)
    {
    	for (int i = 0; i < n; i++)
    		printf("%d ", a[i]);
    	putchar('
    ');
    }
    
    //类似于基数排序,找出数组中第一个重复元素。  
    int RadixSort(int a[], int n)
    {
    	int num = 0;                    //交换次数
    	int i;
    	for (i = 0; i < n; i++)         //当 i != a[i] 时即交换 a[i] 和 a[a[i]],使得 a[a[i]]=a[i]
    	{                               //最终大部分 a[i] 处的值都等于 i
    		while (i != a[i])          //当 a[i] == a[a[i]] 时,即为重复元素
    		{
    			if (a[i] == a[a[i]])
    				return a[i];
    			Swap(a[i], a[a[i]]);
    			printf("
     i = %d, n = %d,数组为: ", i,++num);
    			PrintfArray(a, n);
    		}
    	}
    	return NO_REPEAT_FLAG;
    }
    
    int main()
    {
    	const int MAXN = 10;
    	int a[MAXN] = { 2, 4, 1, 5, 7, 6, 3, 9, 0, 0 }; 
    
    	printf("数组为: ");
    	PrintfArray(a, MAXN);
    
    	int nRepeatNumber = RadixSort(a, MAXN);
    	if (nRepeatNumber != NO_REPEAT_FLAG)
    		printf("该数组有重复元素,此元素为%d
    ", nRepeatNumber);
    	else
    		printf("该数组没有重复元素
    ");
    	getchar();
    	return 0;
    }
    

    该测试结果为

    数组为: 2 4 1 5 7 6 3 9 0 0

    i = 0, n = 1,数组为: 1 4 2 5 7 6 3 9 0 0

    i = 0, n = 2,数组为: 4 1 2 5 7 6 3 9 0 0

    i = 0, n = 3,数组为: 7 1 2 5 4 6 3 9 0 0

    i = 0, n = 4,数组为: 9 1 2 5 4 6 3 7 0 0

    i = 0, n = 5,数组为: 0 1 2 5 4 6 3 7 0 9

    i = 3, n = 6,数组为: 0 1 2 6 4 5 3 7 0 9

    i = 3, n = 7,数组为: 0 1 2 3 4 5 6 7 0 9

    该数组有重复元素,此元素为 0

    该方法会改变原数组。

    方法二

    设置访问标志,比如 a[1]=5,即 a[5] 已经访问过了,a[5] = a[5] + n,如果是第二次访问该位置就找到了重复值。

    #include <stdio.h>  
    const int NO_REPEAT_FLAG = -1;
    int FindRepeatNumberInArray(int *a, int n)
    {
    	for (int i = 0; i < n; i++)
    	{
    		int nRealIndex = a[i] >= n ? a[i] - n : a[i];
    		if (a[nRealIndex] >= n) //这个位置上的值大于n说明已经是第二次访问这个位置了  
    			return nRealIndex;
    		else
    			a[nRealIndex] += n;
    	}
    	return NO_REPEAT_FLAG; //数组中没有重复的数  
    }
    void PrintfArray(int a[], int n)
    {
    	for (int i = 0; i < n; i++)
    		printf("%d ", a[i]);
    	putchar('
    ');
    }
    int main()
    {
    	const int MAXN = 10;
    	int a[MAXN] = { 2, 4, 1, 5, 7, 6, 3, 9, 0, 0 };
    	printf("数组为: 
    ");
    	PrintfArray(a, MAXN);
    
    	int nRepeatNumber = FindRepeatNumberInArray(a, MAXN);
    	if (nRepeatNumber != NO_REPEAT_FLAG)
    		printf("该数组有重复元素,此元素为%d
    ", nRepeatNumber);
    	else
    		printf("该数组没有重复元素
    ");
    	getchar();
    	return 0;
    }
    
  • 相关阅读:
    C++网易云课堂开发工程师-操作符重载
    C++网易云课堂开发工程师-参数传递与返回值
    C++网易云课堂开发工程师-class的声明
    C++网易云课堂开发工程师-头文件与类声明
    线性代数的本质-08第二部分-以线性代数的眼光看叉积
    线性代数本质-08第一部分-叉积的标准介绍
    线性代数的本质-07-点积与对偶性
    线性代数的本质-06补充说明-非方阵
    线性代数的本质-06-逆矩阵、列空间与零空间
    cocos2d-x
  • 原文地址:https://www.cnblogs.com/P3nguin/p/8650838.html
Copyright © 2011-2022 走看看