feat: double-point 11,15,125,167,392

This commit is contained in:
LouisFonda 2025-04-02 23:26:39 +08:00
parent 07a3353880
commit eb9dee4335
Signed by: yigencong
GPG Key ID: 29CE877CED00E966
5 changed files with 257 additions and 0 deletions

View File

@ -0,0 +1,79 @@
/**
* https://leetcode.cn/problems/container-with-most-water/?envType=study-plan-v2&envId=top-interview-150
* @param {number[]} height
* @return {number}
*/
const maxArea = function (height) {
};
/*
暴力解法组合所有的可能得出最大的面积,会超时
*/
function f1(height) {
const n = height.length;
let mArea = -Infinity;
let cArea;// 计算的面积
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
cArea = Math.min(height[i], height[j]) * (j - i);
if (cArea > mArea) mArea = cArea;
}
}
return mArea;
}
/*
使用双指针定义一个left和一个right首先判断height[left] height[right]两者直接谁底因为盛水量是底的那一端决定的
计算当前值并且使用mArea保存起来这个值之后继续移动地的那一侧假设height[right]比height[left]那么就right--然后继续
比较反之left++循环条件为left < right
*/
function f2(height) {
let mArea = -Infinity; // 能盛水的最大面积
let cArea; // 缓存计算的面积,避免重复计算
let left = 0;
let right = height.length - 1;
while (left < right) {
cArea = Math.min(height[left], height[right]) * [right - left];
if (cArea > mArea) mArea = cArea;
if (height[right] > height[left]) { // 如果右端比左端高,移动底的那一段
left++;
} else {
right--;
}
}
return mArea;
}
/*
优化假设当前右边比左边高那么我们应该移动左边面积不仅仅是由两端高度较低的那一端决定的同时也由right - left这个底部决定
在移动的过程中这个底部一定是不断变小的所以当这个决定性的最短边小于之前的最短边那就没必要计算了100%小于之前的结果所以
应该定义一个记录有效边高度的变量用来跳过不必要的判断以此提高小效率
*/
function f2(height) {
let mArea = -Infinity; // 能盛水的最大面积
let cArea; // 缓存计算的面积,避免重复计算
let left = 0;
let right = height.length - 1;
while (left < right) {
cArea = Math.min(height[left], height[right]) * (right - left);
if (cArea > mArea) mArea = cArea;
if (height[left] < height[right]) {
let prevLeft = height[left];
// 增加跳过无效left的逻辑
while (left < right && height[left] <= prevLeft) {
left++;
}
} else {
let prevRight = height[right];
// 增加跳过无效right的逻辑
while (left < right && height[right] <= prevRight) {
right--;
}
}
}
return mArea;
}

View File

@ -0,0 +1,85 @@
/**
* https://leetcode.cn/problems/3sum/?envType=study-plan-v2&envId=top-interview-150
* @param {number[]} nums
* @return {number[][]}
*/
const threeSum = function (nums) {
};
/*
先对数组排序然后遍历数组如果遍历的当前元素大于零则表示后面的元素不可能组合在一起和为0如果当前元素小于零那么就对剩余的所有元素
使用两数之和的方法寻找target=当前元素的相反数如果找到就返回这几个元素然后遍历下一个元素
*/
function f1(nums) {
nums.sort((a, b) => a - b); // 先对数组排序
const result = []; // 结果数组
for (let i = 0; i < nums.length; i++) {
// 如果当前元素大于零直接结束循环,后面的查找没意义
if (nums[i] > 0) break;
// 如果当前元素等于前面的元素也跳过
if (i > 0 && nums[i] === nums[i - 1]) continue;
// 按照两数之和的方法寻找nums[i] 的相反数也就是target == -nums[i]
let left = i + 1;
let right = nums.length - 1;
while (left < right) {
const target = nums[left] + nums[right];
if (target === -nums[i]) {
result.push([nums[i], nums[left], nums[right]]); // 把查到的结果放入结果集中
// 继续寻找往下找
// 跳过重复元素
while (left < right && nums[left] === nums[left + 1]) left++;
while (left < right && nums[right] === nums[right - 1]) right--;
left++;
right--;
continue;
}
if (target < -nums[i]) {
left++;
continue;
}
if (target > -nums[i]) {
right--;
continue;
}
}
}
return result;
}
/*
使用ifelse 减少判断逻辑
*/
function f2(nums) {
nums.sort((a, b) => a - b); // 先对数组排序
const result = []; // 结果数组
for (let i = 0; i < nums.length - 2; i++) {
// 如果当前元素大于零直接结束循环,后面的查找没意义
if (nums[i] > 0) break;
// 如果当前元素等于前面的元素也跳过
if (i > 0 && nums[i] === nums[i - 1]) continue;
let left = i + 1;
let right = nums.length - 1;
while (left < right) {
const sum = nums[i] + nums[left] + nums[right];
if (sum === 0) {
result.push([nums[i], nums[left], nums[right]]);
// 跳过重复元素
while (left < right && nums[left] === nums[left + 1]) left++;
while (left < right && nums[right] === nums[right - 1]) right--;
left++;
right--;
} else if (sum < 0) {
left++;
} else {
right--;
}
}
}
return result;
}

