组合问题汇总-LeetCode 46、77、39、40、219、377、1014(回溯法,DP,贪心)

  • 2019 年 12 月 13 日
  • 笔记

组合问题:LeetCode #46 77 39 40 219 377 1014

1

编程题

回溯法:

  • 递归结束条件
  • 变量状态的改变与恢复(tmp数组)
  • 递归参数中的变量和常量,在循环中变量如何改变!!!

【LeetCode #46】全排列

给定一个没有重复数字的序列,返回其所有可能的全排列。

示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]

class Solution {  public:      vector<vector<int>> res;      void dfs(vector<int>& nums, int n, int idx){          if(idx == n){              res.push_back(nums);              return;          }          for(int i = idx; i < n; i++){              swap(nums[i], nums[idx]);              dfs(nums, n, idx+);              swap(nums[i], nums[idx]);          }      }      vector<vector<int>> permute(vector<int>& nums) {          dfs(nums, nums.size(), );          return res;      }  };  

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/permutations

【LeetCode #77】组合

给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。

示例: 输入: n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]

class Solution {  public:      vector<vector<int>> res;      vector<int> tmp;      void dfs(int n, int idx, int num){          if(idx > n+)  return;          if(tmp.size() == num){              res.push_back(tmp);              return;          }          for(int i = idx; i <= n; i++){              tmp.push_back(i);              dfs(n, i+, num);              tmp.pop_back();          }      }        vector<vector<int>> combine(int n, int k) {          dfs(n, , k);          return res;      }  };  

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/combinations

【LeetCode #39】组合总和

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的数字可以无限制重复被选取。 说明:

所有数字(包括 target)都是正整数。 解集不能包含重复的组合。

示例 1: 输入: candidates = [2,3,6,7], target = 7, 所求解集为: [ [7], [2,2,3] ]

class Solution {  public:      vector<int> tmp;      vector<vector<int>> res;      void dfs(vector<int>& candidates, int target, int start){          if(target <= ){              if(target == ){                  res.push_back(tmp);              }              return;          }          for(int i = start; i < candidates.size(); i++){              tmp.push_back(candidates[i]);              dfs(candidates, target-candidates[i], i);              tmp.pop_back();          }      }      vector<vector<int>> combinationSum(vector<int>& candidates, int target) {          sort(candidates.begin(), candidates.end());          dfs(candidates, target, );          return res;      }  };  

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/combination-sum

【LeetCode #40】组合总和 II

给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用一次。

说明: 所有数字(包括目标数)都是正整数。 解集不能包含重复的组合。

示例 1: 输入: candidates = [10,1,2,7,6,1,5], target = 8, 所求解集为: [ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ]

class Solution {  public:      vector<int> tmp;      vector<vector<int>> res;      set<vector<int>> s;    // 去除重复的组合      void dfs(vector<int>& candidates, int target, int start){          if(target <= ){              if(target == ){                  s.insert(tmp);              }              return;          }          for(int i = start; i < candidates.size(); i++){              tmp.push_back(candidates[i]);              dfs(candidates, target-candidates[i], i+);              tmp.pop_back();          }      }      vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {          sort(candidates.begin(), candidates.end());          dfs(candidates, target, );          for(auto i: s){              res.push_back(i);          }          return res;      }  };  

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/combination-sum-ii

【LeetCode #216】组合总和 III

找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 – 9 的正整数,并且每种组合中不存在重复的数字。

说明: 所有数字都是正整数。 解集不能包含重复的组合。

示例 1: 输入: k = 3, n = 7 输出: [[1,2,4]]

class Solution {  public:      vector<int> tmp;      vector<vector<int>> res;      void dfs(int k, int n, int start){          if(n <=  && k == ){   // n与k都有条件限制              if(n == ){                  res.push_back(tmp);              }              return;          }          for(int i = start; i < ; i++){              tmp.push_back(i);              dfs(k-1, n-i, i+);              tmp.pop_back();          }      }        vector<vector<int>> combinationSum3(int k, int n) {          dfs(k, n, );          return res;      }  };  

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/combination-sum-iii

【LeetCode #377】组合求和 IV

给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数。

示例: nums = [1, 2, 3] target = 4 输出最终为7

class Solution {  public:        int combinationSum4(vector<int>& nums, int target) {          if(nums.empty()) return ;          vector<unsigned long long> dp(target+, );          dp[] = ;          for(int i = ; i <= target; i++){              for(auto j: nums){                  if(i >= j){                      dp[i] += dp[i-j];                  }              }          }          return dp[target];      }  };  

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/combination-sum-iv/

【LeetCode #1014】最佳观光组合

给定正整数数组 A,A[i] 表示第 i 个观光景点的评分,并且两个景点 i 和 j 之间的距离为 j – i。 一对景点(i < j)组成的观光组合的得分为(A[i] + A[j] + i – j):景点的评分之和减去它们两者之间的距离。

返回一对观光景点能取得的最高分。

示例: 输入:[8,1,5,2,6] 输出:11 解释:i = 0, j = 2, A[i] + A[j] + i – j = 8 + 5 + 0 – 2 = 11

解题思路:

虽然暴力法不能够通过,但可以给我一些贪心算法的思路!通过暴力法中tmp = A[i]+i + A[j]-j可以变换成A[i]+i的最大值与A[j]-j的最大值的求和问题,同时j > i. 因此我们可以使用一个tmp来储存max(A[i]+i), 因为其是旧数据,即i < j.

(暴力法,超时)

class Solution {  public:      int maxScoreSightseeingPair(vector<int>& A) {         int tmp = ;         int res = INT_MIN;         for(int i = ; i < A.size(); i++){             for(int j = i+; j < A.size(); j++){                 tmp = A[i] + i + A[j] - j;                 res = max(res, tmp);             }         }         return res;      }  };  

(贪心法)

class Solution {  public:      int maxScoreSightseeingPair(vector<int>& A) {         int tmp = A[] + ;         int res = INT_MIN;         for(int i = ; i < A.size(); i++){             res = max(res, tmp+A[i]-i);             tmp = max(tmp, A[i]+i);         }         return res;      }  };  

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/best-sightseeing-pair