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

     40.数组中只出现一次的数字

    题目描述

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

    思路一:

    对数组排序,然后遍历数组,判断前后不相等的元素,第一个是num1[0], 第二个数num2[0], 注意如果前后相等的两个元素要跳过一位

     1 //num1,num2分别为长度为1的数组。传出参数
     2 //将num1[0],num2[0]设置为返回结果
     3 import java.util.Arrays;
     4 public class Solution {
     5     public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
     6         // 排序
     7         Arrays.sort(array);
     8         
     9         // 然后遍历数组,判断前后不相等的元素
    10         boolean flag = true;    // 判断是第一个满足要求的数字
    11         for(int i = 0; i < array.length; i++){
    12             if(i + 1 < array.length && array[i] == array[i + 1]){
    13                 i++;    // 跳过下一个数
    14             }else {
    15                 if(flag){
    16                     num1[0] = array[i];
    17                     flag = false;
    18                 }else{
    19                     num2[0] = array[i];
    20                 }
    21             }
    22         }
    23     }
    24 }

    思路二:

    利用异或运算

    异或运算的规则是:两个相同数字异或=0一个数和0异或还是它本身

    只有一个数出现一次时,我们把数组中所有的数,依次异或运算,最后剩下的就是落单的数,因为成对儿出现的都抵消了。所以我们尝试把原数组分成两个数组,每个数组分别含有一个只出现一次的数字,且每个数组中其他元素均是成对出现的。

    分成这样两个数组的过程是:假设 两个只出现一次的数字分别为 A 和 B

    1. 定义一个变量 xor ,遍历数组,让这个变量与每个元素都进行一次异或运算,最终的结果肯定是 A 与 B 做异或的结果,因为其他元素都成对出现抵消为0 了。

    2. 从低位开始,找到 xor 的二进制表示中第一个1 出现的位置, 假设位置为 p ,按照异或的规则,这个位置的值既然 是 1,那么说明 A 和 B两个元素在该位置的值肯定不同,肯定是一个是0,一个是1

    3. 定义一个变量 index ,初值为 1, 让它左移 p 位,这样 index 的二进制表示中只有 p 位 为 1, 其他位均为0, 让 index 分别与元素组中每个元素进行按位与运算,判断是否为 0,如果为0则将这个元素归入到数组1, 否则归入到数组2,这样每个数组都有一个只出现一次的元素,而且每个数组中除了这个元素外其他元素肯定都是成对出现的。

    4. 让num1[0] 对数组1的每个元素分别做异或运算,最终 num1[0] 中的元素肯定就等于 A 或 B 中的一个;同理,让num2[0] 对数组2中的每个元素分别做异或运算,最终num2[0] 中的值肯定是 A 或 B 中剩下的那个。

    这里做了一个小优化:把步骤 4 和 步骤 3合并,两个操作同时进行,也就是在 让 index 与原数组中元素进行按位与运算后不将数存入数组1或者数组 2,而是直接让 num1[0] 或 num2[0] 与该数做异或运算,这样最后num1[0] 和 num2[0]就能分别存储 A 或 B 中的一个。

     1 //num1,num2分别为长度为1的数组。传出参数
     2 //将num1[0],num2[0]设置为返回结果
     3 import java.util.Arrays;
     4 public class Solution {
     5     public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
     6        int xor = 0;
     7         for(int i = 0; i < array.length;i++){
     8             xor ^= array[i];
     9         }
    10         // 求出第一个 1 的位置
    11         int index = 1;
    12         while((index & xor) == 0)
    13             index <<= 1;
    14         // 3/4.
    15         for(int i = 0; i < array.length; i++){
    16             if((index & array[i]) != 0)
    17                 num1[0] ^= array[i];
    18             else
    19                 num2[0] ^= array[i];
    20         }
    21         
    22     }
    23 }
  • 相关阅读:
    验证视图状态 MAC 失败的处理办法总结![come from internet]
    在ie6上 让他显示png图片
    挑灯夜战 css hack 再次学习 IE浏览器常见的9个css Bug以及解决办法
    fileupload上传 and IE8 and VS2008 实现图片预览[new Name:经典的Fakepath错误]
    大项目开发语言的选择
    虚拟机安装linux:未找到任何驱动程序
    objectc中的bool
    关于数字内容网站的一些想法
    iphone开发论坛
    在centos5.3下安装mysql5启动时报错
  • 原文地址:https://www.cnblogs.com/hi3254014978/p/12601435.html
Copyright © 2011-2022 走看看