53. 最大子数组和https://leetcode.cn/problems/maximum-subarray/
重刷出现的一些小问题:
1、dp[i]的含义是什么:以i为下标的最大连续子数组的和
所以我们需要找到dp中最大的值————用ans维护。
2、ans的值定义为Number的最小值了,那当nums中只有一个数的时候,返回的是ans,就出
错了。
// 第一感觉:这肯定得用dp做
// 时间复杂度:O(n)
// 空间复杂度:O(n)
const dp = new Array().fill(0);
// 赋初值的一个问题:被一个值搞晕了,以为输出个数
dp[0] = nums[0];
let ans = dp[0];
// dp数组就是存储以该下标结束的一个长度,所以最后当然需要去找出其中的最大值
for(let i = 1;i<nums.length;i++){
dp[i] = Math.max(dp[i-1]+nums[i], nums[i]);
ans = Math.max(dp[i], ans);
}
return ans;
1. 两数之和https://leetcode.cn/problems/two-sum/
容易题;
// 是否存在某数——立马想到哈希法(数组,set, 哈希表)
// 如果不要求O(n^2)的话 那就是两个for循环,那就太low了,所以肯定需要以空间去换时间
// 时间复杂度:O(n)
// 空间复杂度:O(n)
const map = new Map();
for(let i = 0;i<nums.length;i++){
if(map.has(target - nums[i])){
return [map.get(target - nums[i]), i];
}
map.set(nums[i], i);
}
121. 买卖股票的最佳时机https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/
1、重做一次还是用了双重循环n2的 时间复杂度,没有过;
2、直觉用dp通过了;还是上面的问题,你不知道维护的最后的dp是不是最大值,是因为你没
弄清楚dp[i]的含义到底是什么,好在你可以输出看看dp[i]的值你就明白了;
3、实际上都用不上dp,直觉维护一个当前最小值,和当前利润的最大值
// 肯定得选当前最小的买,为什么不是全数字最小的?——因为不能保证最小的顺序一定在卖之后
// 下面的超出时间限制了,那就想办法以空间换时间
// let curMin = 0;
// let ans = 0;
// for(let i = 0;i<prices.length;i++){
// curMin = i;
// let sum = 0;
// for(let j = i+1;j<prices.length;j++){
// sum = prices[j] - prices[i];
// ans = Math.max(ans, sum);
// }
// }
// return ans;
// 也没有用空间换时间
// 其实就是一个关键点:每次都维护当前的一个最小值,然后维护都在当前卖出去的一个价格,找到其中最大值
// 时间复杂度:O(n)
// 空间复杂度:O(1)
let curMin = prices[0];
let ans = 0;
for(let i = 0;i<prices.length;i++){
curMin = Math.min(curMin, prices[i]);
ans = Math.max(ans, prices[i] - curMin);
}
return ans;
169. 多数元素https://leetcode.cn/problems/majority-element/
// 一定要记住先排序,有个直接的切入口,既然多数元素的次数肯定大于n/2,那么在n/2个位置上肯定就是多数元素了
// 时间复杂度:O(nlgn) 排序的
// 空间复杂度: 看排序
// nums.sort();
// return nums[Math.floor(nums.length/2)];
// 也可以尝试出现的值作为键,次数作为值,找出次数最大的
// 时间复杂度:O(n)
// 空间复杂度: O(n)
const map = new Map();
for(let i = 0;i<nums.length;i++){
if(map.has(nums[i])){
map.set(nums[i], map.get(nums[i])+1);
}else{
map.set(nums[i], 1);
}
}
let ans = -1;
let res = 0;
map.forEach(function(value, key){
if(value > ans){
res = key;
ans = value;
}
})
return res;
回顾了一下遍历map的方法:
(1)map.forEach(function(value, key){}) //第一个是值, 第二个是键
(2)for(let item of map){}
for(let key of map.keys()){}
for(let value of map.values()){}
(3)entries遍历,和forEach一样
for(let item of map.entries())
for(let item in xx):遍历的是下标:
283. 移动零https://leetcode.cn/problems/move-zeroes/
哎~~这道题在我找实习的第一个面试中出现,超简单呀,但是我还以为前端不考算法题,我也没刷题,而且很久很久很久很久没刷题了,手生的一批啊,挂了应该的,活该~继续努力!
// 这不就是双指针吗,哼
// 时间复杂度: O(n)
// 空间复杂度: O(1)
// j维持非0元素下标, i遍历所有元素,找到非0元素就放到j的位置上,完了之后填充j之后到数组长度之间的数都为0;
let j = 0;
for(let i = 0;i<nums.length;i++){
if(nums[i]!==0){
nums[j] = nums[i];
j++;
}
}
//填充0
for(let k = j;k<nums.length;k++){
nums[k] = 0;
}
return nums;
581. 最短无序连续子数组https://leetcode.cn/problems/shortest-unsorted-continuous-subarray/
思路是正确的,但是需要更加细心呀;
// 最开始没想法呀,后面试了一下自己的想法有一半案列没过。
// 就去看了官方的解答,就是将原数组与有序后的数组进行比较,找到不相同的左右边界即可。
// 时间复杂度:O(nlgn) 排序
// 空间复杂度:O(n)
const isSorted = (nums)=>{
for(let i = 0; i<nums.length;i++){
if(nums[i] < nums[i-1]){
return false;
}
}
return true;
}
if(isSorted(nums) || nums.length <2){
return 0;
}
// 拷贝该数组,变成有序的数组,且不会改变原先的数组
// 单纯的把数组复制 是浅拷贝,会影响原数组
let sortedNums = [...nums].sort((a,b)=>{
return a-b;
});
let left = 0, right=0;
for(let i = 0; i<nums.length;i++){
if(nums[i] !== sortedNums[i]){
left = i;
break;
}
}
for(let j = nums.length-1; j>=0;j--){
if(nums[j] !== sortedNums[j]){
right = j;
break;
}
}
return right - left + 1;
知识点回顾: 深浅拷贝
首先回顾一下扩展运算符... 学习参考JS中的扩展运算符(...)和剩余运算符(...)_webchang的博客-CSDN博客
非常清晰!
关于深浅拷贝的学习参考
JS之深浅拷贝详解_前端菜菜DayDayUp的博客-CSDN博客
非常清晰+1!
常用方法:新创建一个空数组,一个一个加进去;扩展运算符(这个更好用);一维的话slice()也可以
多维的一定要用JSON.parse(JSON.stringify(obj));
448. 找到所有数组中消失的数字https://leetcode.cn/problems/find-all-numbers-disappeared-in-an-array/
第二次我用了map,还不如用array嘞;
// 用一个数组记录,出现过的值为数组值为其本身的值,没有出现过的值对应的数组值为0
// 时间复杂度:O(n)
// 空间复杂度:O(n)
let n = nums.length;
let ans = new Array(n+1).fill(0);
for(let i = 0;i<n;i++){
ans[nums[i]] = nums[i];
}
let count = [];
console.log(ans);
for(let i =1;i<=n;i++){
if(ans[i]===0){
count.push(i);
}
}
return count;
数组篇结束啦, 多去思考一下问题,还有小错误注意避免,切记不能死记硬背!加油;
还是要更加细心一点,现在思路都大概有了,一是个别地方的小错误要注意,二是怎么实现好也要动动脑子,不行就感觉换一个方法;总之数组吗,排个序啊,双指针遍历啊,用array、map,不外乎这些方法。