面试题:在一个数组中有0-99之间的整数101个(数组无序),用高效方法找出其中的唯一的重复元素!

/*

* 问题:找出101个数据中重复的元素

* 题目如下:现有0到99,共计100个整数,各不相同,将所有数放入一个数组,随机排布。

*        数组长度101,多余的数字是0到99其中任意一个数(唯一重复的数字)

*        请将这个重复的数字找出来

* 分析:

*    A:把数组构造出来

*    B:把数组元素添加进去

*    C:对数组的元素进去打乱(随机分布)

*    D:找出重复的元素

*/

这道题有三种方式:第一种用交换排序找出,第二种求数组的和再减去0-99,第三种异或运算求出

源代码如下:

package java基础题目;

/*
 * 问题:找出101个数据中重复的元素
 * 题目如下:现有0到99,共计100个整数,各不相同,将所有数放入一个数组,随机排布。
 *        数组长度101,多余的数字是0到99其中任意一个数(唯一重复的数字)
 *        请将这个重复的数字找出来
 * 分析:
 *    A:把数组构造出来
 *    B:把数组元素添加进去
 *    C:对数组的元素进去打乱(随机分布)
 *    D:找出重复的元素
 */
public class A {
	public static void main(String[] args) {
		int key = (int)( Math.random() * 100);// 产生一个0到99之间的数字
		System.out.println("key="+key);//这个随机生成的重复元素[0,99]
		// A:把数组构造出来
		int[] arr = new int[101];
		// B:添加0到99之间的整数元素到数组中
		for (int i = 0; i < arr.length - 1; i++) {
			arr[i] = i;
		}
		arr[100] = key;//最后一个元素赋值为随机生成的那个重复元素key,(特别注意,在后面打乱数组顺序后,那么重复的元素就可能不在最后了)
		System.out.println("数组的原始顺序是:");
		print(arr);

		// 调用打乱数组的方法
		random(arr);
		System.out.println("数组的打乱后顺序是:");
		print(arr);

		method1(arr);
		method2(arr);
		method3(arr);

	}

	// 生成一个随机的0到99之间的数
	public static void random(int[] arr) {
		// C:对数组的元素进去打乱(随机分布)
		// Math类中的public static double random():产生随机数,范围是[0.0,1.0)
		// int num = (int)(Math.random()*101);//num的取值范围是[0,100]
		//利用for循环1000次
		for (int i = 0; i < 1000; i++) {
			int index1 = (int) (Math.random() * 101);//随机生成2个下标,然后把两个下标对应的数组的值交换,重复1000次基本就打乱了数组的值
			int index2 = (int) (Math.random() * 101);
			// 交换元素
			int temp = arr[index1];
			arr[index1] = arr[index2];
			arr[index2] = temp;
		}
	}

