面试题:在一个数组中有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



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绝地反击T

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值