View File

@ -0,0 +1,27 @@
/**
* https://leetcode.cn/problems/two-sum-ii-input-array-is-sorted/?envType=study-plan-v2&envId=top-interview-150
* @param {number[]} numbers
* @param {number} target
* @return {number[]}
*/
const twoSum = function (numbers, target) {
};
/*
利用数组有序的特性使用首位指针不断的缩小范围找到可能的值
*/
function f1(numbers, target) {
let left = 0;
let right = numbers.length - 1;
const temp = Infinity;
while (left < right) {
const temp = numbers[left] + numbers[right];
if (temp == target) {
return [left + 1, right + 1];
} if (temp > target) {
right--;
} else { left++; }
}
return []; // 没有找到,不过这个题目测试用例保证一定有解
}

View File

@ -0,0 +1,9 @@
/**
* https://leetcode.cn/problems/text-justification/description/?envType=study-plan-v2&envId=top-interview-150
* @param {string[]} words
* @param {number} maxWidth
* @return {string[]}
*/
const fullJustify = function (words, maxWidth) {
};

View File

@ -0,0 +1,57 @@
/**
* https://leetcode.cn/problems/longest-substring-without-repeating-characters/?envType=study-plan-v2&envId=top-interview-150
* @param {string} s
* @return {number}
*/
const lengthOfLongestSubstring = function (s) {
};
/*
暴力解法定义左右两个指针左指针表示这个无重复字符串的开始位置右指针表示无重复字符的结束位置右指针不停的往右边遍历
每一个字符之后再用一个循环来查找这个字符在左指针到右指针直接是否发生了重复如果发生重复就把左指针移动到这个重复字符的
后一个位置之后继续移动右指针
*/
function f1(s) {
if (s.length === 0) return 0;
if (s.length === 1) return 1;
let left = 0; // 定义左指针
let maxLen = 0; // 最长长度
for (let right = 1; right < s.length; right++) {
// 从left到right,检查当前字符是否发生了重复
for (let i = left; i < right; i++) {
if (s[i] === s[right]) {
left = i + 1;
break;
}
}
maxLen = Math.max(maxLen, right - left + 1);
}
return maxLen;
}
/*
利用hash优化我们在查找left到right直接是否有重复字符串的时使用的是遍历这样的化效率比较底可以使用哈希表来储存每一个字符值为
对应的下标如果当前字符为哈希表中的某一个值直接取出下标赋值给left否则继续移动right添加新的值到哈希表中
*/
function f2(s) {
if (s.length === 0) return 0;
let left = 0; // 定义左指针
let maxLen = 0; // 最长长度
const map = new Map(); // 用于存储字符及其最新位置
for (let right = 0; right < s.length; right++) {
// 如果字符在哈希表中出现过,并且它的索引大于等于 left说明当前窗口有重复字符
if (map.has(s[right]) && map.get(s[right]) >= left) {
// 将 left 移动到重复字符的下一个位置
left = map.get(s[right]) + 1;
}
// 更新字符的最新位置
map.set(s[right], right);
// 计算当前窗口的长度并更新最大值
maxLen = Math.max(maxLen, right - left + 1);
}
return maxLen;
}