尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

7.LeetCode算法习题讲解--双指针--四数之和

7.LeetCode算法习题讲解--双指针--四数之和 一.题目习题链接18. 四数之和 - 力扣LeetCode二.题目分析给定数组nums和目标值target寻找所有不重复的四元组[nums[a], nums[b], nums[c], nums[d]]满足下标约束0 ≤ a,b,c,d n四个下标互不相等数值条件nums[a]nums[b]nums[c]nums[d] target结果要求不能包含重复四元组返回顺序随意⚠️ 重点区分下标不同但元素组合一样 → 视为重复需要去重。 例[2,2,2,2]只能输出一组答案。这里的题目分析与前面三数之和的讲解一样三.算法原理讲解解法一暴力枚举 去重这里我就不过多介绍了可以看上一节的三数之和解法二双指针 去重思路与三数之和的思路完全相同三数之和是固定一个数利用双指针进行查找这里也是类似固定两个数利用双指针进行查找这里需要注意的是要进行三次去重四.编写代码这里有一个注意的点红色框里面会出现数据溢出的风险所以这里需要转化为long long注这里的数组长度要储存下来nums.size()返回的类型是size_t它是无符号整数unsigned无符号数永远 ≥ 0不能存负数。一旦做减法结果小于 0不会得到‑1而是发生「无符号下溢」自动变成一个非常大的正数。class Solution { public: vectorvectorint fourSum(vectorint nums, int target) { vectorvectorint ret; sort(nums.begin(), nums.end()); int n nums.size(); for(int i 0; i n - 3;) // 固定数a { int a i; for(int j i 1; j n - 2;) // 固定数b { int b j, left j 1, right n - 1; while(left right) { // 注意数据溢出 long long num (long long)nums[a] nums[b] nums[left] nums[right]; if(num target) { right--; } else if(num target) { left; } else { ret.push_back({nums[a], nums[b], nums[left], nums[right]}); left; right--; // 去重一 while(left right nums[left] nums[left - 1]) left; while(left right nums[right] nums[right 1]) right--; } } // 去重二 j; while(j n - 2 nums[j] nums[j - 1]) j; } // 去重三 i; while(i n - 3 nums[i] nums[i - 1]) i; } return ret; } };两段代码结果不一样的根源vectorint ret(1,2); // size() 1 cout (0 ret.size() - 3) endl; //①输出1true int n ret.size() - 3; //②n -2ret.size()返回size_t64 位无符号 unsigned第①处0 ret.size()-3ret.size()→size_t(1)无符号1‑3全部操作数都是无符号触发无符号下溢1 -3 -2但是无符号不能存负数按照模 \(2^{64}\) 换算得到巨大无符号数18446744073709551614比较0 这个超大无符号数→ 条件成立输出1(true)整个表达式全部按size_t无符号运算没有转换成 int。第②处int n ret.size() - 3;同样先算ret.size()-3得到那个巨大的size_t大数把这个巨大无符号数赋值给 int 类型变量 n大数截断转换成有符号 int结果变成‑2⚠️关键点下溢发生在无符号运算那一步赋值给 int 只是把巨大数强制截断转回负数不是减法得到‑2
返回列表