剑指Offer-数组中只出现一次的数字
题目描述#
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
思路#
思路一:
利用HashSet的元素不能重复,如果有重复的元素,则删除重复元素,如果没有则添加,最后剩下的就是只出现一次的元素
思路二:
用HashMap<K,V>保存数组的值,key为数组值,value为布尔型表示是否有重复
思路三:
两个不相等的元素在位级表示上必定会有一位存在不同。
将数组的所有元素异或得到的结果为不存在重复的两个元素异或的结果。
diff &= -diff 得到出 diff 最右侧不为 0 的位,也就是不存在重复的两个元素在位级表示上最右侧不同的那一位,利用这一位就可以将两个元素区分开来。
代码实现#
package Array;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
/**
* 数组中只出现一次的数字
* 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
* num1,num2分别为长度为1的数组。传出参数
* 将num1[0],num2[0]设置为返回结果
*/
public class Solution37 {
public static void main(String[] args) {
Solution37 solution37 = new Solution37();
int[] array = {1, 2, 2, 3, 4, 4};
int[] num1 = new int[1];
int[] num2 = new int[1];
solution37.FindNumsAppearOnce_3(array, num1, num2);
System.out.println(num1[0] + " " + num2[0]);
}
/**
* 位运算 异或
* 两个不相等的元素在位级表示上必定会有一位存在不同。
*
* @param array
* @param num1
* @param num2
*/
public void FindNumsAppearOnce_3(int[] array, int num1[], int num2[]) {
int diff = 0;
for (int num : array) diff ^= num;
// 得到最右一位
diff &= -diff;
for (int num : array) {
if ((num & diff) == 0) num1[0] ^= num;
else num2[0] ^= num;
}
}
/**
* 用HashMap<K,V>保存数组的值,key为数组值,value为布尔型表示是否有重复
*
* @param array
* @param num1
* @param num2
*/
public void FindNumsAppearOnce_2(int[] array, int num1[], int num2[]) {
HashMap<Integer, Boolean> map = new HashMap<>();
for (int i = 0; i < array.length; i++) {
if (!map.containsKey(array[i])) {
map.put(array[i], true);
} else {
map.put(array[i], false);
}
}
int index = 0;//区分是第几个不重复的值
for (int i = 0; i < array.length; i++) {
if (map.get(array[i])) {
index++;
if (index == 1) {
num1[0] = array[i];
} else {
num2[0] = array[i];
}
}
}
}
/**
* 利用HashSet的元素不能重复,如果有重复的元素,则删除重复元素,如果没有则添加,最后剩下的就是只出现一次的元素
*
* @param array
* @param num1
* @param num2
*/
public void FindNumsAppearOnce(int[] array, int num1[], int num2[]) {
HashSet<Integer> set = new HashSet<>();
for (int i = 0; i < array.length; i++) {
if (!set.add(array[i])) {
set.remove(array[i]);
}
}
Iterator<Integer> iterator = set.iterator();
num1[0] = iterator.next();
num2[0] = iterator.next();
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?