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

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

时间:2024-10-19 13:22:16浏览次数:3  
标签:两个 数字 nums int ret 异或 整型 数组

这里写目录标题

问题详情

剑指 Offer 56:

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

示例:

输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]

分析问题

首先我们知道两个相同的数异或结果是0,而0异或任何数都是不变的;,而且异或运算是支持交换律和结合律;

C语言中的异或符号是’^’

如:353=335=0^5=5;

那如果数组nums中只有一个数出现一次,其它的数都出现了两次,那我们将所有的数组元素进行异或运算,不就可以得出结果了吗?

但是,在这里有两个只出现一次的数字,我们该怎么办呢,如果我们也将其所有的数组元素都异或在一起,那得出的数是不是就是那两个出现一次的数字异或的结果:

例:[1,1,2,3,4,4,5,5]

2 = 0010;3 = 0011

所以1123445^5 = 023 = 0001 = 1

那我们能不能将这两个数分开来呢?使这两个单独出现的数在它们所在的数组都是单独存在的。再分别异或,就能得出这两个数。
在这里插入图片描述

那如何分出这两个数呢:

我们先把数组nums中所有元素异或起来。

1123445^5 = 023 = 0011^0010 = 0001

相同的数异或为0,0与非0数异或为非0数本身。 所以,全部异或在一起就等价于两个单独数异或.

异或得出值0001,设这个值为ret 。通过观察可以发现,ret为1的位,就说明两个单独数的相同位是不同的。要么是1要么是0。不可能重复。

那我们如何去找到为1的位:

我们定义一个变量m = 1;将1(00000000000000000000000000000001)不断地左移m位,与ret进行&运算,如果结果为非0,那此时,1对应的位就是1向左移m位对应1的位置:

在这里插入图片描述

回到刚刚的数组:通过这个为1的位,和原数组中所有元素进行&运算,就可以把两个单独出现的数分开。其他出现两次的数因为二进制值相同也会共同出现在同一边。

在这里插入图片描述

到这我们写出这个程序就不难了。

代码展示

int* singleNumbers(int* nums, size_t numsSize, int* returnSize) {

    int ret = 0;
    int i = 0;

    //保存单独出现的数异或在一起的值
    for (i = 0; i < numsSize; i++)
    {
        ret ^= nums[i];
    }

    int m = 0;
    //从低向高位找到ret中第m位为1的位置, 为1代表异或在一起的两个数不相同。
    //
    while (m < 32)
    {
        if (ret & (1 << m))
        {
            break;
        }
        else
        {
            m++;
        }
    }

    int x = 0;//记录单独出现的数
    int y = 0;//记录单独出现的数
    for (i = 0; i < numsSize; i++)
    {
        if (nums[i] & (1 << m)) //&为1的为一组 直接全部异或到一起记录其值
        {
            x ^= nums[i];
        }
        else  //为0的为一组
        {
            y ^= nums[i];
        }
    }

    int* retArr = malloc(2 * sizeof(int));

    retArr[0] = x;
    retArr[1] = y;
    *returnSize = 2;

    return retArr;
}

int main()
{
    int p = 0;
    int arr[] = { 1,2,55,55,66,66 };
    int* a = singleNumbers(arr, sizeof(arr) / sizeof(int), &p);

    printf("%d ", a[0]);
    printf("%d ", a[1]);
    free(a);
    a = NULL;
    printf("%d ", p);
	return 0;
}

标签:两个,数字,nums,int,ret,异或,整型,数组
From: https://blog.csdn.net/2303_78558007/article/details/143071854

相关文章

  • 钥匙对对碰:RSA加密解密(数字版&字符串版)JAVA实现
    钥匙对对碰:RSA加密解密(数字版)RSA加密的原理其实很简单,就是你有两把钥匙,一把叫公钥,一把叫私钥。这两把钥匙都有很特别的性质:用公钥加锁(加密)之后,只能用对应的私钥来解锁(解密),反过来也一样。我们来一步步看看它是怎么实现的。1.找两把钥匙的“材料”要做出公钥和私钥,首先需......
  • 数组的定义和初始化
    一、数组的定义数组:是一块连续固定大小的内存空间,有着索引的概念定义数组的语句格式:数据类型[]数组名;【推荐】数据类型数组名[];二、数组的静态初始化/*如果只是定义一个数组的话,没有给初始化值,相当于一个变量没有值,是不能够直接使用的如何对一个数组......
  • 一.介绍函数指针数组 二.函数指针数组的使用
    一我们先来看这个这里面的四个函数都分别存放在函数指针变量中,而且这些函数的指针类型都一模一样那我们就可以搞出一个函数指针数组,来存放这些函数的地址 函数指针数组的写法从函数指针的基础上去写是最容易的想让他成为数组,我们可以在变量p后面加一个[],p就和[]结合了,就说明......
  • IO流读写文件(字节流(单个字节,字节数组),字节缓冲流(..),字符流(..),字符缓冲流(..))
    IO流【输入输出流】:按照流向划分:输入流:外部数据->java程序输出流:java程序->外部数据按照数据类型划分【根据使用记事本打开是否能够看懂来决定】:字节流【万能流】:字节输出流:......
  • 【AI整合包及教程】EchoMimic:开创数字人新时代,让静态图像“活”起来!
    在数字化浪潮的推动下,人工智能技术正以前所未有的速度渗透到我们生活的方方面面。从智能家居到自动驾驶,从智能客服到医疗诊断,AI的触角无处不在。而如今,阿里巴巴旗下的蚂蚁集团再次引领潮流,宣布开源其革命性的数字人技术——EchoMimic,这无疑为虚拟直播行业注入了新的活力。Ech......
  • PHP将整形数字转为Excel下标
    1、背景这两天在接到一个需求,需要导出一个班级所有学员的所有成绩,在最后excel表处理的时候发现导出的列超过了26列,后面会出现AA之类的下标,所以写了一个函数把数字整型转为Excel对应的下标。2、转换函数/***@Notes:将整数转为excel对应的列标*@Functionint_to_chr*@p......
  • 从深海探测到海洋强国:数字孪生助力海洋装备跨越式发展
    海洋广袤无垠,蕴藏着丰富的资源。近现代以来,人类使用各种手段探索海洋探索,广袤无垠的海洋与人类的生活越来越紧密,至少10亿人口摄入的蛋白质来自海洋,全球超过90%的货物、数据信息交流在海洋中转;海洋中丰富的矿产资源、独特的经济军事价值等,使其成为世界各国竞争的新热点。 我......
  • 鑫方盛携手纷享销客打造工业品采购领域CRM数字样板
    鑫方盛集团有限公司(以下简称"鑫方盛")始创于1989年,是国内领先的集数字化平台打造、工业品全品类销售以及国际贸易于一体的一站式工业品服务平台。集团拥有海内外90多家分公司,年营收超百亿元。为全球十万余家包括加工制造、航天军工、能源电力、钢铁冶金、水利水电、交通桥梁,......
  • 交错数组 二维数组 参数
    internalclassProgram{staticvoidMain(string[]args){int[,]arr=CreateArr();//int[,]arr1={{1,2},{2,3}};二维数组中不能使用new关键字//int[][]arr2={newint[]{}};交错数组......
  • c#数组案例(较复杂)两个数组合并、去重和取交集
    usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespace_01_数组{internalclassProgram{staticvoidMain(string[]args){//1.合并两个数组......