两数之和(题号1)
题目
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
提示:
2 <= nums.length <= 103
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
链接
解释
要开始研究算法,LeetCode必不可少。
要刷LeetCode,自然要从第一题开始。
这题是简单题,如果想到那种方法就很简单了,想不到的话可能就是想不到了。
想找到两个和为target
的数,可以换个思路,先找到target
和一个数的差,如果后续循环的时候,有某一个数字在这一堆差里头,那么找到这个差的index
和当前的index
即可。
而且注意题目的描述:
只会存在一个有效答案
那就是不存在没有答案的情况,特殊情况也不用考虑了,十分简单。
自己的答案(数组)
var twoSum = function(nums, target) {
var arr = []
for (let i = 0; i < nums.length; i++) {
var res = arr.findIndex(item => item === nums[i])
if (res > -1) return [res, i]
arr[i] = target - nums[i]
}
};
这里是利用的数组的findIndex()
方法,因为对具体的值不敏感,只关心它的index
。
自己的答案(Map
)
同Map
的话性能会好一些,毕竟它的读写比数组快,而且不需要写判断条件。
var twoSum = function(nums, target) {
var group = new Map()
for (let i = 0; i < nums.length; i++) {
if (group.has(nums[i])) return [group.get(nums[i]), i]
group.set(target - nums[i], i)
}
};
答案就是这样,很清晰易懂
这题主要考的是哈希表,第一步存储差到数组或者Map
中就是一个哈希表,之后在表里查找正确答案就行了,笔者看了看其他的一些答案,JavaScript
基本上都是这个解法,如果更好的方法欢迎在评论区指出
更好的方法
无
整数反转(题号7)
题目
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
示例 1:
输入:x = 123
输出:321
示例 2:
输入:x = -123
输出:-321
示例 3:
输入:x = 120
输出:21
示例 4:
输入:x = 0
输出:0
提示:
-231 <= x <= 231 - 1
链接
解释
看到这题的第一眼就已经想好了做法,的确,这种方法的确是可行的,但其实还有另外一种方法。
自己的答案(经典数组)
var reverse = function(x) {
var num = +Math.abs(x).toString().split('').reverse().join('')
if (num > Math.pow(2, 31) - 1 || num < Math.pow(-2, 31)) return 0
return x < 0 ? 0 - +num : +num
};
说实话,性能并不比另外一种差,可以说是不相伯仲。
执行用时:88 ms, 在所有 JavaScript 提交中击败了96.37%的用户
内存消耗:39 MB, 在所有 JavaScript 提交中击败了96.66%的用户
更好的方法(位运算)
var reverse = function(x) {
var res = 0
while (x) {
// res每次增加10倍,然后加上新增的数据
res = res * 10 + x % 10
if (Math.abs(res) > Math.pow(2, 31)) return 0
// 一个~是按位取反,两个~~是直接去掉小数点后面的内容
// 而且~~不会改变数字的正负,这一点比Math.floor()强不少
x = ~~(x/10)
}
return res
};
其实就是10位10位的累加,又点类似于有经典是10位进1的操作,但又有些许不同。
这样对x
一次次对遍历,最终x
会被拆解为0,拆解完成时还没越界就直接返回res
。
回文数(题号9)
题目
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。
示例 1:
输入:x = 121
输出:true
示例 2:
输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:
输入:x = 10
输出:false
解释:从右向左读, 为 01 。因此它不是一个回文数。
示例 4:
输入:x = -101
输出:false
提示:
-231 <= x <= 231 - 1
进阶:你能不将整数转为字符串来解决这个问题吗?
链接
解释
其实和上面的整数反转的代码差不多,就是可以通过一些判断直接过滤掉一些结果。
比方说负数必然不会时回文数,还有就是可以被10整除的数,因为被10整除的数最后一位必然是0,但没有数字是以0开头的。
自己的答案(位运算)
var isPalindrome = function(x) {
if (x < 0 || (x > 0 && x % 10 === 0)) return false
var xBefore = x
xEnd = 0
while (x) {
xEnd = xEnd * 10 + x % 10
x = ~~(x / 10)
}
return xBefore === xEnd
};
跑得也还不错,抽风的时候可以跑到下面这个成绩,感觉LeetCode是用时和内存消耗很不稳定,没谱的事。
执行用时:196 ms, 在所有 JavaScript 提交中击败了92.80%的用户
内存消耗:46.2 MB, 在所有 JavaScript 提交中击败了97.63%的用户
更好的方法(数学算法)
这块就有点超纲了,感觉这辈子都写不出这样的代码,贴一下地址吧:
PS:想查看往期文章和题目可以点击下面的链接:
这里是按照日期分类的👇
经过有些朋友的提醒,感觉也应该按照题型分类
这里是按照题型分类的👇
有兴趣的也可以看看我的个人主页👇