`
MouseLearnJava
  • 浏览: 467275 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

寻找数组中只出现一次的数

    博客分类:
  • Java
 
阅读更多
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。



分析:首先先来看一个稍微简单的版本:一个数组里除了一个数字之外,其他的数字都出现了两次。请写程序找出这个只出现一次的数字。这里将会考虑到“异或”的操作:因为异或具有如下的特性:

1. 任何数值和0做异或操作,得到的结果还是本身,即A^0=A

2. 任何两个相同的数值做异或操作,得到的结果是0,即A^A=0

所以,数组中所有的数字都异或操作一遍的话,出现两次的数字都会被抵消掉,最后得到的数便是只出现一次的数字。



/**

 * 如果一个数组集合中除了一个数出现了一次,其余的数值都出现了两次, 怎么快速找出这个只出现一次的数值呢?

 * 

 * @author Eric

 * 

 */

public class FinNumber {

 

    /**

     * 考虑到如下两点:

     * 1. 任何数值和0做异或操作,得到的结果还是本身,即A^0=A

     * 2. 任何两个相同的数值做异或操作,得到的结果是0,即A^A=0

     * 

     * 数组中所有的数字异或操作一遍之后得到的数字就是只出现一次的数字。

     */

    public int find(int[] data) {

       int result = 0;

       for (int value : data) {

           result ^= value;

       }

       return result;

    }

 

    public static void main(String[] args) {

       FinNumber fn = new FinNumber();

       int[] data = new int[]{1,5,3,2,1,5,3};

       System.out.println(fn.find(data));

       

    }

}


现在再来看一下,怎么查找两个只出现一次的数字。

思路就是将数组分成两个部分:还是从头到尾依次异或数组中的每一个数字,那么最终得到的结果就是两个只出现一次的数字的异或结果。因为其他数字都出现了两次,在异或中全部抵消掉了。由于这两个数字肯定不一样,那么这个异或结果肯定不为0,也就是说在这个结果数字的二进制表示中至少就有一位为1。在结果数字中找到第一个为1的位的位置,记为第N位。现在以第N位是不是1为标准把原数组中的数字分成两个子数组,第一个子数组中每个数字的第N位都为1,而第二个子数组的每个数字的第N位都为0。

根据这种思想,写出如下代码:

/**

 * 首先来看题目要求:

 * 

 * 在一个数组中除两个数字只出现1次外,其它数字都出现了2次, 要求尽快找出这两个数字

 * 

 * @author Eric

 * 

 */

 

public class FindTwoNoRepeatNumbers {

 

    public void process(int[] data) {

 

       /**

        * 1. 异或整个数组,

        */

       int xor = populateXORValue(data);

 

       /**

        * 2. 根据整个数组异或得到的值,判断哪一位(低位到高位,0开始计算)要进行区别 0 或者1

        */

 

       int position = populatePosition(xor);

 

       /**

        * 3. 根据不同位置上的值是0还是1区别不同的数组

        */

       int[] numbers = populateNoRepeatNumnbers(data, position);

 

       /**

        * 4. 打印出只出现一次的两个数字

        */

       printTwoNumbers(numbers);

    }

 

    private int[] populateNoRepeatNumnbers(int[] data, int position) {

       int num1 = 0, num2 = 0;

       for (int i = 0; i < data.length; ++i) {

           if (((data[i] >> position) & 1) == 1)

              num1 ^= data[i];

           else

              num2 ^= data[i];

       }

       return new int[] { num1, num2 };

    }

 

    private int populateXORValue(int[] data) {

       int xor = 0;

       for (int element : data) {

           xor ^= element;

       }

       return xor;

    }

 

    private int populatePosition(int xorValue) {

       int position = 0;

       while ((xorValue & 1) == 0) {

           xorValue >>= 1;

           position++;

       }

       return position;

    }

 

    private void printTwoNumbers(int[] numbers) {

       System.out.println(String.format("数组中只出现一次的两个数字是: %d, %d", numbers[0],

              numbers[1]));

    }

 

    public static void main(String[] args) {

       FindTwoNoRepeatNumbers util = new FindTwoNoRepeatNumbers();

       util.process(new int[] { 1, 3, 3, 1, 5, 8 });

       util.process(new int[] { 1, 3, 6, 3 });

    }

}


输出结果:

数组中只出现一次的两个数字是: 5, 8

数组中只出现一次的两个数字是: 1, 6

分享到:
评论

相关推荐

    65-数组中出现一次数字的三种解法1

    总的来说,解决数组中出现一次的数字问题需要理解各种算法和数据结构的特性,并根据具体问题选择合适的方法。双循环简单但效率低,空间换时间方法在特定情况下有效,而异或操作则提供了高效的解决方案。在实际应用中...

    数组中数对差最大

    这种方法可以确保我们在一次遍历中检查所有可能的数对,并且只需要O(n)的时间复杂度,其中n是数组的元素数量。 如果数组是无序的,我们可以首先对数组进行排序,然后使用上述双指针方法。排序会增加额外的O(n log n...

    数组中数字出现的次数II1

    标题 "数组中数字出现的次数II1" 描述了一个经典的编程问题,该问题涉及寻找一个在整数数组中仅出现一次的数字,而其他所有数字都出现三次。这是一个基于数组和哈希表的问题,通常在数据结构和算法的学习中会遇到,...

    【算法题】数组中只出现一次的数字

    本题“数组中只出现一次的数字”就是一个典型的例子,它主要涉及到了数组处理和位操作,特别是异或(XOR)操作。下面我们将深入探讨这个问题的解决方案以及相关知识点。 首先,异或操作是一种基本的位运算,它的...

    分治法求两列有序数组的中位数的程序

    (1)设X[0:n-1]和Y[0:n-1]为两个数组,每个数组中含有n个已排好序的数,设计一个算法复杂度为O...思路:对于两个已排好序的数组,可以寻找两个数组中的中位数,只需要进行n次的比较,时间复杂度可以为O(n),代码如下

    数组中数字出现次数(找单身狗问题 位运算实现)1

    这个问题是关于位运算在解决...总结来说,这种方法巧妙地利用了位运算的性质,通过异或操作和位与操作,可以在常数空间复杂度内找到数组中只出现一次的两个数字。这是一种在数据结构和算法领域中常见的高效解决方案。

    程序员面试题100题(63)-数组中三个只出现一次的数字[算法].pdf,这是一份不错的文件

    在编程面试中,经常会遇到寻找数组中特定数字的问题,本题目的核心是找出一个整数数组中三个只出现一次的数字。这个问题可以通过位操作来高效解决,具体方法涉及到异或操作和二进制特性。以下是对这个问题的详细解析...

    数组下标法求众数

    利用数组下标法求众数 获取数组,定义 临时数组 遍历原数组,并将临时数组中对应的索引所在数加一, 以记录原数组中数出现的次数 遍历临时数组,找出原数组... 多次遍历临时数组是为了防止原数组中出现多个“众数”

    三数之和_三数之和_

    这样可以确保在遍历过程中,相同元素只会被考虑一次,从而避免了重复。 2. **固定第一个数**:遍历排序后的数组,对于每个元素`a`,将其作为固定值,开始寻找其余两个数`b`和`c`。 3. **双指针策略**:设置两个...

    labview数组中统计奇偶计数.vi

    labview统计数组中奇数偶数个数,利用移位寄存器,用labview编写的奇偶计数程序,把第i次循环执行的结果作为第i+1次循环的输入,LabVIEW循环结构中的移位寄存器可以实现这种功能。

    在其他数都出现偶数次的数组中找到出现奇数次的数

    因此,如果数组中的所有元素都异或一次,最后的结果就是那个出现奇数次的数。因为偶数次出现的数相互异或后会得到0,而奇数次出现的数只会剩下它自己。下面是相应的Python代码实现: ```python def print_one_odd_...

    数对之差的最大值

    一次遍历的时间复杂度为O(n),其中n是数组的长度,因为只需要遍历数组一次。而排序会引入额外的时间开销,如果使用快速排序、归并排序等高效排序算法,时间复杂度大约为O(n log n)。但是一旦排序完成,查找最大差值...

    只出现一次的数字(分组+异或)1

    题目 "只出现一次的数字(分组+异或)1" 是 LeetCode 上的一个经典算法问题,要求在给定的整数数组 `nums` 中找出仅出现一次的两个元素。数组中其他元素均出现两次,返回这两个单次出现的元素,顺序不限。此题的关键...

    leetcode Single Number II - 位运算处理数组中的数 - 代金桥 - 博客园1

    LeetCode上的Single Number II问题就是一个典型的例子,它考察了如何利用位运算找出数组中出现一次的整数。本文将深入探讨这个问题,并扩展到更广泛的场景,包括找出出现两次和多次的整数。 首先,我们来看Single ...

    寻找两个正序数组的中位数1

    - **合并与不合并**:一个直观的解法是将两个数组合并后再求中位数,但这会增加时间复杂度,因为需要进行一次排序。 3. **算法设计**: - **二分查找法**:由于数组已排序,可以考虑使用二分查找法来提高效率。...

    算法实习:分治算法求n个数的数组中找出第二个最大元素

    在计算机科学领域,寻找数组中的最大或次大元素是常见的问题之一。这类问题不仅有助于理解数据结构的基本概念,也是评估算法效率和复杂度的良好案例。本文将探讨如何使用分治策略来解决一个特定的问题——在一个包含...

    PHP实现找出数组中出现次数超过数组长度一半的数字算法示例

    在PHP编程语言中,寻找数组中出现次数超过数组长度一半的数字是一个经典问题,通常称为“多数元素”问题。这个问题出现在各种编程面试中,是考察候选人算法和数据结构知识的重要题目。下面详细解释了在PHP中实现此...

    如何寻找数组中的第二大数

    总结来说,寻找数组中的第二大数是常见的编程问题,可以通过一次遍历来解决。第一种方法直接比较每个元素更新最大值和次大值,第二种方法则区分最大值和次大值的更新过程。无论哪种方法,关键在于理解数组的特性和...

    c语言面试题之双指针数组中的K-diff数对.zip

    在C语言面试中,双指针技术...除了K-diff数对问题,双指针还可以用于解决很多其他问题,如有序数组的两个数之和等于目标值、寻找数组中的最长连续子序列等。熟悉并能灵活运用双指针技巧,将有助于你在面试中脱颖而出。

    寻找数组中心索引1

    在给定的问题中,我们需要找到一个整数数组的“中心索引”,这个索引使得其左侧元素之和等于右侧元素之和。如果存在多个满足条件的中心索引,我们需要返回最左侧的那个。若数组中没有这样的中心索引,则返回 -1。 ...

Global site tag (gtag.js) - Google Analytics