【LeetCode】Single Number

本文介绍了解决数组中寻找唯一单例元素的问题,提供了两种高效算法实现,并进一步探讨了多个单例元素的情况,包括两个单例及在一个元素仅出现一次而其他元素出现k次的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given an array of integers, every element appears twice except for one. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

解法一:

public class Solution {
    public int singleNumber(int[] A) {
        HashSet<Integer> set=new HashSet<Integer>();
        for(int i:A)
        {
        	if(set.contains(i))
        		set.remove(i);
        	else
        		set.add(i);
        		
        }
        Iterator<Integer> itr=set.iterator();
        return itr.next();
    }
}

利用哈希表,如果已经存在就移除,否则加入,最后只剩1个单独存在的元素


解法二:

public class Solution {
    public int singleNumber(int[] A) {
       int a=0;
        for(int i:A)
        	a^=i;
        return a;
    }
}

0异或任何数都是任何数

任何数异或本身都是0

异或存在交换律

所以所有存在偶数个的数异或完结果都为0,剩下的为只出现一次的数

扩展:

1.一个数组中有两个元素只出现一次,其他所有元素都出现两次,求这两个只出现一次的元素

哈希表解法依旧有效,看解法二。

依旧所有元素求异或,其结果为两个只出现一次的元素不同的位为1,相同的位为0

找到某个不同的位flag。

再次遍历,任意元素&flag会分成两个集合,每个集合一个只出现一次的元素。剩下思路同原题。

package SingleNumber;

public class Solution2
{
	public static void singleNumber(int[] A)
	{
		int a = 0;
		for (int i : A)
			a ^= i;
		int flag = 1;
		while ((a & flag) == 0)
			flag <<= 1;
		int result1 = 0;
		int result2 = 0;

		for (int i : A) {
			if ((i & flag) == 0)
				result1 ^= i;
			else
				result2 ^= i;

		}
		System.out.println(result1 + " " + result2);

	}

	public static void main(String[] args)
	{
		int[] a = { 1, 2, 3, 67, 43, 23, 2, 3, 1, 67, 43, 55 };
		singleNumber(a);
	}
}

扩展2:

一个数组中有一个元素只出现1次,其他所有元素都出现k次,求这个只出现1次的元素

(1)K为偶数,解法同原题

(2)K为奇数

将每个数字转化为二进制,每一位相加模上K。再将得到的二进制转为十进制,即为只出现一次的数。(注意不能用十进制,十进制每一位都有可能本身大于3)

public class Solution4
{
	private static int[] res;

	public static int singleNumber(int[] A, int k)
	{
		int m = 0;
		res = new int[100];
		for (int i : A)
			foo(i);
		int j = 1;
		for (int i = 1; i <= res[0]; i++, j <<= 1) {
			m += res[i] % k * j;
		}
		return m;

	}

	public static void foo(int a)
	{
		int i = 1;
		while (a != 0) {
			if ((a & 1) == 1)
				res[i] += 1;
			a >>= 1;
			i++;
		}
		if (res[0] < i - 1)
			res[0] = i - 1;
	}

	public static void main(String[] args)
	{
		int[] a = { 1, 1, 1, 2, 2, 2, 45, 45, 45, 88, 99, 99, 99, 355, 666,
				666, 355, 355, 666 };
		System.out.println(singleNumber(a, 3));

	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值