feat: leetcode 45,55,121,134,135,238,274,380
This commit is contained in:
parent
dfe0072916
commit
e24153d3db
25
top-interview-leetcode150/55跳跃游戏.js
Normal file
25
top-interview-leetcode150/55跳跃游戏.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* https://leetcode.cn/problems/jump-game/?envType=study-plan-v2&envId=top-interview-150
|
||||||
|
* @param {number[]} nums
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
const canJump = function (nums) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
贪心算法,每一次计数自己能走的最长距离,如果在某一个位置上计算出自己的最长距离超过了数组的最大下标,则表明可以跳跃整个数组
|
||||||
|
如果遍历完数组还是没有找到,则表明不能跳跃数组
|
||||||
|
*/
|
||||||
|
function f1(nums) {
|
||||||
|
let farthest = 0; // 默认能走到的最远下标,初始的时候能走到数组的第一个下表0
|
||||||
|
for (let i = 0; i < nums.length; i++) {
|
||||||
|
// 如果能走的最远距离连当前下表都无法走到直接放回false
|
||||||
|
if (farthest < i) return false;
|
||||||
|
// 如果能走到当前下标,就比较farthest 和 当前下表加上此时的值谁大,更新farthest
|
||||||
|
farthest = Math.max(farthest, i + nums[i]);
|
||||||
|
// 如果更新后的farthest 超过了数组的最大下表,就表示数组能跳跃整个数组,直接返回true
|
||||||
|
if (farthest >= (nums.length - 1)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
36
top-interview-leetcode150/numbers-and-strings/121买卖股票最佳时机.js
Normal file
36
top-interview-leetcode150/numbers-and-strings/121买卖股票最佳时机.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/description/?envType=study-plan-v2&envId=top-interview-150
|
||||||
|
* @param {number[]} prices
|
||||||
|
* @return {number}
|
||||||
|
* 暴力解法:遍历整个数组,找到买入点和所有卖出点的利润,如果利润大于当前利润就更新最大利润,最后返回最大利润,会超时
|
||||||
|
*/
|
||||||
|
|
||||||
|
function f1(prices) {
|
||||||
|
let maxProfit = 0;
|
||||||
|
const size = prices.length;
|
||||||
|
for (let i = 0; i < size; i++) {
|
||||||
|
for (let j = i + 1; j < size; j++) {
|
||||||
|
if (prices[j] - prices[i] > maxProfit) maxProfit = prices[j] - prices[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxProfit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number[]} prices
|
||||||
|
* @return {number}
|
||||||
|
*单次遍历法,定义两个变量,一个maxProfit = 0;一个minPrice=Infinity,maxProfit和上面的暴力法是一样的,保存最大利润,maxProfit
|
||||||
|
*表示的是买入的最小价格,买入的越小后面如果遇到大于它的价格利润就越大,如果利润比maxProfit还大就可以更新maxProfit了,最后
|
||||||
|
*返回即可
|
||||||
|
*/
|
||||||
|
function f2(prices) {
|
||||||
|
let maxProfit = 0;
|
||||||
|
let minPrice = Infinity;
|
||||||
|
for (let i = 0; i < prices.length; i++) {
|
||||||
|
if (prices[i] < minPrice) {
|
||||||
|
minPrice = prices[i];
|
||||||
|
} else if (prices[i] - minPrice > maxProfit) { maxProfit = prices[i] - minPrice; }
|
||||||
|
}
|
||||||
|
return maxProfit;
|
||||||
|
}
|
28
top-interview-leetcode150/numbers-and-strings/134加油站.js
Normal file
28
top-interview-leetcode150/numbers-and-strings/134加油站.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* https://leetcode.cn/problems/gas-station/?envType=study-plan-v2&envId=top-interview-150
|
||||||
|
* @param {number[]} gas
|
||||||
|
* @param {number[]} cost
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
const canCompleteCircuit = function (gas, cost) {
|
||||||
|
let totalGas = 0; let
|
||||||
|
totalCost = 0;
|
||||||
|
let currentGas = 0;
|
||||||
|
let start = 0;
|
||||||
|
|
||||||
|
for (let i = 0; i < gas.length; i++) {
|
||||||
|
totalGas += gas[i];
|
||||||
|
totalCost += cost[i];
|
||||||
|
|
||||||
|
currentGas += gas[i] - cost[i];
|
||||||
|
|
||||||
|
// 如果油量不足,更新起点为下一个加油站
|
||||||
|
if (currentGas < 0) {
|
||||||
|
start = i + 1;
|
||||||
|
currentGas = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果总油量小于总油耗,无法完成一圈
|
||||||
|
return totalGas < totalCost ? -1 : start;
|
||||||
|
};
|
43
top-interview-leetcode150/numbers-and-strings/135分配糖果.js
Normal file
43
top-interview-leetcode150/numbers-and-strings/135分配糖果.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* https://leetcode.cn/problems/candy/?envType=study-plan-v2&envId=top-interview-150
|
||||||
|
* @param {number[]} ratings
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
const candy = function (ratings) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
贪心算法,每个孩子至少分一颗糖果,所以一开始就初始化糖果数组所有元素为1,假设我们是中间的那个孩子,如果我评分比左边的孩子高
|
||||||
|
我应该就要比他多获得一个糖果,如果我们比右边的孩子评分高,我们就应该比右边的孩子多一个糖果,但是我们在处理时先从左往右处理,
|
||||||
|
也就是如果当前孩子比左边孩子评分高就在之前的孩子基础上加上1,这样处理之后会发生一个问题,就是前面的孩子在评分比后面孩子高的时候
|
||||||
|
它获得的糖果已经比后面的孩子多了,所以在处理右边孩子的时候,需要比较当前值和后面孩子糖果加一谁大,取大的那个值,说起来挺难理解,
|
||||||
|
自己用三个孩子思考一下,还是很好理解的。
|
||||||
|
*/
|
||||||
|
|
||||||
|
function f1(ratings) {
|
||||||
|
const n = ratings.length;
|
||||||
|
// 初始化糖果数组
|
||||||
|
const candies = new Array(n).fill(1);
|
||||||
|
// 从左往右处理孩子,如果当前孩子的评分比之前孩子高,当前孩子的糖果数改为之前孩子的糖果数加1
|
||||||
|
for (let i = 1; i < n; i++) {
|
||||||
|
if (ratings[i] > ratings[i - 1]) {
|
||||||
|
candies[i] = candies[i - 1] + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 从右往左遍历,如果当前孩子的评分高,就必须保证当前孩子的糖果数比后面孩子的糖果数加1大,但是经过从左往右的处理
|
||||||
|
// 当前孩子在评分高的情况下糖果数已经大于右边孩子,这样就已经满足要求了,就不要处理了
|
||||||
|
for (let i = n - 2; i >= 0; i--) {
|
||||||
|
if (ratings[i] > ratings[i + 1]) {
|
||||||
|
candies[i] = Math.max(candies[i], candies[i + 1] + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回总糖果数
|
||||||
|
// return candies.reduce((total, cur) => total + cur, 0);
|
||||||
|
let total = 0;
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
total += candies[i];
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* https://leetcode.cn/problems/product-of-array-except-self/?envType=study-plan-v2&envId=top-interview-150
|
||||||
|
* @param {number[]} nums
|
||||||
|
* @return {number[]}
|
||||||
|
*/
|
||||||
|
const productExceptSelf = function (nums) {
|
||||||
|
const n = nums.length;
|
||||||
|
const result = new Array(n).fill(1);
|
||||||
|
|
||||||
|
// 计算每个位置左侧的乘积
|
||||||
|
let leftProduct = 1;
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
result[i] = leftProduct;
|
||||||
|
leftProduct *= nums[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算每个位置右侧的乘积并与左侧乘积相乘
|
||||||
|
let rightProduct = 1;
|
||||||
|
for (let i = n - 1; i >= 0; i--) {
|
||||||
|
result[i] *= rightProduct;
|
||||||
|
rightProduct *= nums[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
31
top-interview-leetcode150/numbers-and-strings/274h指数.js
Normal file
31
top-interview-leetcode150/numbers-and-strings/274h指数.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* https://leetcode.cn/problems/h-index/?envType=study-plan-v2&envId=top-interview-150
|
||||||
|
* @param {number[]} citations
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
const hIndex = function (citations) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
思路:利用贪心算法,遍历整个数组,假设默认是h0,表示有至少零篇论文被引用了至少零次,[0][0,0] 这些都满足,我们遍历的时候检查有没有
|
||||||
|
符合h+1的论文,如果有的化就h++,说明h指数应该增加了,否则的话就表示这个人的学术水平就是当前h,没有必要找下面的h了,直接break
|
||||||
|
*/
|
||||||
|
function f1(citations) {
|
||||||
|
const n = citations.length; // 论文的数量
|
||||||
|
citations.sort((a, b) => b - a); // 按引用次数降序排序
|
||||||
|
let h = 0; // h指数
|
||||||
|
|
||||||
|
// 遍历排序后的数组,寻找最大符合条件的 h 指数
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
if (citations[i] >= h + 1) { // 如果当前论文引用次数大于等于 h+1
|
||||||
|
h++; // 更新 h 指数
|
||||||
|
} else {
|
||||||
|
break; // 如果不满足条件,则退出循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(f1([1, 3, 1]));
|
50
top-interview-leetcode150/numbers-and-strings/380实现数据结构.js
Normal file
50
top-interview-leetcode150/numbers-and-strings/380实现数据结构.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// O(1) 时间插入、删除和获取随机元素
|
||||||
|
// 学习目标,利用哈希表和动态数组实现高效数据结构
|
||||||
|
|
||||||
|
const RandomizedSet = function () {
|
||||||
|
this.nums = [];// 动态数组,储存真实数据,目的是实现O(1)时间内返回随机数据
|
||||||
|
this.valToIndex = new Map(); // 哈希表,实现O(1)时间内查找,删除,插入
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} val
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
RandomizedSet.prototype.insert = function (val) {
|
||||||
|
// 先判断插入的数据是否已经存在,如果存在直接返回false
|
||||||
|
if (this.valToIndex.has(val)) return false;
|
||||||
|
// 维护插入数据的下标
|
||||||
|
this.valToIndex.set(val, this.nums.length);
|
||||||
|
this.nums.push(val);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} val
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
RandomizedSet.prototype.remove = function (val) {
|
||||||
|
// 先判断元素是否存在,如果不存在就返回false
|
||||||
|
if (!this.valToIndex.has(val)) return false;
|
||||||
|
// 获取当前元素和最后一个元素的下标
|
||||||
|
const index = this.valToIndex.get(val);
|
||||||
|
const lastVal = this.nums[this.nums.length - 1];
|
||||||
|
// 把最后一个元素覆盖到当前位置
|
||||||
|
this.nums[index] = lastVal;
|
||||||
|
// 更新原本最后一个元素在哈希表中维持的位置
|
||||||
|
this.valToIndex.set(lastVal, index);
|
||||||
|
// 删除最后一个位置的数据
|
||||||
|
this.nums.pop();
|
||||||
|
// 删除当前元素在哈希表中维持的位置
|
||||||
|
this.valToIndex.delete(val);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
RandomizedSet.prototype.getRandom = function () {
|
||||||
|
// 引入动态数组的目的就是为了实现O(1)返回随机数据
|
||||||
|
const randomIndex = Math.floor(Math.random() * this.nums.length);
|
||||||
|
return this.nums[randomIndex];
|
||||||
|
};
|
54
top-interview-leetcode150/numbers-and-strings/45跳跃游戏II.js
Normal file
54
top-interview-leetcode150/numbers-and-strings/45跳跃游戏II.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* https://leetcode.cn/problems/jump-game-ii/?envType=study-plan-v2&envId=top-interview-150
|
||||||
|
* @param {number[]} nums
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
const jump = function (nums) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
贪心算法,从后往前找,能到达最后一个位置则表明符合要求,所以找能到达最后一个位置的所有下标最小的那个,找到这个位置之后继续找能
|
||||||
|
到达倒数第二个位置的最远的那个位置,直到发现第0个下标也符合即可
|
||||||
|
*/
|
||||||
|
|
||||||
|
function f1(nums) {
|
||||||
|
let position = nums.length - 1; // 表示需要到达的位置,初始时是数组的最后一个位置
|
||||||
|
let steps = 0; // 记录需要跳跃的步数
|
||||||
|
while (position > 0) {
|
||||||
|
for (let i = 0; i < position; i++) {
|
||||||
|
// 从左往右遍历能到达position的位置,如果找到那么这个位置就是我们要找的
|
||||||
|
if (nums[i] + i >= position) {
|
||||||
|
// 更新position
|
||||||
|
position = i;
|
||||||
|
steps++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 贪心算法,
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
function f2(nums) {
|
||||||
|
// 第一步能到达的最远位置
|
||||||
|
let maxPos = 0;
|
||||||
|
let end = 0;
|
||||||
|
let steps = 0;
|
||||||
|
// 无需遍历到最后一个元素,最后一个元素一定能被之前的某个位置跳到
|
||||||
|
for (let i = 0; i < nums.length - 1; i++) {
|
||||||
|
if (maxPos >= i) { // 更新能跳跃的最远位置
|
||||||
|
maxPos = Math.max(maxPos, i + nums[i]);
|
||||||
|
// 如果当前位置已经到达能走的最远位置,则更新下一步的边界
|
||||||
|
if (end === i) {
|
||||||
|
end = maxPos;
|
||||||
|
steps++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return steps;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user