天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 441|回复: 14

多数之和问题(nSum)

 火... [复制链接]

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
发表于 2024-3-7 10:34:03 | 显示全部楼层 |阅读模式
  1. ```C++
  2. vector<int> twoSum(vector<int>& nums, int target) {
  3.         // 先对数组排序
  4.         sort(nums.begin(), nums.end());
  5.         // 左右指针
  6.         int lo = 0, hi = nums.size() - 1;
  7.         while (lo < hi) {
  8.             int sum = nums[lo] + nums[hi];
  9.             // 根据 sum 和 target 的比较,移动左右指针
  10.             if (sum < target) {
  11.                 lo++;
  12.             } else if (sum > target) {
  13.                 hi--;
  14.             } else if (sum == target) {
  15.                 return {nums[lo], nums[hi]};
  16.             }
  17.         }
  18.         return {};
  19. ```
复制代码

  1. ```C++
  2. vector<vector<int>> twoSumTarget(vector<int>& nums, int target {
  3.         // 先对数组排序
  4.         sort(nums.begin(), nums.end());
  5.         vector<vector<int>> res;
  6.         int lo = 0, hi = nums.size() - 1;
  7.         while (lo < hi) {
  8.             int sum = nums[lo] + nums[hi];
  9.             // 根据 sum 和 target 的比较,移动左右指针
  10.             if      (sum < target) lo++;
  11.             else if (sum > target) hi--;
  12.             else {
  13.                 res.push采用back({lo, hi});
  14.                 lo++; hi--;
  15.             }
  16.         }
  17.         return res;
  18.     }
  19. ```
复制代码


  1. ```C++
  2. while (lo < hi) {
  3.         int sum = nums[lo] + nums[hi];
  4.         // 记录索引 lo 和 hi 最初对应的值
  5.         int left = nums[lo], right = nums[hi];
  6.         if (sum < target)      lo++;
  7.         else if (sum > target) hi--;
  8.         else {
  9.             res.push采用back({left, right});
  10.             // 跳过所有重复的元素
  11.             while (lo < hi && nums[lo] == left) lo++;
  12.             while (lo < hi && nums[hi] == right) hi--;
  13.         }
  14.     }
  15.     }
  16. ```
复制代码

 

 

 

 

多数之和问题(nSum)

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
 楼主| 发表于 2024-3-7 10:34:11 | 显示全部楼层
  1. ```C++
  2. vector<vector<int>> threeSumTarget(vector<int>& nums, int target) {
  3.         // 数组得排个序
  4.         sort(nums.begin(), nums.end());
  5.         int n = nums.size();
  6.         vector<vector<int>> res;
  7.         // 穷举 threeSum 的第一个数
  8.         for (int i = 0; i < n; i++) {
  9.             // 对 target - nums[i] 计算 twoSum
  10.             vector<vector<int>>
  11.                     tuples = twoSumTarget(nums, i + 1, target - nums[i]);
  12.             // 如果存在满足条件的二元组,再加上 nums[i] 就是结果三元组
  13.             for (vector<int>& tuple : tuples) {
  14.                 tuple.push采用back(nums[i]);
  15.                 res.push采用back(tuple);
  16.             }
  17.             // 跳过第一个数字重复的情况,否则会出现重复结果
  18.             while (i < n - 1 && nums[i] == nums[i + 1]) i++;
  19.         }
  20.         return res;
  21.     }
  22. ```
复制代码

 

 

 

 

