💢欢迎来到张翊尘的技术站
💥技术如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥
文章目录
- 算法每日一练 (25)
- 四数之和
- 题目描述
- 解题思路
- 解题代码
- `c/c++`
- `golang`
- `lua`
官方站点: 力扣 Leetcode
算法每日一练 (25)
四数之和
题目地址:四数之和
题目描述
给你一个由 n
个整数组成的数组 nums
,和一个目标值 target
。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]]
(若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a
、b
、c
和d
互不相同nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:
输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]
提示:
1 <= nums.length <= 200
-109 <= nums[i] <= 109
-109 <= target <= 109
解题思路
- 本题解法采用了回溯的思路。
本题可以采用双指针进行算法优化,感兴趣的小伙伴可以自行查阅。
- 由题意可知,四元组需要满足以下条件:
- 四元组中的数字可以按任意顺序排列。
- 解集不能包含重复的四元组。
- 整体代码分为了两部分:
fourSum
:这是主函数,负责初始化和调用回溯函数。traceback
:这是一个递归函数,用于通过回溯法生成所有可能的四元组。
- 首先对输入数组
nums
进行排序。排序的目的是为了方便后续去重和剪枝操作。 - 紧接着,创建辅助集合
t
和结果集合res
:t
是一个临时向量,用于存储当前递归路径中的数字。res
是最终结果,用于存储所有满足条件的四元组。
- 然后调用回溯函数
traceback
,该函数的逻辑主要分为以下几部分:- 递归终止条件
- 如果
t
的大小超过 4,则直接返回,因为四元组最多只能有 4 个数字。 - 如果
t
的大小恰好为 4,检查当前和cursum
是否等于目标值target
。如果相等,则将t
添加到结果res
中。
- 如果
- 循环遍历
- 从当前索引
index
开始,遍历数组中的每个数字。 - 去重:如果当前数字与前一个数字相同(
nums[i] == nums[i - 1]
),则跳过当前数字,避免重复解。 - 剪枝:如果当前和加上当前数字已经大于目标值,并且当前数字是非负数,则直接跳出循环,因为后续数字只会更大。
- 递归调用:将当前数字加入临时向量
t
,递归调用traceback
,并将当前索引加 1,当前和加上当前数字。 - 回溯:递归返回后,将当前数字从
t
中移除,继续尝试下一个数字。
- 从当前索引
- 递归终止条件
- 最后着重强调:本题目采用回溯法时间复杂度较高,尤其是在数组较大时,可能会导致性能瓶颈。
解题代码
c/c++
#include <vector>
#include <algorithm>
class Solution
{
public:
std::vector<std::vector<int>> fourSum(std::vector<int> &nums, int target)
{
std::vector<int> t;
std::vector<std::vector<int>> res;
std::sort(nums.begin(), nums.end());
traceback(nums, t, target, 0, 0, res);
return res;
}
private:
void traceback(std::vector<int> &nums, std::vector<int> &t,
int target, int index, long long int cursum,
std::vector<std::vector<int>> &res)
{
int sz = t.size();
if (sz > 4)
return;
if (sz == 4)
{
if (cursum == target)
res.push_back(t);
return;
}
for (int i = index; i < nums.size(); i++)
{
if (i > index && nums[i] == nums[i - 1])
continue;
if (cursum + nums[i] > target && nums[i] >= 0)
break;
t.push_back(nums[i]);
traceback(nums, t, target, i + 1, cursum + nums[i], res);
t.pop_back();
}
}
};
golang
import "sort"
func fourSum(nums []int, target int) [][]int {
res := make([][]int, 0)
sort.Ints(nums)
traceback(nums, []int{}, target, 0, 0, &res)
return res
}
func traceback(nums []int, t []int, target, index, cursum int, res *[][]int) {
sz := len(t)
if sz > 4 {
return
}
if sz == 4 {
if cursum == target {
r := make([]int, sz)
copy(r, t)
*res = append(*res, r)
}
return
}
for i := index; i < len(nums); i++ {
if i > index && nums[i] == nums[i-1] {
continue
}
if cursum+nums[i] > target && nums[i] >= 0 {
break
}
t = append(t, nums[i])
traceback(nums, t, target, i+1, cursum+nums[i], res)
t = t[:len(t)-1]
}
}
lua
local function copyTable(dst, src)
for i = 1, #src do
dst[i] = src[i]
end
end
local function traceback(nums, t, target, index, cursum, res)
local sz = #t
if sz > 4 then
return
end
if sz == 4 then
if cursum == target then
local dst = {}
copyTable(dst, t)
table.insert(res, dst)
end
return
end
for i = index, #nums do
if i > index and nums[i] == nums[i - 1] then
goto continue
end
table.insert(t, nums[i])
traceback(nums, t, target, i + 1, cursum + nums[i], res)
table.remove(t, #t)
::continue::
end
end
local function fourSum(nums, target)
local res = {}
local t = {}
table.sort(nums)
traceback(nums, t, target, 1, 0, res)
return res
end
🌺🌺🌺撒花!
如果本文对你有帮助,就点关注或者留个👍
如果您有任何技术问题或者需要更多其他的内容,请随时向我提问。