找出唯一出现一次的数

1.问题描述:找出数列中唯一一个出现一次的数,其余得数都出现两次。

分析:

  1)最笨的方法当然是穷举了:

#include <stdio.h>

int array[] = { 1 , 3, 3, 1, 5, 5 , 6};

int
get_only()
{
    int *ptmp1, *ptmp2;
    int *arrend = array + sizeof(array) / sizeof(int);

    for(ptmp1 = array; ptmp1 != arrend; ptmp1 ++)
    {
        for (ptmp2 = array; ptmp2 != arrend; ptmp2++)
        {
            if (ptmp2 != ptmp1 && *ptmp2 == *ptmp1)
            {
                break;
            }
        }

        if (ptmp2 == arrend)
        {
            return ptmp1 - array;
        }
    } 

    if (ptmp1 == arrend)
    {
        return -1;
    }
}

int
main(int argc, char *argv[])
{
    int rst = get_only();
    if (rst == -1)
        printf("no such number\n");
    else
        printf("only num is : %d\n", array[rst]);

    return 0;
}

  2)异或操作 (^):

  性质: 0 ^ 0 = 0, 1 ^ 1 = 0, 0 ^ 1 = 1, 0 ^ A = A;

  总结起来就是按位异或 相同为0,不同为1。

  这样一来明显得出,相同的俩个数异或得0,不同的两个数异或一定不为0(多少另算),0和任和数异或都得其本身(0 ^ A = A)。

  由此得出另一种方法,将数组中的所有元素进行异或操作,则剩下的一个必定是唯一一个只出现一次的数:

#include <stdio.h>

int array[] = { 1 , 3, 3, 1, 5, 5 , 6 };

int get_only2()
{
    int ret = array[0];
    int i;
    printf("len is %d\n", len);
    for (i = 1; i < sizeof(array) / sizeof(int); i++)
    {
        printf("ret is %d\n", ret);
        ret = ret ^ array[i];
    }

    return ret;
}

int
main(void)
{
    int ret = get_only2();
    printf("only number is %d\n", ret);

    return 0;
}

  btw:运用异或操作还可完成不借助其它参数,交换两个数的值: (用 g++编译,gcc编译不过)

#include <stdio.h>

void
swap(int &a, int &b)
{
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
}

int
main(void)
{
    int a = 1;
    int b = 2;

    printf("before swap: a %d, b %d\n", a, b);

    swap(a, b);

    printf("after swap:  a %d, b %d\n", a, b);

    return 0;
}

-----------------------------------------------------------------------分割线----------------------------------------------------------

2.问题描述:数列中,只有两个整数只出现一次,其余的出现两次,找出这两个整数.

  有了上边的铺垫,很容易想到用 异或 操作,通常回想到将所有数异或。

  但是发现,若这两个数分别为A, B,则异或后 只能消除其它存在两次的数,但是结果为A ^ B,仍然找不出A, B。

  此时我们希望A和B, 分别出现在两个数组中,并且这两个数组中的各自的其它成员,是两两相同的。然后这两个数组分别各自异或操作,则数组各自只剩下A和B,这样便找出来了。

  但是我们如何分出这样的两个数组呢?

  根据之前分析得出,A和B不相等则 A ^ B 的结果必然不为0,那么这个结果必定可以用16进制表示,并且至少某一位上为1.我们假设从右向左的第x位不为0,即为1.(0x001001...,1的位置为x)

  那么肯定A的第x位为1,B的为0;或者相反。同理,除A,B以外的这些数的第x位上或者为0,或者为1. 此时便可根据第x位为0或者为1,将整个数列分成两个数组且分别包含A和B,姑且叫arrA, arrB。

  这样一分,我们还发现,arrA中除A,以外是两两相同的,arrB除B以外也是两两相同的。最极端的情况是arrA只包含A或者arrB只包含B。但是这不重要,重要的是我们得到了两个数组分别包含A和B且其余两两相同。

  于是,我们分别将arrA中元素异或操作得到A,将arrB中元素异或操作得到B。

  步骤:(g++编译)

  1)先得到A ^ B (get_oxr_rst)

  2)找到第x位上的1,这里的技巧是得到一个mask,只处理这一位 (get_mask)。

  3)用mask & arr[idx], 找到这一位为1的所有元素,并异或操作。

  4)B = orx_rst ^ A.

#include <stdio.h>

int
get_oxr_rst(int *arr, int len)
{
    int rst = 0;
    int idx;

    for(idx = 0; idx < len; idx ++)
    {
        rst ^= arr[idx];
    } 

    return rst;
}

int
get_mask(int oxr_rst)
{
    int mask = 1;
    while((mask & oxr_rst) == 0)
    {
        mask <<= 1;
    } 

    return mask;
}

int
get_rst(int *arr, int len, int &A, int &B)
{
    if (len < 2)
    {
        return 0;
    }

    int oxr_rst = get_oxr_rst(arr, len);
    int mask = get_mask(oxr_rst);

    int idx;

    for (idx = 0; idx < len; idx++)
    {
        if (mask & arr[idx])
        {
            A ^= arr[idx];
        }
    }

    B = A ^ oxr_rst;

    return 1;
}    

