int类型数组中找出现几次的数的题目总结

1.     题目1:int类型数组中除了一个数出现一次以外,其他数都出现两次,求该数。

【分析】全部异或运算即可。

2.     题目2:int类型数组中除了两个数出现一次以外,其他数都出现两次,求这两个数。

参考:http://zhedahht.blog.163.com/blog/static/2541117420071128950682/

【分析】:全部亦或之后得到的数为resultExclusiveOR,找到它的第一个不是0的位,然后将数组按这个位是否为0分成两组,组内全部亦或即可。

/**
 * 创建时间:2014年9月6日下午7:51:17 项目名称:Test
 *
 * @author Cao Yanfeng
 * @since JDK 1.6.0_21 类说明:数组只有两个数是只出现一次,其他的都出现两次,中找到只出现一次的两个数
 */
public classFindNumsAppearOnceTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int[] array = { 1, 2, 1, 9, 3, 2,0, 3 };
        printNumsAppearOnce(array);

    }

    /* 算法思想:全部亦或之后得到的数为resultExclusiveOR,找到它的第一个不是0的位,让后将数组按这个位是否为0分成两组,组内全部亦或即可 */
    public static void printNumsAppearOnce(int[] array) {
        if (array == null || array.length < 2) {
            return;
        }
        int resultExclusiveOR= 0;
        for (int i = 0; i < array.length; i++) {
            resultExclusiveOR^= array[i];
        }
        int mask =1;
        /*只要相&等于0,就左移一位,直到获得模版*/
        while ((resultExclusiveOR&mask)==0) {
            mask<<=1;
        }
        int result1 = 0, result2 = 0;
        for (int i = 0; i < array.length; i++) {
            if ((array[i]&mask)== 0) {
                result1 ^= array[i];
            }else{
                result2 ^= array[i];
            }
        }
        System.out.println("这两个数分别是" + result1 + ","+ result2);
    }
}

3.     题目3:int类型数组中除了三个数出现一次以外,其他数都出现两次,求这三个数

题目的另一种简单形式:求这三个数中任意一个数。

参考:http://zhedahht.blog.163.com/blog/static/25411174201283084246412/

【分析】以实际例子说明:数组为array,三个数互不相同,比如是001,010,100

1)  第一次遍历获得这三个数的异或X=a^b^c,即X=111,可以证明X与a、b、c均不相同;

2)  X^a=b^c=110,X^b=a^c=101,X^c=a^b=011,可以证明这三个数也均不相同。定义函数f(X^a)= f(b^c)=010表示保留除了最后一个bit位为1的位置外其它bit位全部置为0,则f(X^b)= 001,f(X^c)= 001。第二次遍历获取f(X^a)^f(X^b)^f(X^c)的结果即f(X^a)^f(X^b)^f(X^c)=010。

3)  获取f{f(X^a)^f(X^b)^f(X^c)}的结果f{f(X^a)^f(X^b)^f(X^c)}=010,即保留除了最后一个bit位为1的位置外,其它bit位全部置为0,注意,这里获取了一个模版,f(X^a)、f(X^b)、f(X^c)即010、001、001三个数只有f(X^a)该bit位为1。

4)  第三次遍历,只要符合f(X^array[i])=010的数都全部异或,就能求出来a。

5)  第四次遍历,找到a与数组最后一个数交换,0~array.lenth-2范围内可以求得另外两个数。

/**
 * 创建时间:2014年9月6日下午9:36:17
 * 项目名称:Test
 * @authorCao Yanfeng
 * @sinceJDK 1.6.0_21
 * 类说明:   数组只有三个数是只出现一次,其他的都出现两次,中找到只出现一次的三个数
 * 至少需要5次遍历,其中一次是处理将第一个找到的元素删除或再添加一个进去,这里是通过将它与最后一个元素交换来删除的。
 */
public class FindThreeUniqueTest {

