1.找出数组中重复的数字
题目描述:在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3。
思路1:把数组进行排序,然后比对。改变了数组结构。
public static ArrayList<Integer> findRepeatNumber(int[] arr){
ArrayList<Integer> res=new ArrayList<>();
if(arr==null||arr.length==0){
return res;
}
Arrays.sort(arr);
for(int i=1;i<arr.length;i++){
if(arr[i-1]!=arr[i]){
continue;
}else{
res.add(arr[i]);
}
}
return res;
}
思路2:使用hashmap,遍历挨个存进去,如果hashmap里面有了,那就找到了一个重复数字。但是要借助额外辅助空间。
思路3:因为题目说都是0~n-1范围内的,所以如果排序好的话,元素i应该在位置i,所以对于每一个元素,如果元素==位置,那么看下一个,如果不等于的话,就拿它和第i个元素进行比较,如果相等,那么就找到了一个重复数字,如果不想等,那么交换,让元素i去它该在的位置。这种方法也修改了数组。
public static int findRepeatNumber2(int[] arr){
if(arr==null||arr.length==0){
return -1;
}
for(int i=0;i<arr.length;i++){
if(arr[i]==i){
continue;
}
while(arr[i]!=i){
if(arr[i]==arr[arr[i]]){
return arr[i];
}
swap(arr,i,arr[i]);
}
}
return -1;
}
private static void swap(int[] arr, int i, int j) {
int tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
思路4:要求不修改数组,也不能用额外辅助空间。类似二分查找,统计数字范围在数组中出现的次数,比如数字1-n如果在数组中出现的次数超过n,那么一定有重复数字,不断缩小范围。
2.数组中只出现一次的数
题目描述:一个整型数组里除了两个数字之外,其他的数字都出现了偶数次。请写程序找出这两个只出现一次的数字。
思路:使用异或思想。异或运算的性质是,任何一个数字与它自己异或都是0.如果从头到尾异或数组中的每一个数字,那么最终结果就是只出现一次的两个数字异或结果,而且因为这两个数不一样,所以它的异或结果肯定不为0,肯定有一位是1,我们找到第一位是1的位置,根据这一位是不是1把数组分为两个数组,这样就会把两个只出现一次的数字分到了两个数组里面。再对两个数组分别异或,就可以得到只出现一次的数字。
import java.util.ArrayList;
//1到n
public class 数组中只出现一次的数 {
public static ArrayList<Integer> findNumInArr(int[] arr){
ArrayList<Integer> res=new ArrayList<>();
if(arr==null||arr.length==0){
return res;
}
int xorres=0;
for(int i=0;i<arr.length;i++){
xorres^=arr[i];
}
//找到xorres第一个为1的位数
int index=findFirst1(xorres);
ArrayList<Integer> arr1=new ArrayList<>();
ArrayList<Integer> arr2=new ArrayList<>();
for(int i=0;i<arr.length;i++){
if(isBit1(arr[i],index)){ //如果第index位是1,那么就存到num1里面,如果第index位不是1,就存到num2里面
arr1.add(arr[i]);
}else{
arr2.add(arr[i]);
}
}
int rnum1=0;
int rnum2=0;
for(int i=0;i<arr1.size();i++){
rnum1^=arr1.get(i);
}
for(int i=0;i<arr2.size();i++){
rnum2^=arr2.get(i);
}
res.add(rnum1);
res.add(rnum2);
System.out.println(rnum1+" "+rnum2);
return res;
}
private static boolean isBit1(int i, int index) {
for(int j=0;j<index;j++){
i=i>>1;
}
if((i&1)==1){
return true;
}
return false;
}
private static int findFirst1(int xorres) {
int indexbit=0;
while((xorres&1)==0&&indexbit<8){
xorres=xorres>>1;
indexbit++;
}
return indexbit;
}
public static void main(String[] args){
int[] arr={2,4,3,6,3,2,5,5};
findNumInArr(arr);
}
}