欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

给出2n+1(2n+2)个数,其中有n个数是成对出现的,找出只出现一次的一个数/两个数

程序员文章站 2024-03-16 18:50:22
...

1 给出2n+1个数,其中有n个数是成对出现的,让我找出里面只出现了一次的那个数。
2 。给出2n+2个数,其中有n个数是成对出现的,让我找出里面只出现了一次的那两个数。
对于第一个问题我们用位运算来解决中的异或运算,注意异或运算的运算法则:相同为0,不同为本身
给出2n+1(2n+2)个数,其中有n个数是成对出现的,找出只出现一次的一个数/两个数
代码如下:

package yihuo;

public class yihuo {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int personal=0;
		int personal1=0;
		int a[]= {1,2,8,9,7,4,3,2,4,7,3,8,9,1,12};
		for(int i=0;i<a.length;i++) {
			personal=a[i]^personal;
		}
		System.out.println("出现了奇数次的那一个数 personal="+personal);
	}

}

运行截图:
给出2n+1(2n+2)个数,其中有n个数是成对出现的,找出只出现一次的一个数/两个数
2 。给出2n+2个数,其中有n个数是成对出现的,让我找出里面只出现了一次的那两个数。
解题思路:因为是偶数个不同(以),所以异或运算之后得到的是两个不同元素的异或运算值,得不到想要的。但是如果我们把这一组数据分为两组,每一组分担一个不同的,分组异或运算之后,每一组就会把那个单一元素给找出来。
i.困难:在不知道的情况下,如何将N+2个数据划分为我们想要的两组。
ii.解决方法:将N+2个数据异或之后,将会得到我们想要的那两个值的异或值,得到的这个异或值,它的二进制中肯定有至少一位是1(因为不同),这里我们取最高位是1的那一位,将所有数据中对应位按照该位置上是0和1分开,分成两组,然后分组异或,将会得到两个值,就是我们想要的结果了。
如何得到异或值的二进制最高一位为1的位置呢,我用向左移动来实现。肯定有一个1,所以最坏情况是移动到最后成10000000,跳出循环。
for(;p<127;) {//一直向左移动,找到personal1刚开始为1的位置也就是两个数不同的位置。 p=p<<1; youyicount++; }

每次记录向左移动次数,然后 location=8-youyicount;来得到那个位置。
为了在location位置上将所有数据分成两组,我想到0&n(任何数)都为0,1&n(n是1则1,n是0则0),所以将每个值和2的location-1次方做与运算,如果结果为零,说明该数据的二进制在location位置上为0,否则为1。根据0还是1得到两组
代码如下:

for(int i=0,j=0,m=0;i<b.length;i++) {
			int t=b[i]&loc;
			if(t==0) {
				List1.add(b[i]);//两个唯一的数,在第Location位置上不同,所以按照Location位置
//				                                              上0或1分为两组,可以将两个唯一值分开,分开后,按照上面的方法分别求即可
			}else {
				List2.add(b[i]);
			}
		}

得到两组后,就回到第一个问题了,想了好久,觉得可以,点赞支持一下哦

完整代码如下:
package yihuo;

import java.util.ArrayList;

public class yihuo {
	
//	给你n个数,其中有且仅有一个数出现了奇数次,其余的数都出现了偶数次。
//	用线性时间常数空间找出出现了奇数次的那一个数。
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int personal1=0;
		int location=0;
		int loc;
		int one=0;
		int two=0;
		int youyicount=0;
		int b[]= {1,2,8,9,7,4,2,4,7,3,8,1,12,10,12,10,28,20,28,20};
		ArrayList List1 = new ArrayList(); 
		ArrayList List2 = new ArrayList(); 
		for(int i=0;i<b.length;i++) {
			personal1=b[i]^personal1;
		}
		System.out.println("将N+2N个数异或计算得到personal1="+personal1);
		int p=personal1;
		for(;p<127;) {//一直向左移动,找到personal1刚开始为1的位置也就是两个数不同的位置。
			p=p<<1;
			youyicount++;
		}
		location=8-youyicount;//位置
		System.out.println("两个唯一值二进制不同的位置为 location="+location);
		loc=(int) Math.pow(2,location-1);//根据得到的位置,获取需要的值
		System.out.println("根据location得到关键值 loc="+loc);
		for(int i=0,j=0,m=0;i<b.length;i++) {
			int t=b[i]&loc;
			if(t==0) {
				List1.add(b[i]);//两个唯一的数,在第Location位置上不同,所以按照Location位置
//				                                              上0或1分为两组,可以将两个唯一值分开,分开后,按照上面的方法分别求即可
			}else {
				List2.add(b[i]);
			}
		}
		for(int i=0;i<List1.size();i++) {
			int num=(int) List1.get(i);
			one=(int)List1.get(i)^one;
		}
		for(int i=0;i<List2.size();i++) {
			two=(int)List2.get(i)^two;
		}
		
		
		System.out.println("出现了奇数次的那一个数 one="+one);
		System.out.println("出现了奇数次的那一个数 two="+two);
	}

}


结果如图:
给出2n+1(2n+2)个数,其中有n个数是成对出现的,找出只出现一次的一个数/两个数
给出2n+1(2n+2)个数,其中有n个数是成对出现的,找出只出现一次的一个数/两个数