/*
* 问题:找出101个数据中重复的元素
* 题目如下:现有0到99,共计100个整数,各不相同,将所有数放入一个数组,随机排布。
* 数组长度101,多余的数字是0到99其中任意一个数(唯一重复的数字)
* 请将这个重复的数字找出来
* 分析:
* A:把数组构造出来
* B:把数组元素添加进去
* C:对数组的元素进去打乱(随机分布)
* D:找出重复的元素
output:
* 问题:找出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