	// 输出函数print
	public static void print(int[] arr) {
		int len = 0;
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + "\t");
			len++;
			if (len % 5 == 0) {
				System.out.println();
			}

		}
		System.out.println("\n--------------------------------");
	}

	// 解决方案一:用交换排序找出重复的元素(效率低)
	public static void method1(int[] arr) {
		A: for (int i = 0; i < arr.length - 1; i++) {
			for (int j = i + 1; j < arr.length; j++) {
				if (arr[i] == arr[j]) {
					System.out.println("用交换排序找出的重复元素是:" + arr[i]);
					break A;// break只能跳出当前的一层循环
				}
			}
		}
	}

	// 解决方案二:求数组的和sum再减去0到99,剩下的
	/*
	 * 接下来,我们用一个比较巧合的做法,我们回来看题目: 现有0到99,共计100个数字,并且还有一个重复数据,这个数据也是在0到99之间 思路:
	 * A:我们把整个数组的所有元素的值给累加起来,是不是就是0到99和那个重复元素一起的和?
	 * B:我们拿这个结果减去0-99的和,那么最终结果就是那个重复的元素
	 *
	 * 方式二的弊端是:如果计算的数据特别多,就会有数据溢出,所以不好! 更好的方式是:用异或解决!!!!!!
	 */
	public static void method2(int[] arr) {
		int sum = 0;
		for (int i = 0; i < arr.length; i++) {
			sum += arr[i];
		}
		// 使用sum减去0--99的和,剩下的就是重复的数字
		for (int i = 0; i < arr.length - 1; i++) {
//			sum -= arr[i];//不能这样写,因为数组打乱顺序了,重复元素不一定是最后一个了  比如 12345 3,打乱后 3124 5,最后一个变为5
			sum -= i;
		}
		System.out.println("用求和再减去和的方式找出重复的元素是:" + sum);
	}

	/*
	 * 方式三:异或的一个特点是:x^0^1^2...^99^0^1^2...^99=x
	 * 再看一个式子:0^1^2^...^m...^99^m^0^1^2...^m...^99就等于m,即可找出重复元素的值
	 * 所以,我们使用数组中第一个元素异或后面的所有元素。
	 */
	public static void method3(int[] arr){
		for(int i=1;i<arr.length;i++){
			arr[0] = arr[0]^arr[i];
		}
		//我们再次把arr[0]保存的结果和0,1,2...99的数据异或一次
		for(int i=0;i<arr.length-1;i++){
//			arr[0] = arr[0]^arr[i];//不能这样写,因为数组打乱顺序了,重复元素不一定是最后一个了  比如 12345 3,打乱后 3124 5,最后一个变为5
			arr[0] = arr[0]^i;//注意不是arr[0]^arr[i],数组打乱了顺序
		}
		System.out.println("重复的元素是:"+arr[0]);
	}
}

output:

key=49
数组的原始顺序是:
0	1	2	3	4
5	6	7	8	9
10	11	12	13	14
15	16	17	18	19
20	21	22	23	24
25	26	27	28	29
30	31	32	33	34
35	36	37	38	39
40	41	42	43	44
45	46	47	48	49
50	51	52	53	54
55	56	57	58	59
60	61	62	63	64
65	66	67	68	69
70	71	72	73	74
75	76	77	78	79
80	81	82	83	84
85	86	87	88	89
90	91	92	93	94
95	96	97	98	99
49
--------------------------------
数组的打乱后顺序是:
87	16	35	73	71
31	72	95	11	48
15	57	89	1	33
81	94	54	12	25
91	5	58	90	46
32	40	60	75	52
24	18	83	67	65
97	86	43	93	39
7	3	80	70	20
49	64	78	68	96
98	6	51	29	10
42	99	63	50	21
76	9	41	28	2
30	8	49	13	37
53	36	55	69	82
22	14	44	88	59
19	45	92	27	34
77	56	0	47	79
74	62	26	23	61
66	38	85	84	4
17
--------------------------------
用交换排序找出的重复元素是:49
用求和再减去和的方式找出重复的元素是:49
重复的元素是:49
时间: 2024-10-15 10:30:52

面试题:在一个数组中有0-99之间的整数101个(数组无序),用高效方法找出其中的唯一的重复元素!的相关文章

C++数组中有一个数字出现的次数超过了数组长度的一半,找出这个数字。

#include <iostream> #include <bitset> using namespace std; //数组中超过出现次数超过一半的数字(数组) //题目:数组中有一个数字出现的次数超过了数组长度的一半,找出这个数字. template<int _N> int Grial(bitset<_N> &bt,int a[]) { int check[_N]; for(int i=1;i<=_N;i++) { int count =

找出数组中唯一的重复元素

[问题] 1-1000放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现一次. 每个数组元素只能访问一次,设计一个算法,将它找出来:不用辅助存储空间,能否设计一个算法实现? [代码] #include <stdio.h> #include <stdlib.h> #include <string.h> /*根据异或法的计算方式,每两个相异的数执行异或运算之后,结果为1: 每两个相同的数异或之后,结果为0,任何数与0异或,结果仍为自身. 所以数组a[N]

