首页 > 其他分享 >力扣18:四数之和(双指针+剪枝)

力扣18:四数之和(双指针+剪枝)

时间:2023-10-12 11:27:29浏览次数:41  
标签:剪枝 四数 target nums int 力扣 length right left

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

  • 0 <= a, b, c, d < n
  • abc 和 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

拿到题目最快想到的常规思路:对前两个数进行循环,后两个数用双指针,中间保证不重复

 1 class Solution
 2 {
 3 public:
 4     bool isOverflow(int x, int y) //若要判断溢出,只需判断两数同号的情况即可
 5     {
 6         if (x <= 0 && y <= 0 && x < INT32_MIN - y)
 7             return true;
 8         if (x > 0 && y > 0 && x > INT32_MAX - y)
 9             return true;
10         return false;
11     }
12     vector<vector<int>> fourSum(vector<int> &nums, int target)
13     {
14         vector<vector<int>> result;
15         if (nums.size() < 4)
16             return result;
17         sort(nums.begin(), nums.end());
18         for (int i = 0; i < nums.size() - 3; ++i)
19         {
20             if (i > 0 && nums[i] == nums[i - 1])
21                 continue;
22             for (int j = i + 1; j < nums.size() - 2; ++j)
23             {
24                 if (j > i + 1 && nums[j] == nums[j - 1])
25                     continue;
26                 int right = nums.size() - 1;
27                 for (int left = j + 1; left < nums.size() - 1; ++left)
28                 {
29                     if (left > j + 1 && nums[left] == nums[left - 1])
30                     {
31                         continue;
32                     }
33                     while (left < right)
34                     {
35                         long sum = (long)nums[i] + nums[j] + nums[left] + nums[right]; //防止溢出,先把第一个元素转成long型
36 
37                         if (sum == target)
38                         {
39                             result.push_back({nums[i], nums[j], nums[left], nums[right]});
40                             break;
41                         }
42                         else if (sum > target)
43                             right--;
44                         else
45                             break;
46                     }
47                 }
48             }
49         }
50         return result;
51     }
52 };

 

这个写法可以在力扣ac,但效率低了,官方题解给了如下剪枝思路。

 剪枝后:

 1 class Solution
 2 {
 3 public:
 4     vector<vector<int>> fourSum(vector<int> &nums, int target)
 5     {
 6         vector<vector<int>> result;
 7         int length = nums.size();
 8         if (length < 4)
 9             return result;
10         sort(nums.begin(), nums.end());
11         for (int i = 0; i < length - 3; ++i)
12         {
13             if (i > 0 && nums[i] == nums[i - 1])
14                 continue;
15             if ((long)nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target)
16                 break;
17             if ((long)nums[i] + nums[length - 1] + nums[length - 2] + nums[length - 3] < target)
18                 continue;
19             ;
20             for (int j = i + 1; j < length - 2; ++j)
21             {
22                 if (j > i + 1 && nums[j] == nums[j - 1])
23                     continue;
24                 if ((long)nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target)
25                     break;
26                 if ((long)nums[i] + nums[j] + nums[length - 1] + nums[length - 2] < target)
27                     continue;
28                 int right = length - 1;
29                 for (int left = j + 1; left < length - 1; ++left)
30                 {
31                     if (left > j + 1 && nums[left] == nums[left - 1])
32                     {
33                         continue;
34                     }
35                     while (left < right)
36                     {
37                         long sum = (long)nums[i] + nums[j] + nums[left] + nums[right];
38 
39                         if (sum == target)
40                         {
41                             result.push_back({nums[i], nums[j], nums[left], nums[right]});
42                             break;
43                         }
44                         else if (sum > target)
45                             right--;
46                         else
47                             break;
48                     }
49                 }
50             }
51         }
52         return result;
53     }
54 };

 

标签:剪枝,四数,target,nums,int,力扣,length,right,left
From: https://www.cnblogs.com/coderhrz/p/17759057.html

