#面试题--找出数组中的唯一值

#面试题 找出数组中的唯一值

数组中仅有一个元素出现了一次, 其他元素均出现了两次, 找出其中的唯一值, 如数组: [3 4 5 2 3 4 5], 2只出现了一次,即要找出2.

解法1(sort):
/**
	 * 算法1 
	 * 1. 先排序
	 * 2. 若a[i+1]!=a[i] (i为偶数)或a[i+1]不存在 则a[i]为唯一元素
	 * 
	 * [3 4 5 2 3 4 5] 
	 * [2 3 3 4 4 5 5] 
	 * a[1]!=a[0] ==> a[0]为唯一元素
	 * 
	 * [3 4 5 2 2 4 5] 
	 * [2 2 3 4 4 5 5] 
	 * a[3]!=a[2] ==> a[2]为唯一元素

	 * [3 4 5 2 2 4 3] 
	 * [2 2 3 3 4 4 5] 
	 * a[7]不存在 ==> a[6]为唯一元素
	 * @param a
	 */
	public static int findUniqueValue1(final int[] a){
		int[] b = a.clone();
		Arrays.sort(b);
		int result = -1;
		for (int i = 0; i < b.length; i+=2) {
			if(i+1==b.length || b[i+1]!=b[i]){
				result = b[i];
				break;
			}
		}
		return result;
	}
 解法2(map):
/**
	 * 算法2
	 * 利用 map<a[i], null> 
	 * 如果key(a[i])已存在 直接删除 若不存在 添加
	 * 最后剩下唯一的key即为所求的唯一元素
	 * @param a
	 */
	public static int findUniqueValue2(final int[] a){
		
		Map<Integer,Integer> map = new HashMap<>();
		for (int i = 0; i < a.length; i++) {
			if(map.containsKey(a[i]))
				map.remove(a[i]); //off
			else
			    map.put(a[i], null); //on
		}
		int result = -1;
		for (Integer key : map.keySet())
			result = key;
		return result;
	}
解法3(位数组):
/**
	 * 算法3
	 * 利用位数组 Bit[] bits
	 * 如果key(a[i])不存在 bits[a[i]]=1 若已存在 bits[a[i]]=0
	 * 最后bits数组中等于1的索引值即为所求值
	 * 如
	 * 数组 a: [3 4 5 2 3 4 5]
	 * 
	 * init bit array: [0 0 0 0 0 0]
	 * [0 0 0 1 0 0]
	 * [0 0 0 1 1 0]
	 * [0 0 0 1 1 1]
	 * [0 0 1 1 1 1]
	 * [0 0 1 0 1 1]
	 * [0 0 1 0 0 1]
	 * [0 0 1 0 0 0]
	 * @param a
	 * @param max 数组中的最大值
	 */
	public static int findUniqueValue3(final int[] a, int max){
		BitSet bitSet = new BitSet(max);
		for (int i = 0; i < a.length; i++){
			bitSet.flip(a[i]);
		}
		int result = -1;
		for (int i = 0; i <= max; i++) {
			if(bitSet.get(i)){
				result = i;
				break;
			}
		}
		return result;
	}
解法4(异或):
/**
	 * 算法4
	 * 利用自己与自己异或为0的特点 如 3 ^ 3 = 0
	 * [3 4 5 2 3 4 5] 
	 * 3^4^5^2^3^4^5=2
	 * @param a
	 */
	public static int findUniqueValue4(final int[] a){
		int t=a[0] ;
		for (int i = 1; i < a.length; i++) 
			t ^= a[i];  
		return t;
	}

 

下面是对上述四种算法的性能比较:


算法1(sort)算法2(map)算法3(bit array)算法4(异或)
135142255
24
2244342571
3135298111
4136168100
513536612
1

注: 数组大小为1,000,001, 一共运行了5次, 在循环内部分别调用上述4个方法,每个调用之间休眠1秒,运行时间单位是毫秒(ms)

解法5(linux uniq):

利用LInux命令, 如下所示:

$ cat uniq_test.txt 
3
4
5
2
3
4
5
$ sort uniq_test.txt | uniq -u
2

同样测试在1,000,001行的文件中寻找唯一值时的花费,

$ cat find_uniq_value_test.txt | wc -l
1000001
$ time sort find_uniq_value_test.txt | uniq -u
1000001

real	0m2.907s
user	0m9.426s
sys	0m0.039s

需要2秒多.

补充:

构造一个满足要求的测试文本的shell命令

$ seq 1 2 10 
1
3
5
7
9
$ seq 1 2 10 > temp.txt
$ seq 1 2 10 >> temp.txt
$ echo 11 >> temp.txt
$ cat temp.txt 
1
3
5
7
9
1
3
5
7
9
11
$ shuf temp.txt
7
3
5
11
1
1
5
9
7
9
3
$ shuf temp.txt > temp_shuf.txt
$ sort -n temp_shuf.txt | uniq -u
11

参考了:

http://x-wei.github.io/%E6%89%93%E4%B9%B1%E6%96%87%E6%9C%AC%E7%9A%84%E8%A1%8C.html














转载于:https://my.oschina.net/zhuguowei/blog/471682

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值