专栏声明:只求用最简单的,容易理解的方法通过,不求优化,不喜勿喷
今天更新剩下六个的 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;
};