数组中有一个数字出现的次数超过了数组长度的一半,找出这个数

这个算法的时间复杂度是O(n),另外用了两个辅助变量. k用于临时存储数组中的数据,j用于存储某个数出现的次数. 开始时k存储数组中的第一个数,j为0,如果数组出现的数于k相等,则j加1,否则就减1,如果j为0,就把当前数组中的数赋给k 因为指定的数出现的次数大于数组长度的一半,所有j++与j--相抵消之后,最后j的值是大于等于1的,k中存的那个数就是出现最多的那个数. 下面这个算法只适合数组中数组中某个数的出现次数超过数组长度一半的数组,符合题意. c实现 1 #include<stdio.h

在一个数组里面,除了一个数是只有一个之外,其他都是有两个的,编写一个方法找出这唯一的一个数

1 public class singleNum { 2 /* 3 * 因为a^b^a=b,所以1^2^2^3^3=1 4 * 5 * */ 6 7 public int single(int A[]) 8 { 9 int aim,i; 10 for(aim=0,i=0;i<A.length;i++) 11 { 12 aim=aim^A[i]; 13 } 14 return aim; 15 } 16 17 public static void main(String[] args) 18 { 1

c++ 一个有十个整数元素的数组(17 85 67 83 65 49 26 92 38 42),编写一个程序找出其中的最大数和其下标,并在主函数中打印最大数和相应下标

// 5-1 找数组最大值及下标#include<iostream> using namespace std; int main() { int a[10]={17,85,67,83,49,26,92,38,42}; int max,num=0; max=a[0]; for(int i=0;i<10;i++){ if( a[i]>max){ max=a[i]; num=i; } } cout<<"最大值为:"<<max<<&q

面试题:找出数组中只出现一次的数字(二)

难度:中等 一个整数数组,除了一个数之外所有数字都出现了3次,找出这个数字来. 注意: 你的算法应该是线性运行复杂度,且不能使用额外内存空间. 答案: public class Solution { public int singleNumber(int[] nums) { int ones = 0, twos = 0, threes = 0; for (int i = 0; i < nums.length; i++) { // twos holds the num that appears t

面试题:找出数组中只出现一次的数字

难度:中等 一个整数数组,除了一个数之外所有数字都出现了2次,找出这个数字来. 注意: 你的算法应该是线性运行复杂度,且不能使用额外内存空间. 答案: public class Solution { public int singleNumber(int[] nums) { int n =0; // as we know that bitwise XOR in Java // 0 ^ N = N // N ^ N = 0 for(int i=0; i!=nums.length; i++) { n

找出数组中出现次数超过一半的数字

题目:数组中有一个数字出现的次数超过了数组长度的一半,找出这个数字. 解法1:将数组利用快速排序进行排序,因为数组中有一个数字出现的次数超过了数组长度的一半,则排序以后直接取得最中间的那个数字即可! 时间复杂度为:o(n*logN),因为时间主要花费在快速排序上面了! public static int find1(int[] a) { Arrays.sort(a); int mid = 0 + (a.length - 0) / 2; int result = a[mid]; return re

找出数组a[]中符合a[i]+a[j]=K的数对

1.问题描述 在一个整数数组中,元素都为整数,没有重复数.设计一个算法找出满足两个数的和等于k值得数对.例如a[]={1,3,8,6,4}中两个数的和为7的数对为(1,6)和(3,4). 2. 解决方案 2.1 暴力法 首先先到的可能就是暴力法,暴力没举出所有的数对然后再判对他们的和是否为K,但这种方法的时间复杂度为O(n^2),效率比较低,一般不可取.代码也就不写了.. 2.2 二分法 先对数组进行排序,然后使用二分查找算法,使用两个指针分片指向第一个和最后一个元素,然后从两端同时向中间遍历.