前端算法必刷题系列[81]

758 阅读3分钟

这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战

这个系列没啥花头,就是纯 leetcode 题目拆解分析,不求用骚气的一行或者小众取巧解法,而是用清晰的代码和足够简单的思路帮你理清题意。让你在面试中再也不怕算法笔试。

前面连续的难题,来几个简单点放松下

149. 只出现一次的数字(single-number)

标签

  • 简单
  • 异或

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1

输入: [2,2,1]
输出: 1

示例 2

输入: [4,1,2,1,2]
输出: 4

基本思路

这就要说到js异或运算符了, 两个要点

  • 相同的数异或结果为 0
console.log(1^1) // 0
console.log(6^6) // 0
console.log('a'^'a') // 0
  • 与 0 异或 结果为本身

  • 满足交换律

console.log(1^2^1) // 2
console.log(1^1^2) // 2

这样的话,我们就非常清楚这个题目怎么处理了,直接遍历异或就能找出那个单着的dog:那我走?

写法实现

练下 ts 写法,注意 ts 不会影响运行时的 js 行为,也是弱类型的语言。

function singleNumber(nums: number[]): number {
  return nums.reduce((acc, cur) => acc ^ cur)
};

150. 数字的补数(number-complement)

标签

  • 简单
  • 异或

题目

leetcode 传送门

给你一个  整数 num ,输出它的补数。补数是对该数的二进制表示取反。

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1

输入:num = 5
输出:2
解释:5 的二进制表示为 101(没有前导零位),其补数为 010。所以你需要输出 2

示例 2

输入:num = 1
输出:0
解释:1 的二进制表示为 1(没有前导零位),其补数为 0。所以你需要输出 0

基本思路

这里用到异或的另外的性质

  • a ^ b = c 可以推出 a ^ c = b 那么

  • 101 ^ 010 = 111 => 101 ^ 111 = 010 就是我们要的答案了

所以我们只要造一个 跟原数二进制长度相同的 1111.. 然后跟原数异或就得到补数了

另外 toString(2)parseInt(num, 2) 这两个函数的 2,都是二进制的简单转换方式。

写法实现

function findComplement(num: number): number {
  let temp = parseInt(new Array(num.toString(2).length).fill(1).join(''), 2)
  return temp ^ num
}

今天是不是重新认识了异或这个运算呢

另外向大家着重推荐下这个系列的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列

今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦 点击此处交个朋友 Or 搜索我的微信号infinity_9368,可以聊天说地 加我暗号 "天王盖地虎" 下一句的英文,验证消息请发给我 presious tower shock the rever monster,我看到就通过,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧

参考