求数组中出现一次的数字

一个数组中只有一个数字出现一次,其余别的数字都出现两次,如何求出这个出现一次的数字?例如数组a[11]={1,2,2,3,3,4,4,5,5,6,6},则出现一次的是1,通过异或算法即可求出.

代码如下:

int onediffent(int a[],int n)
{
	int temp=0;
	for(int i=0;i<n;i++)
		temp=temp^a[i];

	printf("%d\n",temp);

}

补充:任何数与零异或等于任何数.任何数与自己相异或为0;

假如问题变成一个数组中有两个数字出现一次,其余别的数字都出现两次,那么如何求出这两个数字呢?

算法思路:首先将数组中的一组数字异或,结果存在temp中,然后计算出temp中最低位出现的位置,然后再和数组中所有的数字相与,这样就将数组分成了两个数组,问题转换为一个数组中只有一个数字出现一次的情况。

代码如下:

int twodiffent(int a[],int n)
{
	int temp,count,i,j,k;
	temp=a[0];
	j=k=0;
	int b[n],c[n];

	for(int i=1;i<n;i++)
		temp=temp^a[i];

	count=1;
	//求出temp中为1的最低位位置
	while(!(temp&1))
	{
		temp=temp>>1;
		count*=2;
	}
	//将两个数字分别分到两个数组中,问题转换为一个数组中只有一个出现一次的数.
	for(i=0;i<n;i++)
	{
		if(a[i]&count==1)
			b[j++]=a[i];
		else
			c[k++]=a[i];
	}
	onediffent(b,j);
	onediffent(c,k);
}

在算法群里某热心网友不吝赐教得到目前最优解,相对比算法二优化了至少一个世纪<囧>,代码如下:

void solve(int num[],int n)
{
        int x = 0;
        for(int i = 0; i < n; ++i)
        {
            x = x ^ num[i];
        }
        int smallestOne = x & -x;
        int a = 0;
        int b = 0;
        for(int i = 0; i < n; ++i)
        {
            if((num[i] & smallestOne) != 0)
                a = a ^ num[i];
            else
                b = b ^ num[i];
        }
       printf("%d %d\n",a,b);
}

该算法中x&-x是算出最低位的1,负数在计算机中是以补码表示,例如4&-4=4,1000&-1000=8 表示数字4中二进制位1最低位是在权为2^2出现,数字1000二进制位1最低位是在权值为2^3出现.算法二中的数组完全没有必要使用,空间复杂度为O(1),时间复杂度O(n);

如果你有更好的方法,不妨在此讨论.

时间: 2024-10-19 14:59:21

求数组中出现一次的数字的相关文章

[LeetCode] Kth Largest Element in an Array 数组中第k大的数字

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element. For example, Given [3,2,1,5,6,4] and k = 2, return 5. Note: You may assume k is always valid, 1 ≤ k ≤ array'

求一无序数组中第n大的数字 - 快速选择算法

逛别人博客的时候,偶然看到这一算法题,顺便用C++实现了一下. 最朴素的解法就是先对数组进行排序,返回第n个数即可.. 下面代码中用的是快速选择算法(不晓得这名字对不对) 1 #include <vector> 2 #include <iostream> 3 #include <stdexcept> 4 #include <cstdio> 5 6 const int QS_EERRMSG_LEN = 256; 7 8 9 /** 10 * 快速选择求无序数组

不用遍历 递归算法 求数组中数字的最大值

#include "stdio.h"int ax[] ={1000,5,6,8,9,800,5,200,3,6,5,8,9};int paixu (int n, int ret){    if (n==0) return ret>ax[0]?ret:ax[0];    int ret1= ret>ax[n]? ret:ax[n];    return paixu(n-1,ret1);}int main(int argc, char* argv[]){    int numb

求数组中任意两个数之间所有数字的和

303. Range Sum Query - Immutable   求数组中任意两个数之间所有数字的和 QuestionEditorial Solution My Submissions Total Accepted: 37248 Total Submissions: 146945 Difficulty: Easy Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j),

求数组中两两相加为某个数字的组合数

/** * 求数组中两两相加是20的组合数 * @param array * @param sum */ public static void getMethod_3(int[] array,int sum){ int count = 0; for(int i=0;i<array.length;i++){ if(i==array.length-1){ break; } for(int j=i+1;j<array.length;j++){ if(array[i]+array[j]==sum){

九度OJ 1534 数组中第K小的数字

题目1534:数组中第K小的数字 时间限制:2 秒 内存限制:128 兆 特殊判题:否 提交:1524 解决:307 题目描述: 给定两个整型数组A和B.我们将A和B中的元素两两相加可以得到数组C. 譬如A为[1,2],B为[3,4].那么由A和B中的元素两两相加得到的数组C为[4,5,5,6]. 现在给你数组A和B,求由A和B两两相加得到的数组C中,第K小的数字. 输入: 输入可能包含多个测试案例. 对于每个测试案例,输入的第一行为三个整数m,n, k(1<=m,n<=100000, 1&l

求数组中的最小值以及最小值的序列号

var Arr = [5,6,1,2,3];// var minValue = Math.min.apply(null,Arr);//apply方法可直接求出数组中的最小值var minIndex = $.inArray(minValue,Arr);//inArray求最小数在数组中的序列号 固定方法 alert(minIndex);//输出2 即数字1在数组中的位置 求数组中的最小值以及最小值的序列号

剑指Offer对答如流系列 - 数组中出现次数超过一半的数字

面试题39:数组中出现次数超过一半的数字 题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1, 2, 3, 2, 2, 2, 5, 4, 2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. 问题分析 大家最容易想到的思路是 数字次数超过一半,则说明排序之后数组中间的数字一定就是所求的数字. 既然是数组,要牵扯到排序,大家一般都会选用经典快速排序或者随机快速排序.随机快速排序由于每次划分的依据是从数组随机选出的,所以数据状况对它

写一个方法求数组中的最大值,最小值,总和以及平均值。

class Program { /// <summary> /// 求数组中的最大值,最小值,总和以及平均值. /// </summary> /// <param name="nums">输入一个数组</param> /// <returns>返回一个新的数组(max,min,sum,avg)</returns> public static int[] GetMaxMinSumAvg(int[] nums) { i