         /**
          * @paramargs
          */
         public static void main(String[] args) {
                   // TODO Auto-generated method stub
                   int[] array={2,3,3,4,5,5,0};
                   printThreeUnique(array);

         }
         public static void printThreeUnique(int[] array) {
                   if (array==null||array.length<3) {
                            return;
                   }
                   /*第一次遍历,找到三个数的亦或X*/
                    int xorResult =0;
                    for (int i = 0; i < array.length; i++) {
                            xorResult^=array[i];
                   }
                    /*第二次遍历,找到f(X^a)^f(X^b)^f(X^c)的结果*/
                    int index=0;
                    for (int i = 0; i < array.length; i++) {
                            index^=lastBitof1(xorResult^array[i]);
                   }
                    /*f(X^a)^f(X^b)^f(X^c)的结果只保留最后一位1,其它都置为0,假设该位为m位且f(X^a)的m位为1*/
                    index=lastBitof1(index);
                    /*第三次遍历,a一定在符合f(X^a)的m位为1的分组*/
                    int first=0;
                    for (int i = 0; i < array.length; i++) {
                            if (lastBitof1(xorResult^array[i])==index) {
                                     first^=array[i];
                            }
                   }
                    System.out.println("第一个数是:"+first);
                    /*第四次遍历,找到a的位置并跟最后一个数交换*/
                    for (int i = 0; i < array.length; i++) {
                            if (array[i]==first) {
                                     array[i]^=array[array.length-1];
                                     array[array.length-1]^=array[i];
                                     array[i]^=array[array.length-1];
                            }
                   }
                    /*在0~array.length-2范围内找两个数*/
                    printNumsAppearOnce(array, array.length-1);
         }
         public static void printNumsAppearOnce(int[] array,int lenght) {
                   if (array == null || lenght < 2) {
                            return;
                   }
                   int resultExclusiveOR = 0;
                   for (int i = 0; i < lenght; i++) {
                            resultExclusiveOR ^= array[i];
                   }
                   int mask =1;
                   /*只要相&等于0,就左移一位,直到获得模版*/
                   while ((resultExclusiveOR&mask)==0) {
                            mask<<=1;
                   }
                   int result1 = 0, result2 = 0;
                   for (int i = 0; i < lenght; i++) {
                            if ((array[i]&mask)== 0) {
                                     result1 ^= array[i];
                            } else {
                                     result2 ^= array[i];
                            }
                   }
                   System.out.println("第二个数和第三个数分别是:" + result1 + "," + result2);
         }
         /*只保留最后一位1,其它位都置为0*/
         public static int lastBitof1(int arg){
                   return arg&~(arg-1);
         }

}

4.     题目4:int类型数组中除了一个数出现一次或两次以外,其他数都出现三次,求这个数。

参考:http://blog.csdn.net/dinosoft/article/details/6443354

【分析】每一个bit位,只要出现三次就将该bit位清零。

分析下面的一段代码:

/**
 * 创建时间:2014年9月6日下午10:25:21
 * 项目名称:Test
 * @author Cao Yanfeng
 * @since JDK 1.6.0_21
 * 类说明:  int类型数组中除了一个数出现两次以外,其他数都出现三次,求这个数.
 */
public classFindDoubleTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int[] array1={1,1,1,20};
        printDouble(array1,1);
        int[] array2={1,1,1,20,20};
        printDouble(array2,2);

    }

    public static void printDouble(int[] array,int oneOrTwo) {
        int ones=0,twos=0;
        for (int i = 0; i < array.length; i++) {
            twos|=ones&array[i];
            ones^=array[i];
            int not_threes=~(ones&twos);
            ones&=not_threes;
            twos&=not_threes;
        }
        switch (oneOrTwo) {
        case 1:
            System.out.println("出现1次的数为:"+ones);
            break;
        case 2:
            System.out.println("出现2次的数为:"+twos);
            break;
        default:
            break;
        }
    }

}

如果数组前三项都是相同的数a,箭头前是执行ones&=not_threes和twos&=not_threes之前的数,箭头后是执行ones&=not_threes和twos&=not_threes之后的数,。


i=0


i=1


i=2


twos=0→0


twos=a→a


twos=a→0


ones=a→a


ones=0→0


ones=a→0


not_threes=1


not_threes=1


not_threes=~a

据此可以分析出,当a出现一次的时候,ones能保存a。当a出现两次的时候,twos能保存a。当a出现三次的时候,ones和twos都清零。所以,如果一个数值中所有的数都通过这个循环的话,出现三次的数都清零了,有一个数如果出现一次,它保存在ones中;如果出现两次的话保存在twos中。

时间: 2024-10-22 03:16:38

int类型数组中找出现几次的数的题目总结的相关文章

75 int类型数组中除了一个数出现一次或两次以外,其他数都出现三次,求这个数。