多数之和问题(nSum)

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
 楼主| 发表于 2024-3-7 10:34:21 | 显示全部楼层
  1. ```C++
  2. /* 注意:调用这个函数之前一定要先给 nums 排序 */
  3.     vector<vector<int>> nSumTarget(
  4.             vector<int>& nums, int n, int start, int target) {
  5.         int sz = nums.size();
  6.         vector<vector<int>> res;
  7.         // 至少是 2Sum,且数组大小不应该小于 n
  8.         if (n < 2 || sz < n) return res;
  9.         // 2Sum 是 base case
  10.         if (n == 2) {
  11.             // 双指针那一套操作
  12.             int lo = start, hi = sz - 1;
  13.             while (lo < hi) {
  14.                 int sum = nums[lo] + nums[hi];
  15.                 int left = nums[lo], right = nums[hi];
  16.                 if (sum < target) {
  17.                     while (lo < hi && nums[lo] == left) lo++;
  18.                 } else if (sum > target) {
  19.                     while (lo < hi && nums[hi] == right) hi--;
  20.                 } else {
  21.                     res.push采用back({left, right});
  22.                     while (lo < hi && nums[lo] == left) lo++;
  23.                     while (lo < hi && nums[hi] == right) hi--;
  24.                 }
  25.             }
  26.         } else {
  27.             // n > 2 时,递归计算 (n-1)Sum 的结果
  28.             for (int i = start; i < sz; i++) {
  29.                 vector<vector<int>>
  30.                         sub = nSumTarget(nums, n - 1, i + 1, target - nums[i]);
  31.                 for (vector<int>& arr : sub) {
  32.                     // (n-1)Sum 加上 nums[i] 就是 nSum
  33.                     arr.push采用back(nums[i]);
  34.                     res.push采用back(arr);
  35.                 }
  36.                 while (i < sz - 1 && nums[i] == nums[i + 1]) i++;
  37.             }
  38.         }
  39.         return res;
  40.     }
  41. ```
复制代码

 

 

 

 

