Skip to content

Commit

Permalink
refactor(array): optimize sort-two-pointers/
Browse files Browse the repository at this point in the history
  • Loading branch information
RayJune committed Aug 28, 2024
1 parent 4da1a20 commit 21e5df4
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 44 deletions.
18 changes: 14 additions & 4 deletions src/array/sort-two-pointers/1099-two-sum-less-than-k/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@
*/

/**
* Sort + Two Pointers
* 输入一个整数数组 nums 和整数 k,返回满足两个元素之和小于 k 的最大 sum 值,如果没有则返回 -1
*
* 思路:排序 + Two Pointers 双指针
* 用排序来方便比较大小和跳过重复值,用双指针优化查找效率
*
* Time Complexity: O(n ** 2) = 遍历次数 O(n ** 2) + 排序 O(n * log(n))
* Space complexity: O(log(n)) = 排序
* Auxiliary complexity: O(log(n)) = 排序
* 其中 n 是 nums 数组的长度
*
* @param {number[]} nums
* @param {number} k
Expand All @@ -38,7 +42,7 @@ function twoSumLessThanK(nums, k) {
return -1;
}

let max = -1;
let max = -Infinity;
let left = 0;
let right = nums.length - 1;

Expand All @@ -47,14 +51,20 @@ function twoSumLessThanK(nums, k) {
const sum = nums[left] + nums[right];

if (sum < k) {
max = Math.max(sum, max);
max = Math.max(max, sum);
left += 1;
while (nums[left] === nums[left - 1]) {
left += 1;
}
} else {
right -= 1;
while (nums[right] === nums[right + 1]) {
right -= 1;
}
}
}

return max;
return max === -Infinity ? -1 : max;
}

module.exports = twoSumLessThanK;
18 changes: 12 additions & 6 deletions src/array/sort-two-pointers/15-3sum/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,16 @@
*/

/**
* Sort + Two Pointers, 注意跳过重复的数字
* 输入整数数组 nums,返回数组中所有和为 0 且不重复的三元组。注意不得包含重复的三元组
*
* 思路:
* 排序 + Two Pointers 双指针
* 用排序来比较大小并方便跳过重复元素,用双指针来优化查找的效率。注意跳过重复元素
*
* Time Complexity: O(n ** 2) = 遍历次数 O(n ** 2) + 排序 O(n * log(n))
* Space complexity: O(n) = triplets 长度 O(n) + 排序 O(log(n))
* Auxiliary complexity: O(log(n)) = 排序
* 其中 n 是 nums 数组的长度
*
* @param {number[]} nums
* @returns {number[][]}
Expand All @@ -43,16 +48,17 @@ function threeSum(nums) {
const len = nums.length;

nums.sort((a, b) => a - b);
for (let i = 0; i < len; i++) {
let left = i + 1;
let right = len - 1;

for (let i = 0; i < len - 2; i++) {
if (nums[i] > 0) {
break;
}
if (i > 0 && nums[i] === nums[i - 1]) {
if (nums[i] === nums[i - 1]) {
continue;
}

let left = i + 1;
let right = len - 1;

while (left < right) {
const sum = nums[i] + nums[left] + nums[right];

Expand Down
26 changes: 18 additions & 8 deletions src/array/sort-two-pointers/16-3sum-closest/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,30 +25,42 @@
*/

