上一目录:算法很美
1. 题目:
1-1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素值重复,其他均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;你能否设计一个算法实现?
2. 异或思路:
-
异或的基本公式是A^A=0, A ^ 0 = A, 所以 A ^ A ^ A = A,这样继续类推, A ^ A ^ B ^ B ^ B ^ C ^ C=B。
-
解题思路如下:
这1001个元素有999个是不重复的,把他们假设是A组元素,也就是说A组中元素只出现了1次,只有一个B元素出现了两次,那么我们可以使用1000个不重复的元素对1001个元素,包括A和B组元素进行异或运算,最终使得每一个A元素的数量是2,每一个B元素的数量是3,这样根据1中的规律,最终我们得到的是B元素的值,也就是我们需要寻找的重复元素 -
代码如下:
package com.example.algorithm.demo.c2;
import java.util.Random;
/**
* 找出唯一成对的数
*/
public class c21 {
public static void main(String[]args){
//第一步,构造符合条件的数组,即A+B=N,其中B=2,A=N-2,且存在1到N-1个不重复元素
//小数验证运算
int N = 1001;
//放在N位数的数组中
int[] arr = new int[N];
//先把1到N-1填充到前N个数组元素中
for(int i = 0; i < arr.length-1; i ++){
arr[i] = i+1;
}
//最后一个数是随机数,范围是在[1,N-1]之间
//nextInt()返回的是[0,N)之间的整数,加一后返回[1,N)之间的整数
arr[arr.length-1]=new Random().nextInt(N-1)+1;
//进行异或运算得到最终的B值
//首先对数组arr中的N个元素进行异或运算
int x1 = 0;
for(int i = 0; i < arr.length; i ++){
x1=(x1^arr[i]);
}
//在将得到的异或式x1与1到N-1个元素的异或结果继续异或
for(int i = 1; i < N; i ++){
x1=(x1^i);
}
//输出重复的值
System.out.println("重复的值:"+arr[arr.length-1]);
//最后输出得到的结果,也就是B的值
System.out.println("B:"+x1);
}
}
3. 暴力解决思路(使用辅助存储空间)
- 假设数组arr符合题目要求的构造条件,我们设计另一个辅助数组helper,对arr数组进行遍历,每次循环对helper[arr[i]]做加一操作,那么最后下标是A组元素的helper数组的值都是1,下标B元素的helper数组的值是2,所以只需加一个判断条件,得到值大于1的helper数组元素,输出这个元素下标,也就是B元素
- 代码如下:
package com.example.algorithm.demo.c2;
import java.util.Random;
/**
* 找出唯一成对的数
*/
public class c21 {
public static void main(String[]args){
//第一步,构造符合条件的数组,即A+B=N,其中B=2,A=N-2,且存在1到N-1个不重复元素
//小数验证运算
int N = 1001;
//放在N位数的数组中
int[] arr = new int[N];
//先把1到N-1填充到前N个数组元素中
for(int i = 0; i < arr.length-1; i ++){
arr[i] = i+1;
}
//最后一个数是随机数,范围是在[1,N-1]之间
//nextInt()返回的是[0,N)之间的整数,加一后返回[1,N)之间的整数
arr[arr.length-1]=new Random().nextInt(N-1)+1;
//进行异或运算得到最终的B值
//首先对数组arr中的N个元素进行异或运算
int x1 = 0;
for(int i = 0; i < arr.length; i ++){
x1=(x1^arr[i]);
}
//在将得到的异或式x1与1到N-1个元素的异或结果继续异或
for(int i = 1; i < N; i ++){
x1=(x1^i);
}
System.out.println("===============异或破解=====");
//输出重复的值
System.out.println("重复的值:"+arr[arr.length-1]);
//最后输出得到的结果,也就是B的值
System.out.println("异或破解B:"+x1);
System.out.println("===============暴力破解=====");
//创建辅助数组,因为按照思路,下标最大是N-1,所以长度是N刚刚好
int[] helper = new int[N];
//遍历赋值得出B元素
for (int i = 0; i < N; i ++){
helper[arr[i]] ++;
if (helper[arr[i]] > 1 ){
System.out.println("暴力破解B:"+arr[i]);
break;
}
}
}
}
感觉真不错,脑子还是可以的