[本文链接] http://www.cnblogs.com/hellogiser/p/single-number-of-array-with-other-three-times.html [题目] int类型数组中除了一个数出现一次或两次以外,其他数都出现三次,求这个数. [分析] C++ Code 123456789101112   int singleNumber(int *a, int n) {     int ones = 0, twos = 0;     for (int i = 0;

无序数组中找第k大的数

类快排算法 由于只要求找出第k大的数,没必要将数组中所有值都排序. 快排中的partition算法,返回key在数组中的位置的cnt(相对于left的偏移量),如果cnt正好等于k,那么问题则得到解决:如果cnt小于k,去左边找第k个:如果cnt>k,则去右边找第k-cnt个.直到key的位置等于k-1,则找对问题的解. /*快排中的划分算法*/ int partition(int* input, int low, int high) { int tmp = input[low]; // 取一个

C语言实现一个int类型数组里除了两个数字之外,其他的数字都出现了两次,找出这两个数字

题目是这样叙述的:在一个数组中除两个数字只出现1次外,其它数字都出现了2次, 要求尽快找出这两个数字. 要求:时间复杂度为O(N),空间复杂度为O(1). 请看我的分析:将这道题简单化:一个数组中只有一个数字出现一次,其他数字都是成对出现的,这时我们可以根据异或运算符的特性:A^B^A = B; 0 ^ A = A:我们可以将这个数组的全部元素依次做异或运算,最终结果就是那个只出现一次的数字.不会的可看本人(2019-04-04)那天的博客 如果这个数组中出现两个不同的数字,而其他数字均出现两次

Android java传递int类型数组给C

接着前面的文章<Android java传递int类型数据给C><Android java传递string类型数据给C>,继续实践 实现public native int[] arrElementsIncrease(int[] intArray); 项目布局 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://sc

相邻元素差的绝对值都是1,在这样的数组中找目标元素

有这样一个数组A,大小为n,相邻元素差的绝对值都是1.如:A={4,5,6,5,6,7,8,9,10,9}.现在,给定A和目标整数t,请找到t在A中的位置.除了依次遍历,还有更好的方法么? 这道题目的解法非常有趣. 数组第一个数为array[0], 要找的数为y,设t = abs(y - array[0]).由于每个相邻的数字之差的绝对值为1.故第t个位置之前的数肯定都比y小.因此直接定位到array[t],重新计算t,t = abs(y – array[t]),再重复上述步骤即可.这种算法主要

脑洞题目 - 改自从一组无序数组中找不存在的最小正整数

无聊想的题目,但题目创意改自从一组无序数组中找不存在的最小正整数.并不难,但也有陷阱,比考虑0和负数... /** * 从无序数组中找不存在的最小正整数 * 我的要求:比如:{3,4,6,9,20}中 最小的不存在的正整数为2 */ #include <stdio.h> int main() { int arr[] = {-5, -10, 42, 29, 18, -3, 8, 20, -1}; int i, j, temp; for(i = 1; i < sizeof(arr)/size

bestcoder#43 1002 在数组中找两个数的和取模的最大值 二分

bestcoder#43 1002 在数组中找两个数的和取模的最大值  二分 pog loves szh II Accepts: 97 Submissions: 834 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Description Pog and Szh are playing games. There is a sequence with n number

有序数组中找中位数

问题描述 给定两个有序数组,返回这两个数组的中位数.如果中位数有两个,则返回它们的平均值. e.g. [1, 3, 5]和[2, 4, 6]的中位数是3.5 解决思路 如果两个数组的长度之和为奇数,则中位数有一个:否则中位数为其中两个的平均值. 从两个数组中找第k个数,可以使用递归的思路. 程序 首先,写出在有序数组a和b中找到第k大的程序: 1. 利用归并排序中的merge数组方法,时间复杂度为O(k). public int findKthNaive(int[] a, int[] b, in

在数组中找几个数的和等于某个数[LeetCode]

首先明确一点,这个方面的问题设计到的知识点是数组的查找的问题.对于类似的这样的查找操作的具体办法就是三种解决方法: 1.暴力算法,多个for循环,很高的时间复杂度 2.先排序,然后左右夹逼,但是这样会破坏原始数组的下表 3.利用Hash表,直接定位元素,很少的时间复杂度 TwoSums 先来看看最简单的,在一个数组中找两个数的和等于某个数. 这个题目最简简单的方法就是暴力法,所需的时间复杂度是O(n2),但是这是不允许的,所以一个O(n)的方法就是利用Hash表存储数据,这样能够把查找的时间降低