[失业前端恶补算法]JavaScript leetcode刷题top100(四):移动零、比特位计数、找到所有数组中消失的数字、二叉树的直径、汉明距离、合并二叉树

专栏声明:只求用最简单的,容易理解的方法通过,不求优化,不喜勿喷
今天更新剩下六个的 easy 难度题目:

移动零

  • 题面
    给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
    请注意 ,必须在不复制数组的情况下原地对数组进行操作。

  • 知识点:
    数组

  • 思路
    用一个 cnt 记录当前出现的 0 的个数,遍历数组,每次遇到 0 的时候,cnt + 1;每次遇到不是 0 的数的时候,将这一位之前的第 cnt 位变成当前的数,因为它之前已经出现了 cnt 个 0 了,所以把这些 0 移动的数组末尾的话,当前的数必须要向前移动 cnt 位。
    遍历完毕,将数组最后的 cnt 个数变成 0,即可完成我们需要的操作

  • 代码

var moveZeroes = function (nums) {
    
    
    let cnt = 0;
    for (var i = 0; i < nums.length; i++) {
    
    
        if (nums[i] == 0) {
    
    
            cnt++;
        } else {
    
    
            nums[i - cnt] = nums[i];
        }
    }
    for (var i = nums.length - 1; i > nums.length - 1 - cnt; i--) {
    
    
        nums[i] = 0;
    }
    return nums;
};

比特位计数

  • 题面
    给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。

  • 知识点
    二进制、动态规划

  • 思路
    我们可以看到,当数字的二进制长度只有一位的时候,结果是 0 和 1,当有两位的时候新增的数据是 0 和 1 之前都加上一个 1 ,也就是 00 01 10 11 四种情况,如果是三位,新增的数据就是在位数是 2 位的 4 种情况下前面分别加上 1,以此类推。
    所以当有 n 位的情况下,结果就是就是复制一份 n-1 位的情况,在他们的最高位都加上一个 1。所以我们从 1 位开始,遍历 1 到 n 位的情况,每次依次复制第 n-1 位的内容,然后结果 + 1 即可。
    我们初始化一个 0 在 dp 数组中:对 1 位的情况,遍历数组 0 - 2 ^ ( 1 - 1 ) 位,分别加上 1 存入数组中,结果是 [ 0 ,0 +1 ] ;对于 2 位的情况,遍历数组 0 - 2 ^ ( 2 - 1 ) 位,分别加上 1 存入数组中,结果是 [ 0 ,1 , 0 + 1 , 1 + 1] ;当结果数等于我们需要的总数的时候,停止我们的遍历。

  • 代码

var countBits = function (n) {
    
    
    let re = [0]; //dp数组
    let now = 1;  //位数
    while (re.length < n+1) {
    
    
        for (var i = 0; i < Math.pow(2, now - 1); i++) {
    
    
            re.push(re[i] + 1);
            if(re.length == n+1){
    
    
                break;
            }
        }
        now++;
    }
    return re;
};

找到所有数组中消失的数字

  • 题面
    给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。
  • 知识点
    哈希表
  • 思路
    因为要求优化空间复杂度到 O(1) ,所以我们使用数组本身来记录我们已经出现过的元素,我们遍历整个数组,将对应元素的下标的数变成负数,但是这样操作会破坏我们还没有遍历到的元素,所以我们取每个元素的时候需要将它取绝对值即可。
    之后我们再遍历一次整个数组,还没有变成负数的下标对应的数就是我们没有出现的数,我们将它们输出即可
  • 代码
var findDisappearedNumbers = function (nums) {
    
    
    for (var i = 0; i < nums.length; i++) {
    
    
        if (nums[Math.abs(nums[i]) - 1] > 0) {
    
    
            nums[Math.abs(nums[i]) - 1] *= -1;
        }
    }
    let re = [];
    for (var i = 0; i < nums.length; i++) {
    
    
        if (nums[i] > 0) {
    
    
            re.push(i + 1);
        }
    }
    return re;
};

二叉树的直径

  • 题面
    给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。
  • 知识点
    二叉树、深度优先搜索
  • 思路
    深度优先遍历整棵二叉树,对于每个节点,如果它作为直径的非根节点,它提供的长度就是左子树和右子树长度的最大值;如果它作为直径的根节点,它的直径的长度就是左子树长度和右子树长度 + 1,依次遍历每个节点,找出以它为根节点的直径的最大值,输出即可
  • 代码
var diameterOfBinaryTree = function (root) {
    
    
    let max = 0;
    let dfs = (root) => {
    
    
        if (!root) {
    
    
            return 0;
        }
        let ll = dfs(root.left);
        let rr = dfs(root.right);
        if (ll + 1 + rr > max) {
    
    
            max = ll + 1 + rr;
        }
        return Math.max(ll, rr) + 1;
    }
    dfs(root);
    return max-1;
};

汉明距离

  • 题面
    两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。
    给你两个整数 x 和 y,计算并返回它们之间的汉明距离。
  • 知识点
    二进制
  • 思路
    每次取出两个数 % 2 的结果,比较他们是不是一致,不一致则距离 + 1,之后对这两个数 / 2,(上述操作是将两个十进制的数变为二进制的操作),如此操作直到两个数都变成 0 ,遍历结束,输出汉明距离
  • 代码
var hammingDistance = function (x, y) {
    
    
    let re = 0;
    while (x || y) {
    
    
        let tx = x % 2;
        let ty = y % 2;
        x = Math.floor(x/2);
        y = Math.floor(y/2);
        if (tx != ty) {
    
    
            re++;
        }
    }
    return re;
};

合并二叉树

  • 题面
    给你两棵二叉树: root1 和 root2 。
    想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。
    返回合并后的二叉树。
    注意: 合并过程必须从两个树的根节点开始。
  • 知识点
    二叉树,递归
  • 思路
    递归遍历整个二叉树,每次传入两个同一个位置的节点,如果都存在,将节点 2 的值合并到节点 1 上,返回节点 1,然后有一个不存在,返回另一个节点,如果都不存在返回 null ,之后将左右子树递归调用合并函数进行合并
  • 代码
var mergeTrees = function (root1, root2) {
    
    
   if (!root1 && !root2) {
    
    
        return null;
    }
    if (!root1) return root2;
    if (!root2) return root1;
    root1.val = root1.val + root2.val;
    root1.left = mergeTrees(root1.left, root2.left);
    root1.right = mergeTrees(root1.right, root2.right);
    return root1;
};

猜你喜欢

转载自blog.csdn.net/weixin_46463785/article/details/129462878