zoukankan      html  css  js  c++  java
  • 剑指offer56:数组中只出现一次的数字

    题目描述

    一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
     思路:对于这个题目是没有较好的思路的,只能想到遍历然后利用map计数的方法。
    看了书上的解释才学到了利用异或的方法进行计算
    Tips: 1. 两个相同的数异或值为0
       2. 如果数组中除一个数字外,其余数字都出现两次,那么所有数字的异或值结果即为只出现一次的数
       3. 题目中是存在两个只出现一次的数,那么所有数字的异或值就是这两个数字的异或值。
       4. 由于两个只出现一次的数的异或值肯定不为0,那么异或值的二进制的某一位一定为1,假设为第count位
       5. 接着把原数组分成两组,分组标准是第3位是否为1,那么两个只出现一次的数一定被分到两个不同的组
       6. 对两个组分别求异或值,即可求得两个只出现一次的数字
    代码实现:
    C++较繁琐的实现,注意这里int* num1,int* num2是指针传递,赋值的时候应*num1 = yihuo;
    class Solution {
    public:
        void FindNumsAppearOnce(vector<int> data,int* num1,int* num2) {
            int len = data.size();
            if(len == 0) return;
            //求数组所有数的异或值
            int result = data[0];
            for(int i=1;i<len;i++){
                result = result ^ data[i];
           }
            int count = 0;
            int temp = result;
            //求异或值第几位为1
            while(true){
                if(temp & 1 == 1)
                    break;
                temp = temp >> 1;
                count++;
            }
            //把数组分为两部分
            vector<int> newData;
            for(int i=0;i<len;i++){
                if((data[i]>>count) & 1 == 1)
                    newData.push_back(data[i]);
            }
            int yihuo = newData[0];
            for(int i=1;i<newData.size();i++){
                yihuo = yihuo ^ newData[i];
            }
            *num1 = yihuo;
            *num2 = (result ^ yihuo);
        }
    };

     精简后的代码(java):

    //num1,num2分别为长度为1的数组。传出参数
    //将num1[0],num2[0]设置为返回结果
    public class Solution {
        public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
            if(array.length == 0) return;
            //求所有结果的异或值
            int res = 0;
            for(int elem:array){
                res ^= elem;
            }
            //求该异或值从右边数第一个1的位数
            int num = 1;
            int indexOne = 0;
            while((res & num) == 0){
                num  <<= 1;
                indexOne++;
            }
            num1[0] = 0;
            for(int elem:array){
                if(((elem >> indexOne)&1)==1)
                    num1[0] ^= elem;
            }
            num2[0] = num1[0] ^ res;
        }
    }
  • 相关阅读:
    codevs 1115 开心的金明
    POJ 1125 Stockbroker Grapevine
    POJ 2421 constructing roads
    codevs 1390 回文平方数 USACO
    codevs 1131 统计单词数 2011年NOIP全国联赛普及组
    codevs 1313 质因数分解
    洛谷 绕钉子的长绳子
    洛谷 P1276 校门外的树(增强版)
    codevs 2627 村村通
    codevs 1191 数轴染色
  • 原文地址:https://www.cnblogs.com/ttzz/p/13862320.html
Copyright © 2011-2022 走看看