多数之和问题(nSum)
  • TA的每日心情
    开心
    昨天 06:36
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    105

    主题

    11

    回帖

    1308

    积分

    管理员

    积分
    1308
    QQ
    发表于 2024-3-7 21:06:03 | 显示全部楼层
    1. vector<vector<int>> nSumTarget(vector<int>& nums, int n, int start, int target){
    2.         int sz = nums.size();
    3.         vector<vector<int>> res;
    4.         //至少是2Sum,且数组大小应该小于n
    5.         if(n < 2 || sz < n) return res;
    6.         //2Sum
    7.         if(n == 2){
    8.                 int l = start;
    9.                 int r = nums.size() - 1;
    10.             while(l < r){
    11.                     int sum = nums[l] + nums[r];
    12.                     int left = nums[l];
    13.                     int right = nums[r];
    14.                     if(sum == target){
    15.                             res.push采用back({left, right});
    16.                             //下面两行代码可以保证不出现重复的元素
    17.                             while(l < r && nums[l] == left) l++;
    18.                             while(l < r && nums[r] == right) r--;                       
    19.                     }else if(sum > target){
    20.                             //直接r--也可以,下面这行代码是对r--进行了优化
    21.                             while(l < r && nums[r] == right) r--;       
    22.                     }else if(sum < target){
    23.                             while(l < r && nums[l] == left) l++;
    24.                     }
    25.             }
    26.         }else{
    27.                 //n > 2 递归的计算(n - 1)Sum
    28.                 for(int i = start; i < sz; i++){
    29.                         vector<vector<int>> sub = nSumTarget(nums, n - 1, i + 1, target - nums[i]);
    30.                         int num = sub.size();
    31.                         for(int j = 0; j < num; j++){
    32.                                 sub[j].push采用back(nums[i]);
    33.                                 res.push采用back(sub[j]);
    34.                         }
    35.                         while(i < sz - 1 && nums[i] == nums[i + 1]) i++;
    36.                 }
    37.         }
    38.         return res;       
    39. }
    复制代码

     

     

     

     

    多数之和问题(nSum)
  • TA的每日心情
    开心
    昨天 06:36
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    105

    主题

    11

    回帖

    1308

    积分

    管理员

    积分
    1308
    QQ
    发表于 2024-3-7 21:06:15 | 显示全部楼层
    1. class Solution {
    2. public:
    3.     vector<vector<int>> threeSum(vector<int>& nums) {
    4.         return threeSumTarget(nums, 0);        
    5.     }
    6.     //返回3数之和为target的所有组合并且组合不能重复
    7.     vector<vector<int>> threeSumTarget(vector<int>& nums, int target) {
    8.         vector<vector<int>> res;
    9.         sort(nums.begin(), nums.end());
    10.         int size = nums.size();
    11.         
    12.         for(int i = 0; i < size; i++){
    13.             vector<vector<int>> tuples = twoSumTarget(nums, i + 1, target - nums[i]);
    14.             
    15.             //如果存在满足条件的二元组,再加上nums[i]即为一个结果
    16.             int n = tuples.size();
    17.             for(int j = 0; j < n; j++){
    18.                 tuples[j].push采用back(nums[i]);
    19.                 res.push采用back(tuples[j]);
    20.             }
    21.             //跳过第一个数字重复的情况,否则会出现重复的结果
    22.             while(i < size - 1 && nums[i] == nums[i + 1]){
    23.                 i++;
    24.             }
    25.         }
    26.         return res;
    27.     }
    28.     vector<vector<int>> twoSumTarget(vector<int>& nums, int start, int target){
    29.             sort(nums.begin(), nums.end());
    30.             vector<vector<int>> res;
    31.             int l = start;
    32.             int r = nums.size() - 1;
    33.             while(l < r){
    34.                     int sum = nums[l] + nums[r];
    35.                     int left = nums[l];
    36.                     int right = nums[r];
    37.                     if(sum == target){
    38.                             res.push采用back({left, right});
    39.                             //下面两行代码可以保证不出现重复的元素
    40.                             while(l < r && nums[l] == left) l++;
    41.                             while(l < r && nums[r] == right) r--;                       
    42.                     }else if(sum > target){
    43.                             //直接r--也可以,下面这行代码是对r--进行了优化
    44.                             while(l < r && nums[r] == right) r--;       
    45.                     }else if(sum < target){
    46.                             while(l < r && nums[l] == left) l++;
    47.                     }
    48.             }
    49.             return res;
    50.     }
    51. };
    复制代码

     

     

     

     

    多数之和问题(nSum)
  • TA的每日心情
    开心
    昨天 06:36
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    105

    主题

    11

    回帖

    1308

    积分

    管理员

    积分
    1308
    QQ
    发表于 2024-3-7 21:06:24 | 显示全部楼层
    1. vector<vector<int>> twoSumTarget(vector<int>& nums, int target){
    2.         sort(nums.begin(), nums.end());
    3.         vector<vector<int>> res;
    4.         int l = 0;
    5.         int r = nums.size() - 1;
    6.         while(l < r){
    7.                 int sum = nums[l] + nums[r];
    8.                 int left = nums[l];
    9.                 int right = nums[r];
    10.                 if(sum == target){
    11.                         res.push采用back({left, right});
    12.                         //下面两行代码可以保证不出现重复的元素
    13.                         while(l < r && nums[l] == left) l++;
    14.                         while(l < r && nums[r] == right) r--;                       
    15.                 }else if(sum > target){
    16.                         //直接r--也可以,下面这行代码是对r--进行了优化
    17.                         while(l < r && nums[r] == right) r--;       
    18.                 }else if(sum < target){
    19.                         while(l < r && nums[l] == left) l++;
    20.                 }
    21.         }
    22.         return res;
    23. }
    复制代码

     

     

     

     

    多数之和问题(nSum)
  • TA的每日心情
    开心
    昨天 06:36
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    105

    主题

    11

    回帖

    1308

    积分

    管理员

    积分
    1308
    QQ
    发表于 2024-3-8 17:26:22 | 显示全部楼层
    1. typedef vector<vector<int>::iterator> Manager;
    2. class Solution {
    3. public:
    4.   vector<vector<int>> nSum(vector<int> &nums, int target, int n) {
    5.     if (nums.size() < n) return {}; // 特判,数组长度小于n时返回空
    6.     sort(nums.begin(), nums.end()); // 数组排序
    7.     Manager iters(n - 1, nums.begin()); // 指针数组
    8.     vector<vector<int>> result; // 返回值
    9.     vector<int> record; // 记录栈
    10.     int cur采用n = n; // 当前所求的是几数之和
    11.     // 当求完i数和(1. 遍历完;2. 从**it开始的i个数大于target)后,回溯到求i+1数和
    12.     auto back = [&record, &target](Manager::iterator &it) {
    13.       target += record.back();
    14.       record.pop采用back();
    15.       --it;
    16.     };
    17.     for (auto it = iters.begin();; ++*it) {
    18.       cur采用n = n - record.size(); // 当前所求为cur采用n数之和
    19.       // cur采用n数之和遍历完,回溯
    20.       if (*it > nums.end() - cur采用n) {
    21.         if (cur采用n == n) break;
    22.         back(it);
    23.         continue;
    24.       }
    25.       // 剪枝,排除不可能的情况
    26.       if (accumulate(*it, *it + cur采用n, 0) > target) {
    27.         if (cur采用n == n) break; // 直接返回结果
    28.         back(it);
    29.         continue;
    30.       }
    31.       // 求2数之和
    32.       if (cur采用n == 2) {
    33.         for (auto left = *it, right = nums.end() - 1; left < right;) {
    34.           int sum = *left + *right;
    35.           if (sum < target) {
    36.             do { ++left; } while (left < right && *left == *(left - 1));
    37.           } else if (sum > target) {
    38.             do { --right; } while (left < right && *right == *(right + 1));
    39.           } else {
    40.             record.push采用back(*left);
    41.             record.push采用back(*right);
    42.             result.push采用back(record);
    43.             record.pop采用back();
    44.             record.pop采用back();
    45.             do { ++left; } while (left < right && *left == *(left - 1));
    46.             do { --right; } while (left < right && *right == *(right + 1));
    47.           }
    48.         }
    49.         back(it);
    50.         continue;
    51.       }
    52.       // 去重
    53.       auto start = cur采用n == n ? *it == nums.begin() : *it == *(it - 1) + 1;
    54.       if (!start && **it == *(*it - 1)) continue;
    55.       // 优化,设当前求i数之和,从nums中从右往左选取i-1个数,计算i数之和,如果小于targe则右移it
    56.       if (**it + accumulate(nums.end() - cur采用n + 1, nums.end(), 0) < target) continue;
    57.       // 由求cur采用n数之和转换为求cur采用n - 1数之和
    58.       record.push采用back(**it);
    59.       target -= **it; // 记录当前选取的数
    60.       ++it; // 右移it
    61.       *it = *(it - 1); // 初始化下轮迭代的it
    62.     }
    63.     return result;
    64.   }
    65. };
    66. https://leetcode.cn/problems/4sum/solutions/593183/nshu-zhi-he-by-zhiyuanlck-x98k/
    复制代码

     

     

     

     

    多数之和问题(nSum)
  • TA的每日心情
    开心
    昨天 06:36
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    105

    主题

    11

    回帖

    1308

    积分

    管理员

    积分
    1308
    QQ
    发表于 2024-3-8 17:30:51 | 显示全部楼层
    1. class Solution {
    2.     vector<vector<int>> nSum(vector<int>& nums, int target, int count) {
    3.         if (nums.size() < count || count < 2)
    4.             return {};
    5.         sort(nums.begin(), nums.end());
    6.         vector<vector<int>> result;
    7.         vector<int> temp采用result(count, 0);
    8.         vector<int> indices(count - 2, 0);          // 保存前 n - 2 个数的指针
    9.         iota(indices.begin(), indices.end(), 0);    // 给前 n - 2 个指针初始化为 0, 1, 2, ..., n - 3
    10.         while (true)
    11.         {
    12.             // 计算两数之和的目标值 (最终的目标值减去前 n - 2 个指针的值的和)
    13.             long temp采用target = target;
    14.             for (int i = 0; i < count - 2; i++)
    15.                 temp采用target -= nums[indices[i]];
    16.             
    17.             // 求解两数之和问题
    18.             int left = indices.back() + 1;
    19.             int right = nums.size() - 1;
    20.             while (left < right)
    21.             {
    22.                 if (nums[left] + nums[right] == temp采用target)
    23.                 {
    24.                     for (int i = 0; i < count - 2; i++)
    25.                         temp采用result[i] = nums[indices[i]];
    26.                     temp采用result[count - 2] = nums[left];
    27.                     temp采用result[count - 1] = nums[right];
    28.                     result.push采用back(temp采用result);
    29.                     while (left < right && nums[left] == nums[left + 1])
    30.                         left++;
    31.                     while (left < right && nums[right] == nums[right - 1])
    32.                         right--;
    33.                     left++;
    34.                     right--;
    35.                 }
    36.                 else
    37.                 {
    38.                     if (nums[left] + nums[right] > temp采用target)
    39.                     {
    40.                         right--;
    41.                     }
    42.                     else
    43.                     {
    44.                         left++;
    45.                     }
    46.                 }
    47.             }
    48.             // 更新前 n - 2 个指针
    49.             for (int i = 0; i < count - 2; i++)
    50.             {
    51.                 int& cur = indices[count - 3 - i];
    52.                 for (int origin = nums[cur]; cur < nums.size() - 2 - i && nums[cur] == origin; ++cur);
    53.                 if (cur < nums.size() - 2 - i)
    54.                 {
    55.                     for (int j = 0; j < i; j++)
    56.                     {
    57.                         indices[count - 2 - i + j] = indices[count - 3 - i + j] + 1;
    58.                     }
    59.                     break;
    60.                 }
    61.             }
    62.             if (count > 2 && indices.front() > nums.size() - count)
    63.             {
    64.                 break;
    65.             }
    66.         }
    67.         return result;
    68.     }
    69. public:
    70.     vector<vector<int>> fourSum(vector<int>& nums, int target) {
    71.         //求解四数之和
    72.         return nSum(nums, target, 4);
    73.     }
    74. };
    75. 链接:https://leetcode.cn/problems/4sum/solutions/
    复制代码

     

     

     

     

    多数之和问题(nSum)
  • TA的每日心情
    开心
    昨天 06:36
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    105

    主题

    11

    回帖

    1308

    积分

    管理员

    积分
    1308
    QQ
    发表于 2024-3-8 17:35:03 | 显示全部楼层
    1. class Solution {
    2. public:
    3.     vector<vector<int>> twoSum(vector<int>& nums, long target, int left){
    4.         int right = nums.size() - 1;
    5.         long sum2;
    6.         vector<vector<int>> ans;
    7.         while(left < right){
    8.             sum2 = (long) nums[left] + nums[right];
    9.             if(sum2 > target){
    10.                 right--;
    11.             }else if(sum2 < target){
    12.                 left++;
    13.             }else{
    14.                 ans.push采用back({nums[left], nums[right]});
    15.                 left++;
    16.                 right--;
    17.                 while(left < right && nums[right] == nums[right+1]){
    18.                     right--;
    19.                 }
    20.                 while(left < right && nums[left] == nums[left-1]){
    21.                     left++;
    22.                 }
    23.             }
    24.         }
    25.         return ans;
    26.     }
    27.     vector<vector<int>> nSum(vector<int>& nums, long target, int n, int left){
    28.         vector<vector<int>> ans;
    29.         vector<vector<int>> ans1;
    30.         if(n == 2){
    31.             ans = twoSum(nums, target, left);
    32.         }else{
    33.             for(int i=left; i<=nums.size() - n; i++){
    34.                 if(i > left && nums[i] == nums[i-1]){
    35.                     continue;
    36.                 }
    37.                 ans1 = nSum(nums, target - nums[i], n-1, i+1);
    38.                 for(int j=0; j<ans1.size(); j++){
    39.                     ans1[j].insert(ans1[j].begin(), nums[i]);
    40.                 }
    41.                 ans.insert(ans.end(), ans1.begin(), ans1.end());
    42.             }  
    43.         }
    44.         return ans;
    45.     }
    46.     vector<vector<int>> fourSum(vector<int>& nums, int target) {
    47.         vector<vector<int>> ans;
    48.         sort(nums.begin(), nums.end());
    49.         int n = nums.size();
    50.         if(n < 4){
    51.             return ans;
    52.         }
    53.         ans = nSum(nums, (long)target, 4, 0);
    54.         return ans;
    55.     }
    56. };
    57. 链接:https://leetcode.cn/problems/4sum/solutions/2090909/tong-guo-di-gui-ke-yi-qiu-nge-shu-zi-zhi-rc3a/
    复制代码

     

     

     

     

    多数之和问题(nSum)

    该用户从未签到

    主题

    0

    回帖

    0

    积分

    管理员

    积分
    0
    发表于 2024-3-11 18:31:53 | 显示全部楼层
    1. class Solution {
    2. private:
    3.     vector<vector<int>> p;
    4.     vector<int> v={1,2,3,4,5,6,7,8,9};
    5. public:
    6.     void helper(vector<int> &vec,int l,int k,int n,int index) {
    7.         if(k==0 && n==0) {
    8.             p.push采用back(vec);
    9.             return;
    10.         } else if(k==0) return;
    11.         else if(n<0) return;
    12.         
    13.         for(int i=l;i<v.size();i++) {
    14.             vec[index]=v[i];
    15.             helper(vec,i+1,k-1,n-vec[index],index+1);
    16.         }
    17.         return;
    18.     }
    19.     vector<vector<int>> combinationSum3(int k, int n) {
    20.         vector<int> vec(k,0);
    21.         helper(vec,0,k,n,0);
    22.         return p;
    23.     }
    24. };
    复制代码
    多数之和问题(nSum)
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|中国膜结构网_中国空间膜结构协会

    GMT+8, 2024-11-1 09:03 , Processed in 0.208397 second(s), 26 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表