首页 > 其他分享 >异或运算解决查找数组中出现奇数次元素

异或运算解决查找数组中出现奇数次元素

时间:2024-11-01 09:45:22浏览次数:5  
标签:num 运算 int 元素 异或 查找 result 数组

        假设有一个数组只有一个元素出现奇数次,需要查找这个出现奇数次的元素,怎么使用时间复杂度为O(n),空间复杂度为O(1),来解决这道题。以下是使用异或来解决这道题:

  public static int selectOddTimesNum(int[] nums) {
    int result = 0;
    for (int num : nums){
      result ^= num;
    }
    return result;
  }

        这里可以看到,时间复杂度为O(n),空间复杂度只创建了个result变量接收结果,也满足了题目要求。如果不使用异或的话,一般操作是使用HashMap或者其它数据结构来遍历数组,并将每个元素出现的次数记录,然后再遍历输出奇数次的元素。

        这里使用了异或发现,这样更简洁更方便解决这个问题。这里只查了一次,那么我需要进阶一下。有一个数组,里面有2个出现了奇数次的元素,那怎么使用异或运算将这两个数查找出来呢?

        这好像不难,但是按照上面的异或运算,最后结果只能查找出两个奇数次元素的异或结果,并不能分别找出这两个元素。这里就需要回归异或,以及系统运算的原理了。首先异或,可以看成不进位运算,也就是我们十进制中满十进一,现在满十,但不进一了。其次,电脑系统运算是二进制运算。那么通过上面的异或运算,结果是两个数异或的结果,也就是 a ^ b。那么这两个数转为二进制的话,必然至少有一位是不同的,也就是其中一个为1,一个为0。

        那么现在我们得到了第一次异或的结果a ^ b,接下来只需要找出其中一个元素,那另一个就能找出来。上面说了,它俩至少有一位不相同,那我就假设第n位不同,怎么确定这第n位呢?这里我取a ^ b的二进制的最右边的1,假设这一位不同。那么异或运算这一位为1的。

  public static int[] selectOddTimesNum2(int[] nums) {
    int[] temp = new int[2];
    int result = 0;
    for (int num : nums){
      result ^= num;
    }
    // 取出最右边的1
    int rightOne = result & (~result + 1);
    int other = 0;
    for(int num : nums){
      // 只要这一位为1的,就进行异或
      if ((num & rightOne) == 1){
        other ^= num;
      }
    }
    // 结果就是其中一个数
    temp[0] = other;
    // 再异或一下,就是另一个数
    temp[1] = result ^ other;
    return temp;
  }

        可以看到取出一位不同位就能计算出其中一个元素,但是这样下去,如果继续增加出现的元素个数,无疑计算会越来越大,还不如使用HashMap来记录。这里只是讲解一下异或的应用,以及异或的缺点,在实际问题解决中,根据不同场景使用异或,或许能达到意想不到的结果。

        

标签:num,运算,int,元素,异或,查找,result,数组
From: https://blog.csdn.net/swlft/article/details/143423008

相关文章

  • 二叉查找树知识简记
    二叉查找树( BST)一、概念1、简述一种能够将链表插入的灵活性和有序数组查找的高效性结合起来的符号表实现。具体来说,就是使用每个结点含有两个链接(链表中每个结点只含有一个链接)的二叉查找树来高效地实现符号表2、特点(1)在二叉查找树中,每个结点还包含了一个键和一个值,键之......
  • c语言经典20例(输入数组元素,进行排序并输出)
    下面是C语言程序的文字讲解,该程序实现了输入数组元素、对其进行选择排序并输出排序后的数组。#include<stdio.h>voidselectionSort(intarr[],intn){inti,j,min_idx,temp;//一次移动未排序部分的边界for(i=0;i<n-1;i++){//找到......
  • 为什么 C 语言数组是从 0 开始计数的?
    C语言等大多数编程语言的数组从0开始而不从1开始,有两个原因:第一:地址计算更方便C语言从0开始的话,array[i]的地址就正好是:(array+i)如果是从1开始的话,就是(array+i-1)多一次计算,性能受影响,再扩展到二维数组的话array[i][j]从0开始的地址是:(ar......
  • 倍增求后缀数组
    倍增求后缀数组1.一些定义后缀\(i\):子串\([\text{len}(S)-i+1,\text{len}(S)]\);\(\text{SA}(i)\):排名为\(i\)的后缀;\(\text{rank}(i)\):后缀\(i\)的排名,\(\foralli>n,\text{rank}(i)=0\)。后缀数组即\(\text{SA}\)。2.求法先对每个单独的字符从小到大排序,得到每个......
  • 深入理解计算机系统 3.6 数组分配和访问
    C语言中的数组是一种将标量数据聚集成更大数据类型的方式。C语言实现数组的方式非常简单,因此很容易翻译成机器代码。C语言一个不同寻常的特点是可以产生指向数组中元素的指针,并对这些指针进行运算。在机器代码中,这些指针会被翻译成地址计算。3.6.1 基本原则对于数据类型T和......
  • 每日算法一练:剑指offer——数组篇(7)
    1.文物朝代确认        展览馆展出来自13个朝代的文物,每排展柜展出5个文物。某排文物的摆放情况记录于数组 places,其中 places[i] 表示处于第 i 位文物的所属朝代编号。其中,编号为0的朝代表示未知朝代。请判断并返回这排文物的所属朝代编号是否能够视为连......
  • 数组排序简介-计数排序(Counting Sort)
    基本思想        通过统计数组中每个元素在数组中出现的次数,根据这些统计信息将数组元素有序的放置到正确位置,从而达到排序的目的。算法步骤计算排序范围:遍历数组,找出待排序序列中最大值元素 nums_max和最小值元素 nums_min,计算出排序范围为 nums_max−nums_min......
  • 数组排序简介-快速排序(Quick Sort)
    基本思想        采用经典的分治策略,选择数组中某个元素作为基准数,通过一趟排序将数组分为独立的两个子数组,一个子数组中所有元素值都比基准数小,另一个子数组中所有元素值都比基准数大。然后再按照同样的方式递归的对两个子数组分别进行快速排序,以达到整个数组有序。......
  • [SCOI2014] 方伯伯的玉米田(树状数组优化 DP)
     loj传送门https://loj.ac/p/2211洛谷题目传送门https://www.luogu.com.cn/problem/P3287解题思路首先,我们可以贪心地思考一下:对于每一次区间的加一操作,右端点是在末尾会比右端点在中间的情况更好。因为,当你的右端点在序列中间的时候,相对之下,后面的数就更小了一些,这样是......
  • 108-二叉树-将有序数组转换为二叉搜索树
    树|二叉搜索树|数组|分治|二叉树二叉搜索树(BinarySearchTree,简称BST)和平衡二叉搜索树(BalancedBinarySearchTree)是计算机科学中非常重要的数据结构,广泛应用于各种算法和系统中。理解它们的定义、特点和性质对于掌握数据结构和算法至关重要。下面,我们将详细......