int
main(int argc, char *argv[])
{
    int arr[] = { -4, 2, 2, 4 , 3, 5, 5, 3};
    int A = 0, B = 0;

    int rst = get_rst(arr, sizeof(arr) / sizeof(int), A, B);

    if (rst)
        printf("different number is A %d and B %d\n", A, B);
    else
        printf("wrong args\n");

    return 0;
}

未完,待续。

  

  

  

  

 

  

时间: 2024-07-28 22:00:09

找出唯一出现一次的数的相关文章

1.2 如何找出唯一成对的数(4种解法)

作者:acDream_ 来源:CSDN 原文:https://blog.csdn.net/acDream_/column/info/32487 原文是用Java实现的,自己理解后用C语言实现,记录下来. Problem:1-1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素值重复,其他均只出现一次.设计一个算法,将它找出来,你能否设计一个算法实现? 思路1(最先想到的): 首先也是最暴力的方法就是一个循环嵌套一个循环,一个一个去找 时间复杂度为O(n²) 下面是实现的代码:

一个数如果恰好等于它的因子之和,这个数就称为&quot;完数&quot;。 例如,6的因子为1、2、3,而6=1+2+3,因此6是&quot;完数&quot;。 编程序找出N之内的所有完数,

题目描述 一个数如果恰好等于它的因子之和,这个数就称为"完数". 例如,6的因子为1.2.3,而6=1+2+3,因此6是"完数". 编程序找出N之内的所有完数,并按下面格式输出其因子: 输入 N 输出 ? its factors are ? ? ? 样例输入 1000 样例输出 6 its factors are 1 2 3 28 its factors are 1 2 4 7 14 496 its factors are 1 2 4 8 16 31 62 124

题目:一个数如果恰好等于它的因子之和,这个数就称为 &quot;完数 &quot;。例如6=1+2+3.编程&#160;&#160;&#160;&#160; 找出1000以内的所有完数。

题目:一个数如果恰好等于它的因子之和,这个数就称为 "完数 ".例如6=1+2+3.编程     找出1000以内的所有完数. 1 package day11_2; 2 3 public class lianxi09 { 4 public static void main(String[] args) { 5 6 for (int i = 1; i < 1000; i++) { 7 int sum=0; 8 for (int j = 1; j <i; j++) { 9 10

找出1000以内的所有完数

题目:一个数如果恰好等于它的因子之和,这个数就称为 "完数 ".例如6=1+2+3.编程 找出1000以内的所有完数. 1 package com.li.FiftyAlgorthm; 2 3 /** 4 * 题目:一个数如果恰好等于它的因子之和,这个数就称为 "完数 ".例如6=1+2+3.编程 找出1000以内的所有完数. 5 * 6 * @author yejin 7 * 8 */ 9 public class Wanshu { 10 public static

码农谷 找出N之内的所有完数

题目描述 一个数如果恰好等于它的因子之和,这个数就称为"完数". 例如,6的因子为1.2.3,而6=1+2+3,因此6是"完数". 编程序找出N之内的所有完数,并按下面格式输出其因子. 输入描述 N 输出描述 ? its factors are ? ? ? 样例 输入: 1000 输出: 6 its factors are 1 2 3 28 its factors are 1 2 4 7 14 496 its factors are 1 2 4 8 16 31 62

java实现找出1000以内的所有完数

/**  *   *题目:一个数如果恰好等于它的因子之和,这个数就称为"完数".例如6=1+2+3.编程 找出1000以内的所有完数  *  */ public class Test9 {     public static int perfact(int n) {         int s = 0;         for (int i = 1;i <= n / 2;i++) {             if (n % i == 0) {                 s 

【Java】编程找出1000以内的所有完数。

1 package com.xt.homework.hw09; 2 /** 3 * 5. 一个正整数,如果恰好等于除它本身外的所有因子之和,这个数就称为"完数". 4 * 例如6=1+2+3,编程找出1000以内的所有完数. 5 * 6 * 7 * @author 天耀二期 8 * 杨勃隆 9 */ 10 public class HomeWork05 { 11 public static void main(String[] args){ 12 { 13 int i,j,k; 14

javascript 找出数字数组中最大的数

找出数字数组中最大的数 var Match = (function(){ var arr = null; var len = 0; return { max:function(arr,len){ arr = arr; len = arr.length; var newArr = arr.sort(); return newArr[len-1]; } } })(); var maxCount = Match.max([3,4,5,11,3,4,55,67,88,33]); console.log(

输入一组数,找出其中满足某种条件的数(二)

书接上文. 输入一组数,找出其中满足某种条件的数. 短短的一句话,可以衍生出各种场景.今天遇到一道题,输入一些学生的分数,哪个分数出现的次数最多?如果有多个并列,从大到小输出.分数均为不超过100的非负整数. 我首先想到的是利用哈希表,用空间换时间. 1 #include<iostream> 2 using namespace std; 3 4 int main() 5 { 6 int hash[101] = { 0 }; 7 int n = 0; 8 while (cin >>n