feat: 添加算法题目35,234,876,739

This commit is contained in:
LouisFonda 2025-06-22 00:33:08 +08:00
parent 614b10bcd0
commit dbcfc3f91a
Signed by: yigencong
GPG Key ID: 29CE877CED00E966
6 changed files with 240 additions and 0 deletions

View File

@ -22,6 +22,7 @@
"no-constant-condition": "off", // while(true)
"default-case": "off", // switchdefault
"no-fallthrough": "off", // case穿
"prefer-destructuring": ["error", {"object": false, "array": false}],
"import/extensions": [
"error",
"ignorePackages", // node_modules

View File

@ -0,0 +1,36 @@
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
const searchInsert = function (nums, target) {
};
/*
直接使用二分查找二分查找没什么好说的但是这个题目中target不一定存在nums中所以需要设置一个pos遍历来保存target应该插入的位置
我们只需在target < nums[mid]的时候设置一次就行初始化pos的index=nums.length
*/
function f2(nums, target) {
let pos = nums.length;
let left = 0;
let right = nums.length - 1;
// 二分查找知道left>right结束查找
while (left <= right) {
const mid = Math.floor((left + right) / 2);
// 如果target<nums[mid] 则更新pos
if (target === nums[mid]) return mid;
if (target < nums[mid]) {
pos = mid;
right = mid - 1;
continue;
}
left = mid + 1;
}
return pos;
}

View File

@ -84,3 +84,48 @@ function topKbest(nums, k) {
// 堆顶即为第 k 大元素
return heap[0];
}
/*
若题目没有要求动态的维护这个topk,那么可以使用quick-select来实现O(n)的时间复杂度完成这个题目
思路题目要求我们找出第k大的数那么当整个数组排序之后倒数第k个数不就是我们要求的吗比如[5,4,3,2,1] k = 2,那么排序后[1,2,3,4,5]
倒数第二个数的下标就是nums.length - k = 5 - 2 = 3 nums[3]恰好就是我们要找的这个数我们没有必要对整个数组排序我们只要找到排序后这个
数正确的位置即可知道快速排序的话我们可以使用partition来确定pivot,pivot在partition之后就已经确认如果pivot的下标等于倒数第k个位置
那么pivot就是排序之后的倒数第k个数也就是topk
*/
function f2(nums, k) {
return quickSelect(nums, 0, nums.length - 1, nums.length - k);
}
function quickSelect(nums, left, right, n) {
const p = partition(nums, left, right);
if (p === n) return nums[n];
return p < n ? quickSelect(nums, p + 1, right, n) : quickSelect(nums, left, p - 1, n);
}
/**
* 分区函数返回pivotpivot 左边的数都不大于右边的数都不小于它
* @param {*} nums 要操作的数组
* @param {*} left 开始位置左边界
* @param {*} right 结束位置, 右边界
* @returns number 返回的piivot
*/
function partition(arr, left, right) {
const pivot = arr[right];
let p = left;
for (let i = left; i < right; i++) {
if (arr[i] <= pivot) {
// [arr[i], arr[p]] = [arr[p], arr[i]];
swap(arr, i, p);
p++;
}
}
// [arr[p], arr[right]] = [arr[right], arr[p]];
swap(arr, p, right);
return p;
}
function swap(nums, a, b) {
const tmp = nums[a];
nums[a] = nums[b];
nums[b] = tmp;
}

View File

@ -0,0 +1,40 @@
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
const isPalindrome = function (head) {
};
/*
利用栈将链表的值存储起来然后再从头开始遍历链表比较每个节点的值和栈顶的值是否相等
利用了回文的定义正着和倒着应该是一样的
*/
function f1(head) {
const stack = [];
let current = head;
// 第一步:将所有节点的值压入栈中
while (current) {
stack.push(current.val);
current = current.next;
}
// 第二步:从头开始重新遍历链表,同时与栈顶比较
current = head;
while (current) {
if (current.val !== stack.pop()) {
return false;
}
current = current.next;
}
return true;
}

View File

@ -0,0 +1,32 @@
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
const middleNode = function (head) {
};
function ListNode(val, next) {
this.val = (val === undefined ? 0 : val);
this.next = (next === undefined ? null : next);
}
/*
如果利用快慢指针寻找重点如果有两个中点返回后面那个直接利用靠右的判断方法 fast && fast.next
*/
function f1(head) {
let slow = head;
let fast = head;
while (fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}

View File

@ -0,0 +1,86 @@
/**
* @param {number[]} temperatures
* @return {number[]}
*/
const dailyTemperatures = function (temperatures) {
};
/*
直接利用单调栈单调栈中存入的是元素的下标这样不仅能比较元素还能通过下标设置结果
*/
function f1(temperatures) {
const res = []; // 收集结果
const stack = []; // 单调递减栈,寻找右边第一个比栈顶元素大的元素
for (let i = 0; i < temperatures.length; i++) {
// 如果栈为空或者当前元素小于等于栈顶元素,将这个元素的下标压入栈中
if (!stack.length || temperatures[i] <= temperatures[stack[stack.length - 1]]) {
stack.push(i);
} else {
// 依次比较栈顶元素,直到栈为空,或者当前元素小于等于栈顶元素
while (stack.length && temperatures[i] > temperatures[stack[stack.length - 1]]) {
const cur = stack.pop();
res[cur] = i - cur;
}
// 将当前元素下标压入栈中
stack.push(i);
}
}
// 如果栈中还有元素将其在result中的对应位置设置从0表示后面没有元素大于当前位置的元素
for (const i of stack) {
res[i] = 0;
}
return res;
}
/*
chatgpt 优化之后的写法思路没有变去除了if判断逻辑如下
遍历整个温度如果单调栈有元素并且当前元素大于栈顶元素就一直处理直到栈中没有元素或者当前元素小于等于栈顶元素
然后将当前元素压入栈中
*/
/**
* 计算每一天需要等待多少天才会有更高温度
* 如果后面没有更高的温度则返回 0
*
* @param {number[]} temperatures - 每天的温度数组
* @returns {number[]} - 返回一个数组表示每一天距离下一次更高温度的天数
*/
function f2(temperatures) {
// 初始化结果数组,默认所有值为 0表示找不到更高温度
const res = new Array(temperatures.length).fill(0);
// 用来存储下标的单调递减栈(栈顶到栈底的温度依次递减)
const stack = [];
// 遍历温度数组
for (let i = 0; i < temperatures.length; i++) {
const currentTemp = temperatures[i];
/**
* 当前温度比栈顶下标对应的温度大说明当前是更高温度的一天
* 所以可以开始出栈并记录距离
*
* 注意每个元素最多被 push pop 各一次所以总体时间复杂度是 O(n)
*/
while (
stack.length > 0
&& currentTemp > temperatures[stack[stack.length - 1]]
) {
// 栈顶元素下标
const prevIndex = stack.pop();
// 当前天i就是之前那天prevIndex等待的更高温度的那一天
res[prevIndex] = i - prevIndex;
}
// 无论如何都要把当前下标压栈,作为之后判断的基准
stack.push(i);
}
// 栈中剩下的下标所对应的位置已经默认填 0不需要再处理
return res;
}