18. 四数之和(LeetCode)——C语言及JS
Posted 阿料
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了18. 四数之和(LeetCode)——C语言及JS相关的知识,希望对你有一定的参考价值。
一、C语言实现
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int cmp(const void *a, const void *b)
{
return *((int *)a) - *((int *)b);
}
int **fourSum(int *nums, int numsSize, int target, int *returnSize, int **returnColumnSizes)
{
if (numsSize < 4)
{
*returnSize = 0;
*returnColumnSizes = NULL;
return NULL;
}
// 先对数组进行排序
qsort(nums, numsSize, sizeof(int), cmp);
// 初始化*returnSize
*returnSize = 0;
// 分配存储四元组的数组
int **returnArr = (int **)malloc(sizeof(int *) * (numsSize - 2) * (numsSize - 2));
*returnColumnSizes = (int *)malloc(sizeof(int) * (numsSize - 2) * (numsSize - 2));
// 开始进入循环
// 由于进行了剪枝操作,因此,要用i < numsSize - 3作为终止循环的条件
// 否则会导致数组访问越界
for (int i = 0; i < numsSize - 3; i++)
{
// 剪枝操作
if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target)
{
break;
}
if (nums[i] + nums[numsSize - 3] + nums[numsSize - 2] + nums[numsSize - 1] < target)
{
continue;
}
// 首元素去重
if (i > 0 && nums[i] == nums[i - 1])
{
continue;
}
// 由于进行了剪枝操作,因此,要用j < numsSize - 2作为终止循环的条件
// 否则会导致数组访问越界
for (int j = i + 1; j < numsSize - 2; j++)
{
// 剪枝操作
if (nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target)
{
break;
}
if (nums[i] + nums[j] + nums[numsSize - 2] + nums[numsSize - 1] < target)
{
continue;
}
// 第二个元素去重
if (j > i + 1 && nums[j] == nums[j - 1])
{
continue;
}
int head = j + 1;
int tail = numsSize - 1;
while (head < tail)
{
// 左指针去重
if (head > j + 1 && nums[head] == nums[head - 1])
{
head++;
continue;
}
// 右指针去重
if (tail < numsSize - 1 && nums[tail] == nums[tail + 1])
{
tail--;
continue;
}
if (nums[i] + nums[j] + nums[head] + nums[tail] == target)
{
returnArr[*returnSize] = (int *)malloc(sizeof(int) * 4);
returnArr[*returnSize][0] = nums[i];
returnArr[*returnSize][1] = nums[j];
returnArr[*returnSize][2] = nums[head];
returnArr[*returnSize][3] = nums[tail];
(*returnColumnSizes)[*returnSize] = 4;
(*returnSize) += 1;
head++;
tail--;
}
else if (nums[i] + nums[j] + nums[head] + nums[tail] > target)
{
tail--;
}
else
{
head++;
}
}
}
}
return returnArr;
}
二、JS实现
/**
* @param {number[]} nums
* @param {number} target
* @return {number[][]}
*/
const fourSum = function (nums, target) {
const len = nums.length
if (len < 4) {
return []
}
nums.sort((x, y) => { return x - y })
const results = []
for (let i = 0; i < len; i++) {
if (i > 0 && nums[i - 1] === nums[i]) {
continue
}
// 剪枝操作
if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) {
break
}
// 剪枝操作
if (nums[i] + nums[len - 3] + nums[len - 2] + nums[len - 1] < target) {
continue
}
for (let j = i + 1; j < len; j++) {
if (j > i + 1 && nums[j - 1] === nums[j]) {
continue
}
// 剪枝操作
if (nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) {
break
}
// 剪枝操作
if (nums[i] + nums[j] + nums[len - 2] + nums[len - 1] < target) {
continue
}
let head = j + 1
let tail = len - 1
while (head < tail) {
if (head > j + 1 && nums[head - 1] === nums[head]) {
head++
continue
}
if (tail < len - 1 && nums[tail + 1] === nums[tail]) {
tail--
continue
}
if (nums[i] + nums[j] + nums[head] + nums[tail] === target) {
// 存储符合条件的四元组到结果数组
results.push([nums[i], nums[j], nums[head], nums[tail]])
// 将头指针右移,尾指针左移
head++
tail--
} else if (nums[i] + nums[j] + nums[head] + nums[tail] > target) {
tail--
} else {
head++
}
}
}
}
return results
}
- 时间复杂度:O(n^3),其中n是数组的长度。排序的时间复杂度是O(nlogn),枚举四元组的时间复杂度是 O(n^3),因此总时间复杂度为 O(n^3+nlogn)==O(n^3)。
- 空间复杂度:O(logn),其中n是数组的长度。空间复杂度主要取决于排序额外使用的空间。此外排序修改了输入数组nums,实际情况中不一定允许,因此也可以看成使用了一个额外的数组存储了数组nums 的副本并排序,空间复杂度为 O(n)。
以上是关于18. 四数之和(LeetCode)——C语言及JS的主要内容,如果未能解决你的问题,请参考以下文章