zoukankan      html  css  js  c++  java
  • [剑指Offer]56-数组中数字出现的次数(位运算)

    题目一 数组中只出现一次的数字

    题目

    一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字

    题解

    • 异或。
    • 先考虑:数组中只有一个数字只出现了一次,其他数字都出现了两次,怎么找出这个数字?全部异或,结果即为所求数字。
    • 那么,原问题可以将原数组分成两个集合,两个集合都满足上面的题目,则可求出两个出现一次的数字,那么分组方法?分组:将所有数都做异或,一定至少有一位是1,因为存在两个不相同数字。先找出这一位,然后按这一位是0/1分为两组,两组自然就满足了上面的要求,可求的结果。
    • 综上,步骤一:分组,步骤二:全部异或求得数字。

    相关

    • 异或运算可初始化为0,因为0与任何数异或都是它本身。
    • 找到最后一个1:num&(~num+1)

    代码

    public class Main {
    	public static void main(String[] args) {
    		int[] arr= {2,4,3,6,3,2,5,5};
    		int[] num1=new int[1];
    		int[] num2=new int[1];
    		FindNumsAppearOnce(arr,num1,num2);
    		System.out.println(num1[0]);
    		System.out.println(num2[0]);
    	}
    
        //num1,num2分别为长度为1的数组。传出参数
        //将num1[0],num2[0]设置为返回结果
        public static void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        	if(array==null||array.length<2) {
        		return;
        	}
        	
        	//所有数异或
        	int xorResult=0;
        	for(int i=0;i<array.length;++i) {
        		xorResult^=array[i];
        	}
        	
        	//找到(最后一个)为1的位
        	int bitPos=findFirstOnePos(xorResult);
        	
        	num1[0]=0;
        	num2[0]=0;
        	for(int i=0;i<array.length;++i) {
        		if((array[i]&bitPos)==0) {//bitPos位为0的分为一组
        			num1[0]^=array[i];//该组内所有数异或,结果即为第一个出现一次的数
        		}
        		else {//bitPos为1的分为一组
        			num2[0]^=array[i];//该组内所有数异或,结果即为第二个出现一次的数
        		}
        	}
        }
        
        //获得二进制最后一个1的位置
        private static int findFirstOnePos(int num) {
        	return num&(~num+1);
        }
    }
    
    

    题目二 数组中唯一只出现一次的数字

    题目

    一个数组中,一个数字只出现一次,其他数字都出现三次,找出只出现一次的数字

    题解

    • 用一个32位数组,记录每个数对应位相加的和,每位%3的结果得到的数字就是所求数字。
      时间复杂度O(n),空间复杂度O(1).

    • 其他解法:排序,再找,时间复杂度O(nlogn);或者哈希表,空间复杂度O(n).

    相关

    涉及到了知道哪些位是1,通过位移和与运算得到最终的数。

    代码

    public class Main {
    	public static void main(String[] args) {
    		int[] arr= {1,2,3,3,2,1,4,1,2,3};
    		System.out.println(occurOnce(arr));
    	}
    	
    	public static int occurOnce(int[] nums) {
    		int[] bitSum=new int[32];
    		for(int i=0;i<nums.length;++i) {
    			int bitMask=1;
    			for(int j=0;j<31;++j) {
    				if((nums[i]&bitMask)!=0) {
    					++bitSum[j];
    				}
    				bitMask<<=1;
    			}
    		}
    		
    		int ans=0;
    		for(int i=31;i>=0;--i) {//高位移的多,按从高到低位遍历
    			ans<<=1;
    			ans+=bitSum[i]%3;
    		}
    		return ans;
    	}
    }
    
  • 相关阅读:
    Lock
    synchronized
    线程可见性与原子性
    线程安全问题
    MySQL索引背后的数据结构和原理
    求一颗二叉树中两个节点的最低公共父节点
    Session not active, could not store state 的解决方法
    https nginx 设置
    第三方支付系统
    facebook页面种简单测试js调用flash开放的js接口的方法
  • 原文地址:https://www.cnblogs.com/coding-gaga/p/11162883.html
Copyright © 2011-2022 走看看