抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

leetcode刷题笔记

202. 快乐数 - 力扣(LeetCode)

1
2
3
4
5
6
7
8
9
//错误代码
var getHappy = function(n){
let ans = 0;
while(n){
ans+= (n%10) ** 2;
n/=10;
}
return ans;
}

错误原因

在 JavaScript 中,使用/运算符进行除法运算时(如n /= 10这个操作),如果n原本是整数类型,这样的除法操作会将结果转换为浮点数类型。
例如,当n初始值为19,第一次执行n /= 10后,n会变成1.9,而后续在getHappy函数里期望对每一位数字进行处理(通过n % 10获取个位数字等操作),浮点数的取余等操作的行为和预期处理整数时不一致,并且不符合题目本意(通常是按整数的每一位来处理)。
要解决这个问题,应该使用Math.floor(向下取整)或者Math.trunc(去除小数部分)等方法来确保n在分割每一位数字的过程中依然保持整数类型,修改后的getHappy函数如下:

1
2
3
4
5
6
7
8
var getHappy = function(n){
let ans = 0;
while(n){
ans+= (n%10) ** 2;
n = Math.trunc(n/10);
}
return ans;
}

15. 三数之和 - 力扣(LeetCode)

1
2
3
4
5
//错误代码
var threeSum = function(nums) {
nums.sort();
//...
};

错误原因

Array.sort()默认排序是将元素转换为字符串,然后按照它们的 UTF-16 码元值升序排序,所以这样写会导致整数无法按大小排序。正确代码如下

1
2
3
4
var threeSum = function(nums) {
nums.sort((a,b)=>a-b);
//...
};

541. 反转字符串 II - 力扣(LeetCode)

1
2
3
4
5
6
7
8
9
//错误代码
var reverse = function(s,from,to){
while(from<to){
let temp = s[from];
s[from] = s[to];
s[t0] = temp;
from++,to--;
}
}

错误原因

JavaScript中字符串为按值传递,作为参数传递时无法改变值。应改为传递数组,正确代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var reverse = function(arr,from,to){
while(from<to){
let temp = arr[from];
arr[from] = arr[to];
arr[to] = temp;
from++,to--;
}
}
var reverseStr = function(s, k) {
const arr = Array.from(s);
for(let i=0;i<arr.length;i+=2*k){
reverse(arr,i,Math.min(arr.length-1,i+k-1));
}
return arr.join('');
};

28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)

KMP算法模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var strStr = function(haystack, needle) {
const m=haystack.length,n=needle.length;
if(n===0) return 0;
const next= new Array(n).fill(0);
for(let i=1,j=0;i<n;i++){
while(j>0&&needle[i]!==needle[j]) j=next[j-1];
if(needle[i]===needle[j]) j++;
next[i]=j;
}
for(let i=0,j=0;i<m;i++){
while(j>0&&haystack[i]!==needle[j]) j=next[j-1];
if(haystack[i]===needle[j]) j++;
if(j===n) return i-n+1;
}
return -1;
};

239. 滑动窗口最大值 - 力扣(LeetCode)

数组模拟栈:const stack = [];

  • 入栈:stack.push(x);
  • 出栈:stack.pop();
  • 查看栈顶:stack.at(-1);
  • 判断栈非空:stack.length

数组模拟队列:const queue = []

  • 入队:queue.push(x)
  • 出队:queue.shift()
  • 查看队首:queue[0]
  • 查看队尾:queue.at(-1)
  • 判断队非空:queue.length
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var maxSlidingWindow = function(nums, k) {
let ans = [];
let queue = [];
for(let i=0;i<k-1;i++){
while(queue.length&&nums[queue.at(-1)]<nums[i]) queue.pop();
queue.push(i);
}
for(let i=k-1;i<nums.length;i++){
while(queue.length&&nums[queue.at(-1)]<nums[i]) queue.pop();
queue.push(i);
while(queue[0]<=i-k) queue.shift();
ans.push(nums[queue[0]]);
}
return ans;
};

77. 组合 - 力扣(LeetCode)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//错误代码
const ans = [];
const path = [];
var backtracking = function(n,k,startIndex){
if(path.length===k){
ans.push(path);
return;
}
for(let i=startIndex;i<=n-k+path.length+1;i++){
path.push(i);
backtracking(n,k,i+1);
path.pop();
}
};
var combine = function(n, k) {
backtracking(n,k,1);
return ans;
};

错误原因

  1. ans和path需要初始化
  2. 需将path的副本加入ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let ans = [];
let path = [];
var backtracking = function(n,k,startIndex){
if(path.length===k){
ans.push(path.concat());
return;
}
for(let i=startIndex;i<=n-k+path.length+1;i++){
path.push(i);
backtracking(n,k,i+1);
path.pop();
}
};
var combine = function(n, k) {
ans = [];
path = [];
backtracking(n,k,1);
return ans;
};

189. 轮转数组 - 力扣(LeetCode)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//错误代码
var rotate = function(nums, k) {
const reverse = function(nums,from,to){
while(from<to){
let temp = nums[from];
nums[from] = nums [to];
nums[to] = temp;
from++,to--;
}
}
reverse(nums,0,nums.length-k-1);
reverse(nums,nums.length-k,nums.length-1);
reverse(nums,0,nums.length-1);
};

错误原因

