牛客 —两个数出现了奇数次

俩个数出现了奇数次

上一篇博客一个数出现了奇数次

牛客网链接

题的内容:给定一个数组arr,其中只有两个数字出现了奇数次,其它数字都出现了偶数次,按照从小到大顺序输出这两个数。

输入描述:

第一行输入一个n,
第二行输入n个数

输出描述

输出出现奇数次的两个数,按照从小到大的顺序。

示例1

输入:
4
1 1 2 3
输出:
2 3

示例2

输入:
6
11 22 11 23 23 45
输出:
22 45

代码实现

方法一:采用的是HashSet
思路:直接遍历数组,将值加入到HashSet当中,如果第一次加入,set当中还没有值,就直接加入,当第二次进来的时候,将第一次进来的直接踢出去,这样循环完成之后,set当中只剩下了需要的结果。

import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scan = new Scanner(System.in);
        while (scan.hasNext()){
    
    
            //用set实现,找出出现次数为奇数次的那俩个数字
            Set<Integer> set = new HashSet<>();
            int n = scan.nextInt();
            int[] arr = new int[n];
            for (int i = 0;i < n;i++){
    
    
                arr[i] = scan.nextInt();
                if (!set.contains(arr[i])){
    
    
                    set.add(arr[i]);
                }else{
    
    //如果存在把之前加进来的踢出去,因为它出现了奇数次,就和最后的结果没有什么关系了
                    set.remove(arr[i]);
                }
            }
            //到达这里,set里面就只剩下俩个出现奇数次的数字了
            //得到这俩个数字
            //第一种获取值的方法
            int[] res = new int[2];
            int k = 0;
            for (int i = 0;i < n;i++){
    
    
                if (set.contains(arr[i])){
    
    
                    set.remove(arr[i]);
                    res[k++] = arr[i];
                    if (k == 2)break;
                }
            }
			//第二种获取值的方法,采用迭代器
            /*int[] res = new int[2];
            int k = 0;
            Iterator<Integer> it = set.iterator();
            while (it.hasNext()){
                res[k++] = it.next();
            }*/
            if(res[0] < res[1]){
    
    
                System.out.println(res[0]+" "+res[1]);
            }else{
    
    
                System.out.println(res[1]+" "+res[0]);
            }
        }
    }
}

方法二:采用位运算的方法
思路:首先之前的数组中只有一个出现奇数次的数字,采用的是异或的方法(具体方法,看我上一篇博客,上面有链接),同样俩个奇数次也可以异或,如果想办法可以将这俩个数分到俩个组里面,是不是这样一组里面就有一个数字,就跟之前的做法一致了。
因此最主要的是如何分组:分组,肯定是要找不同之处,首先我们同样遍历数组进行异或,最后面得到的结果是那俩个数字的异或结果,比如这俩个数字是3和5,他们的二进制是011和101,那么它俩异或的结果是010,那么观察3和5的二进制,那么它俩倒数第二位一个是0一个是1,他们异或的结果正好这个不同的位置是1,因此我们只有确定这个1的位置,就可以进行分组了,接下来看代码,代码中注解和详细。

import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scan = new Scanner(System.in);
        while (scan.hasNext()){
    
    
            int n = scan.nextInt();
            int[] arr = new int[n];
            //用于存储2个出现奇数次的整数
            int result[] = new int[2];
            //1.第1次进行整体异或运算
            int res = 0;
            for (int i = 0;i < n;i++){
    
    
                arr[i] = scan.nextInt();
                res ^= arr[i];
            }
//            //如果进行异或运算的结果为0,则说明输入的数组不符合题目要求
//            if (res == 0){
    
    
//                return null;
//            }
            //2.确定2个整数的不同位,以此来作为分组依据
            int separator = 1;
            while ((res & separator) == 0){
    
    
                separator <<= 1;//进行左移
            }
            //3.第二次分组进行异或运算
            for (int i = 0;i < arr.length;i++){
    
    
                if ((arr[i] & separator) == 0){
    
    
                    result[0] ^= arr[i];
                }else{
    
    
                    result[1] ^= arr[i];
                }
            }
            if(result[0] < result[1]){
    
    
                System.out.println(result[0]+" "+result[1]);
            }else{
    
    
                System.out.println(result[1]+" "+result[0]);
            }
        }
    }
}


猜你喜欢

转载自blog.csdn.net/qq_45665172/article/details/113701541
今日推荐