算法——一天一道算法题篇——找只出现一次的两个数

找只出现一次的两个数

题目:

一个整型数组里除了两个数字只出现一次之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

举例说明:

现在有一个数组:{1,3,4,2,4,3};

假设数组元素的规模不是很大,想要找到只出现一次的元素,可以定义一个辅助数组,flag[100];里面存放的是数组元素出现的次数,flag数组的下标表示的是数组:{1,3,4,2,4,3}里的元素。

代码如下:

package hello.ant;

public class AlogArrayFind2 {
	public static void main(String[] args) {
		int array[]={1,3,4,2,4,3};
		int flag[]=new int[100];
		for(int i=0;i<array.length;i++){
			flag[array[i]]++;
		}
		for(int i=0;i<flag.length;i++){
			if(flag[i]==1){
				System.out.print(i+"  ");
			}
		}
	}
}

如果数组元素比较大的话,比如说,{1000,2,2,1000,33,45,}这种方式肯定不好,采用了官方给的提示,利用java中set,用来存放不重复的元素,来解决元素之间相差太大带来的问题:

代码如下:

package hello.ant;

import java.util.HashSet;
import java.util.Set;

//从数组中查找出个数为1的两个数,
public class AlogArrayFind {
	public static void main(String[] args) {
		int array[]={1000,2,2,1000,33,45};
		Set<Integer> set=new HashSet<Integer>();
		for(int i=0;i<array.length;i++){
			int x=set.size();
			set.add(array[i]);
			if(x==set.size()){
//				System.out.println(array[i]);
				set.remove(array[i]);
			}
		}
		System.out.println(set);
	}
}

结果如下:[33, 45]

最好的一种方法如下:


异或运算:任何一个数字异或它自己都等于0。

A.我们将数组中所有的数字异或,所得的结果相当于只出现一次的两个数的异或结果。
B.接着我们考虑,如果能够将原数组分为两个子数组,而且两个只出现一次的数分别在不同的子数组中。那么再分别对子数组异或,就可以得到这两个数。

现在我们考虑A中的结果,由于出现一次的两个数不同,所以它们异或的结果的二进制表示中至少有一位为1。在结果中找出第一个为1的位置,记为n,就可以区分这两个数,因为这两个数的二进制第n位肯定不同。
然后将原数组中的数,按照二进制第n位是否为1可以划分为两个子数组,这样,问题就解决了。

代码大部分是借鉴官方的,还是贴出来吧,对于位运算部分,不得不说,是挺巧妙的。

package hello.ant;
/**
 * @author gejing E-mail:[email protected]
 * @version 创建时间:2014年5月13日 下午8:50:07 类说明 寻找数组中只出现一次的两个数,其他的都出现了两次
 */
public class Code010 {
	public static void main(String[] args) {
		int data[] = { 1,3,1,12,2,2};
		findAppearOnce(data);
	}

	/**
	 * 找出数组中只出现一次的两个数
	 *
	 * @param data
	 */
	private static void findAppearOnce(int[] data) {
		int result = 0;
		int num1 = 0, num2 = 0;
		System.out.println(isFirst1(1, 1));
		// 求出所有数组元素的异或结果
		for (int i = 0; i < data.length; i++) {
			result = data[i] ^ result;
		}
		// 求出结果二进制第一位为1的索引
		String binaryResult = Integer.toBinaryString(result);
		int first1 = binaryResult.indexOf("1");
		System.out.println(first1);
		// 按照该索引将数组分为两个子数组
		for (int i = 0; i < data.length; i++) {
			if (isFirst1(data[i], first1 + 1)) {// 由于数组索引和需要移的位差一位
				num1 = data[i] ^ num1;
			} else {
				num2 = data[i] ^ num2;
			}
		}
		System.out.println(num1 + "   " + num2);

	}

	/**
	 * 判断第index位是否为1
	 *
	 * @param i
	 * @param index
	 * @return
	 */
	private static boolean isFirst1(int i, int index) {
		if (((i >> index) & 1) == 1) {
			return true;
		} else {
			return false;
		}
	}

}

不过我也存在一个疑惑,Integer.toBinaryString(result).indexOf("1"),大部分情况下都为0,而每次i>>index个单位,怎么还能满足要求,由于时间问题,暂时研究到这,记录下来,下次再看。。。

算法——一天一道算法题篇——找只出现一次的两个数,布布扣,bubuko.com

时间: 2024-12-24 11:45:22

算法——一天一道算法题篇——找只出现一次的两个数的相关文章

C语言编程 找出数列中只出现一次的两个数

原题:一个数组中只有两个数字是出现一次,其他所有数字都出现了两次.找出这两个只出现一次的数字,编程实现. 此题要用到在数列中找出只出现一次的一个数字的方法参考https://blog.51cto.com/14232799/2382172 此题明显无法一次性将两个数都找出,所以需要将数列分为两部分,每一部分有一个只出现一次的数,那么此时需要的就是分离数列的条件. 沿用找出一个数时的思想,将数列进行相互异或,但这次所得的值不是只出现一次的那个数了,因为只出现一次的数有两个,所以此次计算得到的是只出现