相关文章

  • 【力扣】9.回文数
    转化成字符串之后进行判断的思路很简单咱就不写了。做一下进阶:你能不将整数转为字符串来解决这个问题吗?我最初的思路:用二进制掩码异或判断。学到了新知识:GCC内建函数__builtin_clz(CountLeadingZeros,统计前导零个数)->获取二进制正数最大有效位。细节:注意掩码获取时int最高位1......
  • 力扣-2367-算术三元组的数目
    给你一个下标从0开始、严格递增的整数数组nums和一个正整数diff。如果满足下述全部条件,则三元组(i,j,k)就是一个算术三元组:i<j<k,nums[j]-nums[i]==diff且nums[k]-nums[j]==diff返回不同算术三元组的数目。 示例1:输入:nums=[0,1,4,6,7,10],di......
  • 力扣-2744-最大字符串配对数目
    给你一个下标从0开始的数组words,数组中包含互不相同的字符串。如果字符串words[i]与字符串words[j]满足以下条件,我们称它们可以匹配:字符串words[i]等于words[j]的反转字符串。0<=i<j<words.length请你返回数组words中的最大匹配数目。注意,每个字符串最......
  • 力扣-2006-差的绝对值为 K 的数对数目
    给你一个整数数组nums和一个整数k,请你返回数对(i,j)的数目,满足i<j且|nums[i]-nums[j]|==k。|x|的值定义为:如果x>=0,那么值为x。如果x<0,那么值为-x。示例1:输入:nums=[1,2,2,1],k=1输出:4解释:差的绝对值为1的数对为:-[1,2,2,1]-[1,2,2,1]-......
  • 力扣-2574-左右元素和的差值
    给你一个下标从0开始的整数数组nums,请你找出一个下标从0开始的整数数组answer,其中:answer.length==nums.lengthanswer[i]=|leftSum[i]-rightSum[i]|其中:leftSum[i]是数组nums中下标i左侧元素之和。如果不存在对应的元素,leftSum[i]=0。rightSum[i]是数组n......
  • 力扣-2114-句子中的最多单词数
    一个句子由一些单词以及它们之间的单个空格组成,句子的开头和结尾不会有多余空格。给你一个字符串数组sentences,其中sentences[i]表示单个句子。请你返回单个句子里单词的最多数目。 示例1:输入:sentences=["aliceandbobloveleetcode","ithinksotoo","......
  • 八股乱背,力扣不会!下辈子远离计算机
    昨天接到了许久未见老友的一个电话,片刻寒暄之后聊到主题:朋友受人之托,帮人打听家中小孩选择计算机专业之后的就业问题的。既然是朋友,自然不敢欺瞒,就把目前计算机就业相关的真实情况如实“汇报”了。那么计算机行业现状如何呢?大家看这幅图自然就明白了:杭州一家不知名的公司(我从......
  • 力扣刷题笔记-08 字符串转整数
    08字符串转整数属于对字符串进行操作的问题百无一用是情深问题字符串里有数字,空格,正负号等,需要先过滤出来在这道题目里,我们通常考虑字符串的组合是“空格+正负号+数字”,一开始我想可能是“正负号+空格+数字”,但是这样的组合根本不可能是数字啊,没什么意义。循环条件for循......
  • 力扣刷题笔记-07 整数反转
    07整数反转狗看了都摇头的年纪,纯爱战士一败涂地。怎么反转temp用来保存个位数res用来保存当前结果123,取模运算,这样就可以获得最后一位。比如对123%10,得到temp=3.判断res是不是溢出(重点)如果没有溢出,res扩大十倍,再加上个位数,就相当于是反转了。res=res*10+temp;返回......
  • 力扣-2427-公因子的数目
    给你两个正整数a和b,返回a和b的公因子的数目。如果x可以同时整除a和b,则认为x是a和b的一个公因子。 示例1:输入:a=12,b=6输出:4解释:12和6的公因子是1、2、3、6。示例2:输入:a=25,b=30输出:2解释:25和30的公因子是1、5。提示:1<=a,......