​ 元素左移、右移,传入翻转长度不能小于0或大于数组长度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var rotate = function(nums, k) {
k%=nums.length;
const reverse = function(nums,from,to){
while(from<to){
let temp = nums[from];
nums[from] = nums [to];
nums[to] = temp;
from++,to--;
}
}
reverse(nums,0,nums.length-k-1);
reverse(nums,nums.length-k,nums.length-1);
reverse(nums,0,nums.length-1);
};

121. 买卖股票的最佳时机 - 力扣(LeetCode)

1
2
3
4
5
6
7
8
9
//错误代码
var maxProfit = function(prices) {
let preMin = 0,ans = 0;
for(let price of prices){
if(price > preMin) ans = Math.max(ans,price-preMin);
else preMin = price;
}
return ans;
};

错误原因

​ 设置preMin为0会导致股票一定有price的收益,正确做法应该是设置成Number.MAX_SAFE_INTEGER

1
2
3
4
5
6
7
8
var maxProfit = function(prices) {
let preMin = Number.MAX_SAFE_INTEGER,ans = 0;
for(let price of prices){
if(price > preMin) ans = Math.max(ans,price-preMin);
else preMin = price;
}
return ans;
};

6. Z 字形变换 - 力扣(LeetCode)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//错误代码
var convert = function(s, numRows) {
let ans = "";
let temp = new Array(numRows).fill([]);
let index=0,flag =-1;
for(let ch of s){
if(index===0||index === numRows-1) flag = -flag;
temp[index].push(ch);
index+=flag;
}
for(let i=0;i<numRows;i++){
ans+=temp[i].join('');
}
return ans;
};

错误原因

new Array(numRows).fill([]) 这种方式会导致 temp 数组中的所有元素都引用同一个空数组,而不是每个元素都是独立的空数组。

​ 同时,当rows===1是需要特殊处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var convert = function(s, numRows) {
if(numRows===1) return s;
let ans = "";
let temp = new Array(numRows).fill().map(()=>[]);
let index=0,flag =-1;
for(let ch of s){
if(index===0||index === numRows-1) flag = -flag;
temp[index].push(ch);
index+=flag;
}
for(let i=0;i<numRows;i++){
ans+=temp[i].join('');
}
return ans;
};

84. 柱状图中最大的矩形 - 力扣(LeetCode)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//错误代码
var largestRectangleArea = function(heights) {
const n = heights.length;
const leftLowerIndex = new Array(n).fill(0);
const rightLowerIndex = new Array(n).fill(n-1);
let ans = 0;
let stack = [];
for(let i=0;i<n;i++){
while(stack.length>0&&heights[stack.at(-1)]>heights[i]){
const index = stack.pop();
rightLowerIndex[index]=i;
}
stack.push(i);
}
stack = [];
for(let i=n-1;i>=0;i--){
while(stack.length>0&&heights[stack.at(-1)]>heights[i]){
const index = stack.pop();
leftLowerIndex[index]=i;
}
stack.push(i);
}
for(let i=0;i<n;i++){
ans = Math.max(ans,heights[i]*(rightLowerIndex[i]-leftLowerIndex[i]-1));
}
return ans;
};

错误原因:

左边更低高度索引初值应设为-1;右边更低高度索引初值应设为n;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//正确代码
var largestRectangleArea = function(heights) {
const n = heights.length;
const leftLowerIndex = new Array(n).fill(-1);
const rightLowerIndex = new Array(n).fill(n);
let ans = 0;
let stack = [];
for(let i=0;i<n;i++){
while(stack.length>0&&heights[stack.at(-1)]>heights[i]){
const index = stack.pop();
rightLowerIndex[index]=i;
}
stack.push(i);
}
stack = [];
for(let i=n-1;i>=0;i--){
while(stack.length>0&&heights[stack.at(-1)]>heights[i]){
const index = stack.pop();
leftLowerIndex[index]=i;
}
stack.push(i);
}
for(let i=0;i<n;i++){
ans = Math.max(ans,heights[i]*(rightLowerIndex[i]-leftLowerIndex[i]-1));
}
return ans;
};

343. 整数拆分 - 力扣(LeetCode)

考虑数值过小的边界情况,取整取余

1
2
3
4
5
6
7
8
9
//正确代码
var integerBreak = function(n) {
if(n<=3) return n-1;
if(n%3===1){
return 3**(Math.floor(n/3)-1)*4;
}else{
return 3**(Math.floor(n/3))*2**Math.floor((n%3)/2);
}
};

96. 不同的二叉搜索树 - 力扣(LeetCode)

1
2
3
4
5
6
7
8
9
//计算组合数
var numTrees = function(n) {
let ans = 1,fz = 2*n,count = n-1,fm=n;
while(count--){
ans*=fz--;
while(ans%fm===0) ans/=fm--;
}
return ans;
};

494. 目标和 - 力扣(LeetCode)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var findTargetSumWays = function(nums, target) {
let sum = 0;
for(let num of nums) sum+=num;
if(sum+target<0||(sum+target)%2===1) return 0;
const m=nums.length,n=(sum+target)>>1;
const dp = new Array(m+1).fill().map(()=>new Array(n+1).fill(0));
dp[0][0]=1;
for(let i=1;i<=m;i++){
for(let j=0;j<=n;j++){
dp[i][j]+=dp[i-1][j];
if(nums[i-1]<=j) dp[i][j]+=dp[i-1][j-nums[i-1]];
}
}
return dp[m][n];
};

评论