几道用异或运算符 (xor) 来解的题

山子野
• 阅读 2646

题目来自 leetcode,这是我的 leetcode 解题集,目前在刷第一轮。希望可以一起研究题目。

540 single element in a sorted array

Given a sorted array consisting of only integers where every element appears twice except for one element which appears once. Find this single element that appears only once.
给出一个由整数1 组成的有序2 数组。数组中有一个元素只出现一次,其余的全部出现两次。找出这个只出现一次的元素。

Example 1:

Input: [1,1,2,3,3,4,4,8,8]
Output: 2

Example 2:

Input: [3,3,7,7,10,11,11]
Output: 10

Note: Your solution should run in O(log n) time and O(1) space.

solution 1 (go)

func singleNonDuplicate(nums []int) int {
    len := len(nums)
    for i, v := range nums {
        if i == len - 1 {  // 当前元素如果已经是最后一个元素,直接 break. 同时也是为了防止下面的 nums[i+1] 数组越界
            break
        }
        nums[i+1] = v ^ nums[i+1]  // 当前元素和下一个元素 xor 的结果会被保存到下一个元素
    }
    
    return nums[len-1]  
}

solution 2 (go)

func singleNonDuplicate(nums []int) int {
    left  := 0
    right := len(nums) - 1
    mid := 0
    for left <= right {
        mid = (left + right) / 2
        if left == right {   // left = right, 则 mid = left = right 。即当前值为该查找过程的最后一个值
            break
        }
        if mid % 2 == 1 {  // mid % 2 == 1 说明 nums[mid] 左右各有奇数个元素
            if nums[mid] == nums[mid+1] {
                right = mid - 1
            } else if nums[mid] == nums[mid-1] {
                left = mid + 1
            } else {
                break
            }
        } else { // mid % 2 == 0 说明 nums[mid] 左右各有偶数个元素
            if nums[mid] == nums[mid+1] {
                left = mid + 2
            } else if nums[mid] == nums[mid-1] {
                right = mid - 2
            } else {
                break
            }
        }
    }
    
    return nums[mid]
}

solution 1 (javascript)

var singleNonDuplicate = function(nums) {
    return nums.reduce((x,y)=>x^y);
};

explain

solution 1 (go)

时间复杂度 O(n)

如果 go 有 reduce 功能的话会很好做,比如用 js 直接 return nums.reduce((x, y) => x ^ y) 搞定。这种解法主要是用到了 xor (异或) 位运算符的其中 3 个性质 :

  1. x ^ x = 0
  2. 0 ^ x = x
  3. x ^ y ^ x = x ^ x ^ y

根据这三个性质 :

[1,1,2,3,3,4,4,8,8]

  1 ^ 1 ^ 2 ^ 3 ^ 3 ^ 4 ^ 4 ^ 8 ^ 8
= 0 ^ 2 ^ 0 ^ 0 ^ 0
= 2   // 也就是说把整个数组元素进行异或,得到的最后结果就是不重复值

由于 go 没有 reduce, 我们在 range 的时候都把 当前元素 ^ 下一个元素 的结果覆盖下一个元素的值,以此来达到 reduce 的效果。这样在遍历一遍之后 nums 的最后一个元素就是我们想要的结果,时间复杂度是 O(n)。

solution 2 (go)

时间复杂度 O(log(n))

题目要求时间复杂度是 O(log(n)),再加上已经说明了数组是有序的。其实也只剩下 二分查找 这一种思路了。 二分查找中,每一次迭代都要判断出目标元素在中间元素的左边还是右边,每一次迭代舍弃掉一半不符合条件的数据,直到找到目标元素。

即,每次迭代要判断出不重复值是在中间值的左边还是右边。

/**
 * 由题目可知,nums 只能有奇数个数元素,所以一定会有处于中间的元素。有两种情况:
 *    1. 中间元素左右两边有奇数个元素,如: 1,1,2,2,3,4,4. 中间元素 2 左右两侧各有 3 个元素
 *    2. 中间元素左右两边有偶数个元素,如: 1,1,2,2,3,3,4,5,5. 中间元素 3 左右两侧各有 4 个元素
 */

if mid % 2 == 1 {  // mid % 2 == 1 说明 nums[mid] 左右各有奇数个元素
    // eg: 1,1,2,3,3,4,4 . 
    // 如果中间元素 nums[3] 和 nums[4] 是一对重复值,则 nums[3] 左侧的奇数个元素一定有一个元素无法与其他元素组成一对重复值
    // 即,不重复值一定在 nums[mid] 左侧,right = mid - 1
    if nums[mid] == nums[mid+1] {
        right = mid - 1
    } else if nums[mid] == nums[mid-1] { // 同理,不重复值一定在 nums[mid] 右侧
        left = mid + 1
    } else {
        break
    }
} else { // mid % 2 == 0 说明 nums[mid] 左右各有偶数个元素
    // eg: 1,1,2,2,3,3,4,5,5
    // 中间元素 nums[4] 和 nums[5] 是一对重复值,则 nums[5] 右侧的 4,5,5 是奇数个元素,已定有个一元素无法与其他元素组成一对重复值
    // 即,不重复值已定在 nums[mid] 右侧,left = mid + 2
    if nums[mid] == nums[mid+1] {
        left = mid + 2
    } else if nums[mid] == nums[mid-1] { // 同理,不重复值一定在 nums[mid] 左侧
        right = mid - 2
    } else {
        break
    }
}

461 hamming distance

The Hamming distance between two integers is the number of positions at which the corresponding bits are different.

Given two integers x and y, calculate the Hamming distance.

求整数 x 和 y 的汉明距离。
Note:
0 ≤ x, y < 231.

example

Input: x = 1, y = 4

Output: 2

Explanation:
1   (0 0 0 1)
4   (0 1 0 0)
       ↑   ↑

The above arrows point to positions where the corresponding bits are different.

solution (go)

func hammingDistance(x int, y int) int {
    bits := strconv.FormatInt(int64(x^y), 2)
    var count1 int
    for _,n := range bits {
        if string(n) == "1" {
            count1 ++
        }
    }
    
    return count1
}

explain

题目要求计算两个整数的 汉明距离。汉明距离的计算对象一般是两个等长字符串。所以其实我们要计算的是这两个整数的二进制字符串的汉明距离。
简单的做法就是利用异或符的性质:相同为 0 ,不同为 1。 将 x ^ y 的计算结果转为二进制字符串,求出这个字符串中 "1" 出现的次数即可。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
thinkphp3.2.3模板渲染支持三元表达式
thinkphp3.2.3模板渲染支持三元表达式{$status?'正常':'错误'}{$info'status'?$info'msg':$info'error'}注意:三元运算符中暂时不支持点语法。如下:           <divclass"modalhidefade"id'myModa
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这