编程题:指向函数的指针,求两个数中较大的数。

#include<stdio.h> int max(x,y) { int z; if(x>y)  z=x; else  z=y; return z; } void main() { int a,b,c; int (*p)(); p=max; scanf("%d,%d",&a,&b); c=(*p)(a,b); printf("%d,%d,max is %d\n",a,b,c); } 编程题:指向函数的指针,求两个数中较大的数.,布布

C++找数组中只出现一次的两个数并保存(牛客剑指offer)

//////////////////////////////////// //一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. //心得:开始我以为是只出现一次的一个数,题中确是有2个只出现一次的数 //数组从i=0,开始,另一个j=i+1开始,当出现一个相等的我就把它保存在我新建的数组里面b[n/2+1], //当j==n时,说明在i位置之后没有跟a[i]相等的数值了,但是不能保证前面没有, //于是这里我保存在b数组里面的数据就起作用了,再遍历一遍

找出一组数中只出现一次的两个数,其他所有数都是成对出现的

题目: 给一组数,只有两个数只出现了一次,其他所有数都是成对出现的.怎么找出这两个数.编写函数实现. 题目分析: 上次介绍了,对于一组数中只有一个数只出现一次,其他所有数都是成对出现的,我们采用了对全部数组元素进行异或,但是对于找出两个出现一次的数应该怎么解决呢?先对所有的元素进行异或,则结果为两个出现一次的数的异或结果,然后将结果转换为二进制,找出二进制数中的第一个1,然后根据这个1的判断条件进行分组,分为两组,分别对两个组的元素进行全部异或,则就找出两个不同的数. 例如:数组中的元素为下面这

找出1-100中缺失的两个数

题目:有一个数组 int array[100]:本来应该存放的数为1~100,但是有两个数据a,b丢失了,值变成了0.问如何找出丢失的那两个数?附带条件不能开辟额外的空间. 解题思路:常见的两种解法有:1.计算a+b和a*b的值,然后在解方程求解(但是这样会使得中间某个变量过大).2.使用bit位来标记.占用13个字节.第二种方法使用了额外空间,第一种可能会造成整型溢出.这里考虑转化为熟悉的方法.数组array[100],其下标正好为0-99,能不能利用上数组下标求解呢?答案是肯定的.这里将数组

字节算法面试的一道DP题

题目:青蛙跳台阶吃虫子,数组arr代表每个台阶有多少个虫子,要求青蛙每次最多跳k个台阶,最多一共跳n次,计算青蛙最多能吃到多少个虫子? 例:arr=[8 10 9 7 17 13]  k=2 n=3 max=10+7+17=34 def mostinsects(arr,k,n): #arr 台阶数组 #k 每次最多可以跳的台阶数 #n 最多可以跳的次数 #转移方程 DP[i][j] 代表在第i个台阶跳了j次后能吃到的最多虫子 #DP[i][j]=max(DP[i-1][j-1],DP[i-2][

在数组中找出只出现一次的两个数

来来来,看一道面试题!!! 题目是这样叙述的: 在一个数组中除两个数字只出现1次外,其它数字都出现了2次, 要求尽快找出这两个数字. 要求:时间复杂度为O(N),空间复杂度为O(1). 这该怎么解决呢??? 请看我的分析: 将这道题简单化: 一个数组中只有一个数字出现一次,其他数字都是成对出现的,这时我们可以根据异或运算符的特性:A^B^A = B; 0 ^ A = A:我们可以将这个数组的全部元素依次做异或运算,最终结果就是那个只出现一次的数字. 如果这个数组中出现两个不同的数字,而其他数字均

认真对待每一道算法题 之 找明星问题 - 淘宇瀚

n个人中只有一个明星,明星不认识其他所有的人,而其他人都认识明星,不是明星的人可能认识也可能不认识.你每次只可以问一个人是否认识另一个人这样的问题,问最少问多少次可以找出明星. 做法1: 将所有人站队,按照顺序(假如编号分别为1.2.3..n),首先问1,2互相认识,有四种情况出现: (1)1 认识 2,2不认识1, 认识别人的肯定不是明星,排除1: (2)1 不认识2,2认识1, 根据(1)的道理,同样可以排除2: (3)1与2 互相认识,可以断定,两个人都不是明星,随机删除一个就好: (4)

一天一道算法题---6.26---二分查找

感谢微信平台---一天一道算法题----每天多一点进步-- 好累啊  现在在用win7自带的输入法 打起来真麻烦 快点把这2天的搞完就重装了 还是直接来源于----〉 待字闺中 分析 给定一个数组A,其中有一个位置被称为Magic Index,含义是:如果i是Magic Index,则A[i] = i.假设A中的元素递增有序.且不重复,请给出方法,找到这个Magic Index.更进一步,当A中允许有重复的元素,该怎么办呢? 没有重复元素的情况 一些同学在遇到这个题目的时候,往往会觉得比较简单.