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

336 阅读2分钟

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

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

156. 移动零(move-zeroes)

标签

  • 简单
  • 双指针

题目

leetcode 传送门

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序

示例 1

输入: [0,1,0,3,12]
输出: [1,3,12,0,0]

基本思路

看似简单的题目,把0移动到末尾,其他数相对位置不变。

使用两个指针ij,只要nums[i]! == 0,我们就交换nums[i]nums[j],再把 j 指针后移,令 j 始终指向最后一个非 0 元素就行

写法实现

function moveZeroes(nums: number[]): void {
  if (nums.length !== 0) {
    let j = 0;
    for (let i = 0; i < nums.length; i++) {
      if (nums[i] !== 0) {
        [nums[i], nums[j]] = [nums[j], nums[i]]
        j++
      }
    }
  }
};

157. 比特位计数 (counting-bits)

标签

  • 中等

题目

leetcode 传送门

给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。

示例 1

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

示例 2

输入: 5
输出: [0,1,1,2,1,2]
  • 给出时间复杂度为O(n*sizeof(integer)) 的解答非常容易。但你可以在线性时间O(n) 内用一趟扫描做到吗?
  • 要求算法的空间复杂度为O(n)

基本思路

分奇偶讨论

  • 偶数: 最后一位是 0,位移运算右移一位,把 0 移掉,其实就是除以二,发现 1 的个数是不会变的,举个例子

    console.log(8>>1) // 4 
    
    • 8 右移一位4 其实就是 8 / 2 = 4
    • 那么 二进制下看
      • 8 => 1000
      • 4 => 100
    • 其实就是把最后一位 0 移掉了, 1 的个数是不会变的

所以如果 i 是 偶数, res[i] = res[i / 2]

  • 奇数: 奇数其实就很简单,上一个偶数最后一位是 0,加 1,那么 1 的个数就是

res[i] = res[i-1] + 1

写法实现

function countBits(n: number): number[] {
  // 0 的 二进制是 0
  let res = [0]
  for (let i = 1; i <= n; i++) {
    if (i % 2 === 0) {
      // 偶数情况 最后一位是 0 所以 1 的个数一定和除以2(或者说右移一位) 的那个数一样多,
      res[i] = res[i / 2]
    } else {
      // 奇数情况 因为上一个数偶数末尾必然是 0 现在变成 1,所以个数 + 1
      res[i] = res[i-1] + 1
    }
  }
  return res
};

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

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

参考