/**
* Sort + Two Pointers, 注意跳过重复的数字
* 输入一个整数数组 nums 和一个目标值 target,返回其最接近 target 的三个整数的和
*
* 思路:
* 排序 + Two Pointers 双指针
* 用排序来比较大小并方便跳过重复元素,用双指针来优化查找的效率。注意跳过重复元素
*
* Time Complexity: O(n ** 2) = 遍历次数 O(n ** 2) + 排序 O(n * log(n))
* Space complexity: O(log(n)) = 排序
* Auxiliary complexity: O(log(n)) = 排序
* 其中 n 是 nums 数组的长度
*
* @param {number[]} nums
* @param {number} target
* @returns {number}
*/
function threeSumClosest(nums, target) {
let closet = Infinity;
const len = nums.length;
let closest = Infinity;

nums.sort((a, b) => a - b);
for (let i = 0; i < len; i++) {
for (let i = 0; i < len - 2; i++) {
if (nums[i] === nums[i - 1]) {
continue;
}

let left = i + 1;
let right = len - 1;

while (left < right) {
const sum = nums[i] + nums[left] + nums[right];

if (Math.abs(sum - target) < Math.abs(closet - target)) {
closet = sum;
if (Math.abs(sum - target) < Math.abs(closest - target)) {
closest = sum;
}
if (sum === target) {
return sum;
}
if (sum > target) {
right -= 1;
Expand All @@ -60,13 +72,11 @@ function threeSumClosest(nums, target) {
while (nums[left] === nums[left - 1]) {
left += 1;
}
} else {
return target;
}
}
}

return closet;
return closest;
}

module.exports = threeSumClosest;
2 changes: 1 addition & 1 deletion src/array/sort-two-pointers/16-3sum-closest/template-zh.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* 16. 最接近的三数之和
*
* 给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。
* 给定一个包括 n 个整数的数组 nums 和一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。
* 返回这三个数的和。
* 假定每组输入只存在唯一答案。
*
Expand Down
37 changes: 24 additions & 13 deletions src/array/sort-two-pointers/18-4sum/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,16 @@
*/

/**
* Sort + Two Pointers
* 输入一个整数数组 nums 和目标值 target,返回满足四个不同的元素之和等于 target 的不重复的四元组
*
* Time Complexity: O(n ** 2) = 遍历次数 O(n ** 2) + 排序 O(n * log(n))
* 思路:
* 排序 + Two Pointers 双指针
* 用排序来比较大小并方便跳过重复元素,用双指针来优化查找的效率。注意跳过重复元素
*
* Time Complexity: O(n ** 3) = 遍历次数 O(n ** 3) + 排序 O(n * log(n))
* Space complexity: O(n) = quadruplets 长度 O(n) + 排序 O(log(n))
* Auxiliary complexity: O(log(n)) = 排序
* 其中 n 是 nums 数组的长度
*
* @param {number[]} nums
* @param {number} target
Expand All @@ -45,17 +50,23 @@ function fourSum(nums, target) {

nums.sort((a, b) => a - b);
for (let i = 0; i < len - 3; i++) {
if (i > 0 && nums[i] === nums[i - 1]) {
if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) {
break;
}
if (nums[i] === nums[i - 1]) {
continue;
}
if (nums[i] + nums[len - 3] + nums[len - 2] + nums[len - 1] < target) {
continue;
}
for (let j = i + 1; j < len - 2; j++) {
if (j !== i + 1 && nums[j] === nums[j - 1]) {
continue;
}
if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) {
if (nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) {
break;
}
if (nums[i] + nums[len - 3] + nums[len - 2] + nums[len - 1] < target) {
if (j > i + 1 && nums[j] === nums[j - 1]) {
continue;
}
if (nums[i] + nums[j] + nums[len - 2] + nums[len - 1] < target) {
continue;
}

Expand All @@ -65,7 +76,11 @@ function fourSum(nums, target) {
while (left < right) {
const sum = nums[i] + nums[j] + nums[left] + nums[right];

if (sum === target) {
if (sum > target) {
right -= 1;
} else if (sum < target) {
left += 1;
} else {
quadruplets.push([nums[i], nums[j], nums[left], nums[right]]);
left += 1;
right -= 1;
Expand All @@ -75,10 +90,6 @@ function fourSum(nums, target) {
while (nums[right] === nums[right + 1]) {
right -= 1;
}
} else if (sum > target) {
right -= 1;
} else {
left += 1;
}
}
}
Expand Down
19 changes: 13 additions & 6 deletions src/array/sort-two-pointers/259-3sum-smaller/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,33 @@
*/

/**
* Sort + Two Pointers, 需要注意的该题目隐藏条件:triplets 可以重复,不需要去重
* 输入一个整数数组 nums 和目标值 target,返回满足三个元素之和小于 target 的三元组个数
*
* 思路:排序 + 双指针
* 用排序来方便比较大小,用双指针来优化查找的效率
*
* Time Complexity: O(n ** 2) = 遍历次数 O(n ** 2) + 排序 O(n * log(n))
* Space complexity: O(log(n)) = 排序
* Auxiliary complexity: O(log(n)) = 排序
* 其中 n 是 nums 数组的长度
*
* @param {number[]} nums
* @param {number} target
* @returns {number}
*/
function threeSumSmaller(nums, target) {
if (nums.length < 3) {
return [];
}

const len = nums.length;
let count = 0;

if (len < 3) {
return 0;
}
nums.sort((a, b) => a - b);
for (let i = 0; i < len; i++) {
for (let i = 0; i < len - 2; i++) {
if (nums[i] + nums[i + 1] + nums[i + 2] > target) {
break;
}

let left = i + 1;
let right = len - 1;

Expand Down
4 changes: 2 additions & 2 deletions src/array/sort-two-pointers/259-3sum-smaller/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ test('define threeSumSmaller function', () => {
});

test('nums = [], target = 0', () => {
expect(threeSumSmaller([], 0)).toEqual([]);
expect(threeSumSmaller([], 0)).toBe(0);
});

test('nums = [0], target = 0', () => {
expect(threeSumSmaller([0], 0)).toEqual([]);
expect(threeSumSmaller([0], 0)).toBe(0);
});

test('nums = [-2, 0, 1, 3], target = 2', () => {
Expand Down
12 changes: 8 additions & 4 deletions src/array/two-pointers/167-two-sum-ii/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,24 @@
*/

/**
* Two Pointers
* 输入一个按照非递减顺序排列的整数数组 numbers,找出数组中两个数相加之和等于目标数 target,并以长度为 2 的整数数组的形式返回这两个数的下标值
*
* Time Complexity: O(n) = while 循环次数
* 思路:
* Two Pointer 双指针
* 创建 left right 分别指向头尾,利用数组是非递减顺序的性质,判断左右指针指向的值之和和 target 比大小来移动左右指针,直到得到目标值
*
* Time Complexity: O(n) = 遍历次数
* Space complexity: O(1)
* Auxiliary complexity: O(1)
* 其中 n 是 numbers 数组的长度
*
* @param {number[]} numbers
* @param {number} target
* @returns {number[]}
*/
function twoSum(numbers, target) {
const len = numbers.length;
let left = 0;
let right = len - 1;
let right = numbers.length - 1;

while (left < right) {
const sum = numbers[left] + numbers[right];
Expand Down

0 comments on commit 21e5df4

Please sign in to comment.