文章目录

  • ​​31.下一个排列​​
  • ​​C++版本​​
  • ​​Python版本​​
  • ​​32.最长有效括号​​
  • ​​C++版本​​
  • ​​Python​​
  • ​​33.搜索旋转排序数组​​
  • ​​C++版本​​
  • ​​Python版本​​
  • ​​34.搜索范围​​
  • ​​C++ 版本​​
  • ​​Python 版本​​
  • ​​35.搜索插入位置​​
  • ​​C++版本​​
  • ​​Python​​
  • ​​36.有效数独​​
  • ​​C++版本​​
  • ​​Python​​
  • ​​37.解数独​​
  • ​​C++版本​​
  • ​​Python 版本​​
  • ​​38.报数​​
  • ​​C++ 版本​​
  • ​​Python 版本​​
  • ​​39.组合总和​​
  • ​​C++ 版本​​
  • ​​Python 版本​​
  • ​​40.组合求和​​
  • ​​C++ 版本​​
  • ​​Python 版本​​

31.下一个排列

给出一个序列,求出该序列的下一个更大的排列,如果不存在,则排列成最小的排列
1,2,3-> 1,3,2
1,3,2 -> 2,1,3
算法思想:找到变化的规律,就是前后数大小的比较,找到最后一个前数小于后数的索引开始变换,当相邻与最后一个数相邻时,直接交换;当与最后一个数相隔时,先交换,再将当前数后面的倒序。

C++版本

C++版本简化了Python的思路,建议先看下python的思路

void changeTwo(vector<int> &nums,int i,int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
void changeBlock(vector<int> &nums,int i,int j){
while (i<j) {
changeTwo(nums, i, j);
i++;
j--;
}
}

void nextPermutation(vector<int> &nums){
int n = nums.size();
for(int i=n-1;i>0;i--){
if(nums[i]>nums[i-1]){
if(i==n-1){
changeTwo(nums, i-1, i);
break;
}
else{
changeTwo(nums, i-1, n-1);
changeBlock(nums, i, n-1);
break;
}

}
else if(i==1){
changeBlock(nums, 0, n-1);
}
}
}
int main(){
vector<int> nums = {2,1,4,3};
nextPermutation(nums);
for(int i=0;i<nums.size();i++){
cout<<nums[i]<<" ";
}
cout<<endl;
}

这个版本没有考虑左括号多的情况,所以再修改一版。

int longestValidP(string s){
int maxlen = 0;
vector<int> stack;
int lastError = -1;
int templen=0;
for(int i=0;i<s.size();i++){
if(s[i]=='('){
stack.push_back('(');
}
else if(s[i]==')'){
if(stack.size()>0){
stack.pop_back();
templen += 2;
int len;
if(stack.size()==0){
len = i - lastError;
}
else{
len = templen;
}
maxlen = maxlen>len? maxlen:len;
}
else{
lastError = i;
templen = 0;
}
}
else{
lastError = i;
templen = 0;
}
}
return maxlen;
}
int main(){
string s = "((())";

int n = longestValidP(s);
cout<<"longest:"<<n<<endl;
}

Python版本

Python代码没有考虑重复数值的情况。

def nextPermutation(nums):
n = len(nums)
l = []
for i in range(n-1):
if(nums[i] < nums[i+1]):
l.append(i)
if len(l) == 0:
changeTwo(nums,0,n-1)
elif len(l) == n:
changeTwo(nums,n-2,n-1)

else:
if l[-1] == n-2:
changeTwo(nums,n-2,n-1)
else:
temp = -1
for i in range(l[-1]+1,n-1):
if nums[l[-1]]< nums[i]:
continue
else:
temp = i
break
if temp == -1:
exchange(nums,l[-1],temp)
changeTwo(nums,l[-1]+1,n-1)
else:
exchange(nums,l[-1],temp-1)
changeTwo(nums,l[-1]+1,n-1)

def changeTwo(nums,i,j):
if j-i==1:
exchange(nums,i,j)

else:
right = (j-i+1)//2+i
for x in range(i,right):
exchange(nums,x,j-x+i)

def exchange(nums,i,j):
temp = nums[i]
nums[i] = nums[j]
nums[j] = temp

nums = [1,2,5,4,3]
nextPermutation(nums)
print(nums)

32.最长有效括号

给定一个包含括号的字符串,计算最长的有效括号
‘()(’ ->2
‘(())’ -> 4
‘)()’ -> 2
算法思想:C++利用栈,检查是否有成对的括号。Python动态规划的解法。

C++版本

int longestValidP(string s){
int maxlen = 0;
vector<int> stack;
int lastError = -1;
for(int i=0;i<s.size();i++){
if(s[i]=='('){
stack.push_back('(');
}
else if(s[i]==')'){
if(stack.size()!=0){
stack.pop_back();
if(i==s.size()-1){
int temp = i - lastError;
if (temp>maxlen) {
maxlen = temp;
}
}
}
else{
int temp = i -1 - lastError;
if(temp>maxlen){
maxlen = temp;
}
lastError = i;
}
}
else{
int temp = i -1 - lastError;
if(temp>maxlen){
maxlen = temp;
}
lastError = i;
}
}
return maxlen;
}
int main(){
string s = "(())";

int n = longestValidP(s);
cout<<"longest:"<<n<<endl;
}

Python

动态规划的方法比较难懂,后面整理一篇文章学习下。

# dptable保存有效长度  递归的思想 每一个小部分的有效长度+前一部分的有效长度
class Solution(object):
def longestValidP(self,s):
dp = [0 for _ in range(0,len(s))]
print(dp)
left = 0
ans = 0
for i in range(0,len(s)):
if s[i]=='(':
left += 1
elif left>0:
left -= 1
dp[i] = dp[i-1] + 2 # +2只出现在右括号
j = i - dp[i] # 获取前一部分的有效括号值
if j >= 0:
dp[i] += dp[j] # 当前的总有效长度
ans = max(ans,dp[i])
return ans
sol = Solution()
print(sol.longestValidP("((()"))

33.搜索旋转排序数组

给定一个升序数组按照某个点旋转后的数组,(如[0,1,2,4,5,6,7]可能变为[4,5,6,7,0,1,2])。搜索一个目标值,如果存在则返回索引,不存在返回-1。
算法思想:如果仔细考虑会发现各种情况判断很复杂,但是汇总一下发现,无非是两个方向,找出情况不多的一个方向即可。

C++版本

int searchSort(vector<int> nums,int target){
int n = nums.size();
if(n<=0){return -1;}
int left=0;
int right = n-1;
while (left<=right) {
int mid = (left+right)/2;

if(nums[mid]==target){
return mid;
}
if(target>=nums[left]){
if(nums[left]<=nums[mid]&&nums[mid]<target){

left = mid + 1;
}
else
right = mid -1;
}
else if(target<=nums[right]){
if(nums[right]>=nums[mid]&&nums[mid]>target){
right = mid-1;
}
else{
left = mid+1;
}
}
else{
return -1;
}
}
return -1;
}
int main(){
vector<int> nums = {4,5,6,7,0,1,2};
int target = 0;
int res = searchSort(nums, target);
cout<<res<<endl;
}

Python版本

def search(nums,target):
n = len(nums)
left = 0
right = n-1

while(left<=right):
mid = (left+right)//2 # 开始总是错误,调试发现这里没有括号...
if nums[mid] == target:
return mid
if target >= nums[left]:
if target > nums[mid] >= nums[left]:
left = mid+1
else:
right = mid-1
elif target <= nums[right]:
if target < nums[mid] <= nums[right]:

right = mid-1
else:
left = mid+1
else:
return None
return None
nums = [4,5,6,7,0,1,2]
print(search(nums,7))

34.搜索范围

给定一个排序数组,求出目标值的范围,如nums = [4,5,5,5,6,6,6,6,7,8],target=6,则搜索的范围应该为[4,7]。
算法思想:先用二分法找到一个目标值,再采用二分法的变种找到其边界范围。C++代码精简很多。

C++ 版本

int bi_search(int A[],int low,int high,int key);
vector<int> searchRange(int A[],int n,int target){
int pos = bi_search(A, 0, n-1, target);
vector<int> v;
int low = -1,high = -1;
if(pos>0){
low = high = pos;
int l = low;
do{
low = l;
l = bi_search(A, 0, low-1, target);
}while(l>=0);
int h = high;
do{
high = h;
h = bi_search(A, high+1, n-1, target);
}while(h>=0);
}
v.push_back(low);
v.push_back(high);
return v;
}
int bi_search(int A[],int low,int high,int key){
while (low<=high) {
int mid = (low+high)/2;
if(A[mid]==key){
return mid;
}
else if(key>A[mid]){
low = mid+1;
}
else{
high = mid-1;
}
}
return -1;
}
int main(){
const int cnt = 9;
int A[cnt] = {1,2,3,4,4,5,5,6,7};
int target = 4;
vector<int> v = searchRange(A, cnt, target);

for (int i=0; i<v.size(); i++) {
cout<<v[i]<<" ";
}
cout<<endl;
}

Python 版本

def searchTarget(nums,target):
n = len(nums)
left = 0
right = n-1
while(left<=right):
mid = (left+right)//2
if nums[mid]==target:
return mid
elif nums[mid]>target:
right = mid-1
else:
left = mid+1
return -1
def searchRange(nums,target):
n = len(nums)
mid = searchTarget(nums,target)
left = -1
right = -1
if mid==0:
left = mid
if mid==n-1:
right = mid

if nums[mid-1]==target:
templ = 0
tempr = mid-1
while(templ<=tempr):
tempmid = (templ+tempr)//2
if(nums[tempmid]==target):

if tempmid==0 or nums[tempmid-1]!=target or tempmid==tempr:
left = tempmid
break
elif nums[tempmid-1]==target:
tempr = tempmid-1
else:
templ = tempmid+1
else:
left = mid
if nums[mid+1]==target:
templ = mid+1
tempr = n-1
while(templ<=tempr):
tempmid = (templ+tempr)//2
if(nums[tempmid]==target):
if tempmid==n-1 or nums[tempmid+1]!=target or tempmid==templ:
right = tempmid
break
elif nums[tempmid+1]==target:
templ = tempmid+1
else:
tempr = tempmid-1
else:
right = mid
return [left,right]

print(searchRange([4,5,5,5,6,6,6,6,7,8],6))

35.搜索插入位置

给定一个排序数组和目标值,在数组中查找目标值,如果存在返回索引;如果不存在返回其要插入的位置。
算法思想:在二分法的没有找到的基础上返回左节点即可。

C++版本

int searchIndex(vector<int> nums,int target){
int n = nums.size();
int left = 0;
int right = n-1;
while (left<=right) {
int mid = (left+right)/2;
if(nums[mid]==target){
return mid;
}
else if(nums[mid]>target){
right = mid-1;
}
else{
left = mid+1;
}
}
return left;
}
int main(){
vector<int> nums = {1,3,5,7};
int target = 4;
int res = searchIndex(nums, target);
cout<<res<<endl;
}

Python

def searchIndex(nums,target):
n = len(nums)
left=0
right=n-1
while(left<=right):
mid = (left+right)//2
if nums[mid]==target:
return mid
elif nums[mid]>target:
right = mid-1
else:
left = mid+1
return left
print(searchIndex([1,3,5,6],0))

36.有效数独

判断一个9x9的数组,行、列、3x3数组(9x9分为9个3x3的小方块)是否有重复数字。
算法思想:对行、列、每个3x3的数组分别建立一个备忘录。

C++版本

bool isValidSudoku(vector<vector<char>> &nums){
const int cnt=9;
bool row_mask[cnt][cnt] = {false};
bool col_mask[cnt][cnt] = {false};
bool box_mask[cnt][cnt] = {false};
for(int i=0;i<nums.size();i++){
for(int j=0;j<nums[0].size();j++){
if(!isdigit(nums[i][j])) continue;
int idx = nums[i][j]-'0'-1;
if (row_mask[i][idx]==true) {
return false;
}
row_mask[i][idx] = true;
if(col_mask[j][idx]==true){
return false;
}
col_mask[j][idx] = true;
int torow = (i/3)*3 + (j/3);
if(box_mask[torow][idx]==true){
return false;
}
box_mask[torow][idx] = true;
}
}
return true;
}
int main(){
vector<vector<char>> nums = {{'5','3','.','.','7','.','.','.','.'},
{'6', '.', '.', '1', '9', '5', '.', '.', '.'},
{'.', '9', '8', '.', '.', '.', '.', '6', '.'},
{'8', '.', '.', '.', '6', '.', '.', '.', '3'},
{'4', '.', '.', '8', '.', '3', '.', '.', '1'},
{'7', '.', '.', '.', '2', '.', '.', '.', '6'},
{'.', '6', '.', '.', '.', '.', '2', '8', '.'},
{'.', '.', '.', '4', '1', '9', '.', '.', '5'},
{'.', '.', '.', '.', '8', '.', '.', '7', '9'}};
bool res = isValidSudoku(nums);
cout<<res<<endl;
}

Python

def validSudoku(nums):
cacheCol = [[0]*9 for _ in range(9)]
cacheRow = [[0]*9 for _ in range(9)]
cacheBox = [[0]*9 for _ in range(9)]
k = 0
for i in range(9):
for j in range(9):
if nums[i][j]=='.':
continue
boxCol = (i//3)*3+j//3

if cacheCol[j][int(nums[i][j])-1]!=0 or cacheRow[i][int(nums[i][j])-1]!=0 or cacheBox[boxCol][int(nums[i][j])-1]!=0:
return False
cacheCol[j][int(nums[i][j])-1] = 1
cacheRow[i][int(nums[i][j])-1] = 1
cacheBox[boxCol][int(nums[i][j])-1] = 1
k += 1
# print(k)
return True

nums = [["5","3",".",".","7",".",".",".","."],
["6", ".", ".", "1", "9", "5", ".", ".", "."],
[".", "9", "8", ".", ".", ".", ".", "6", "."],
["8", ".", ".", ".", "6", ".", ".", ".", "3"],
["4", ".", ".", "8", ".", "3", ".", ".", "1"],
["7", ".", ".", ".", "2", ".", ".", ".", "6"],
[".", "6", ".", ".", ".", ".", "2", "8", "."],
[".", ".", ".", "4", "1", "9", ".", ".", "5"],
[".", ".", ".", ".", "8", ".", ".", "7", "9"]]
print(validSudoku(nums))

37.解数独

给出一个待完善的数独,遵循一下规则解出:

  • 数字1-9在每一行只能出现一次
  • 数字1-9在每一列只能出现一次
  • 数字1-9在每个3x3的box只能出现一次

算法思想:大的思路是通过回溯算法来做,在每一个执行过程中,可以约束参数来减少回溯。C++和Python的实现方法大同小异。这个题花了不少时间…

C++版本

const int SudokuSize = 9;
bool row_mask[SudokuSize][SudokuSize];
bool col_mask[SudokuSize][SudokuSize];
bool area_mask[SudokuSize][SudokuSize];
bool initSudokuMask(vector<vector<char>> &board){
memset(row_mask, false, sizeof(row_mask));
memset(col_mask, false, sizeof(col_mask));
memset(area_mask, false, sizeof(area_mask));
for(int i=0;i<SudokuSize;i++){
for(int j=0;j<SudokuSize;j++){
if(!isdigit(board[i][j])){
continue;
}
int idx = board[i][j]-'0'-1;
int area = (i/3)*3+j/3;
if(row_mask[i][idx]||col_mask[j][idx]||area_mask[area][idx]){
return false;
}
row_mask[i][idx]=col_mask[j][idx]=area_mask[area][idx]=true;
}
}
return true;
}
bool recursiveSudoku(vector<vector<char>> &board,int row,int col){
if(row>=SudokuSize){
return true;
}
if(col>=SudokuSize){
return recursiveSudoku(board, row+1, 0);
}
if(board[row][col]!='.'){
return recursiveSudoku(board, row, col+1);
}
int area;
for(int i=0;i<SudokuSize;i++){
area = (row/3)*3+col/3;
if(row_mask[row][i]||col_mask[col][i]||area_mask[area][i]){
continue;
}
board[row][col] = i+'1';
row_mask[row][i]=col_mask[col][i]=area_mask[area][i]=true;
if(recursiveSudoku(board, row, col+1)==true){
return true;
}
//backtrace;
board[row][col] = '.';
row_mask[row][i]=col_mask[col][i]=area_mask[area][i]=false;
}
return false;
}
void solveSudoku(vector<vector<char>> &board){
if(initSudokuMask(board)==false){
return;
}
recursiveSudoku(board, 0, 0);
}
void printSudoku(vector<vector<char>> res){
for(int i=0;i<SudokuSize;i++){
for(int j=0;j<SudokuSize;j++){
cout<<res[i][j];
if(j==SudokuSize-1){
cout<<endl;
}
}
}
}
int main(){
vector<vector<char>> nums = {{'5','3','.','.','7','.','.','.','.'},
{'6', '.', '.', '1', '9', '5', '.', '.', '.'},
{'.', '9', '8', '.', '.', '.', '.', '6', '.'},
{'8', '.', '.', '.', '6', '.', '.', '.', '3'},
{'4', '.', '.', '8', '.', '3', '.', '.', '1'},
{'7', '.', '.', '.', '2', '.', '.', '.', '6'},
{'.', '6', '.', '.', '.', '.', '2', '8', '.'},
{'.', '.', '.', '4', '1', '9', '.', '.', '5'},
{'.', '.', '.', '.', '8', '.', '.', '7', '9'}};

solveSudoku(nums);
printSudoku(nums);
}

Python 版本

class Solution(object):

def solveSudoku(self,board):
i = 0
j = 0
l = []
i,j = self.findNext(board,i,j)

def findValue(board,i,j):

validSet = self.constructSet(board,i, j)
for x in range(1,10):
if x not in validSet:
tmp = copy.deepcopy(board)
tmp[i][j] = str(x)
if self.fullBoard(tmp):
l.append(tmp)

a,b = i,j

a,b = self.findNext(tmp,a,b)

findValue(tmp,a,b)
return
findValue(board,i,j)
if l==[]:
return None
return l[0]

def transformIndex(self,i,j):
if j<8:
a = i
b = j+1
else:
a = i+1
b = 0
return a,b

def constructSet(self,board,i,j):
validSet = set()
boxRow = (i // 3) * 3
boxCol = (j // 3) * 3
for col in board[i]:
if col!='.':
validSet.add(int(col))
for row in range(9):
if board[row][j]!='.':
validSet.add(int(board[row][j]))
for row in range(boxRow,boxRow+3):
for col in range(boxCol,boxCol+3):
if board[row][col]!='.':
validSet.add(int(board[row][col]))
return validSet

def fullBoard(self,board):
for i in range(9):
for j in range(9):
if board[i][j]=='.':
return False
return True
def findNext(self,board,i,j):
while(board[i][j]!='.'):
i,j = self.transformIndex(i,j)
if i==8 and j==8:
break

return i,j

nums = [["5", "3", ".", ".", "7", ".", ".", ".", "."],
["6", ".", ".", "1", "9", "5", ".", ".", "."],
[".", "9", "8", ".", ".", ".", ".", "6", "."],
["8", ".", ".", ".", "6", ".", ".", ".", "3"],
["4", ".", ".", "8", ".", "3", ".", ".", "1"],
["7", ".", ".", ".", "2", ".", ".", ".", "6"],
[".", "6", ".", ".", ".", ".", "2", "8", "."],
[".", ".", ".", "4", "1", "9", ".", ".", "5"],
[".", ".", ".", ".", "8", ".", ".", "7", "9"]]
Sol = Solution()
res = Sol.solveSudoku(nums)
print(res)

38.报数

初始为1,后续:
1
11
21
1211
111221
输入n,输出第n项

算法思想:这题较简单,找到下一序列的规则即可。

C++ 版本

vector<int> getNext(vector<int> &input);
vector<int> countAndSay(int n){
vector<int> input = {1};
vector<int> output;
if(n==1){
return input;
}
for(int i=0;i<n-1;i++){
output = getNext(input);
input = output;
}
return output;
}

vector<int> getNext(vector<int> &input){
vector<int> res;
int n = input.size();
for(int i=0;i<n;i++){
if(i==n-1){
res.push_back(1);
res.push_back(input[i]);
break;
}
if(input[i]==input[i+1]){
res.push_back(2);
res.push_back(input[i]);
i++;
}
else{
res.push_back(1);
res.push_back(input[i]);
}
}
return res;
}

int main(){
// vector<int> input = {2,1};
// vector<int> res = getNext(input);
vector<int> res = countAndSay(5);
for(int i=0;i<res.size();i++){
cout<<res[i];
}
cout<<endl;
}

Python 版本

def countAndSay(n):
def nextSay(res):
ifnext = True
res2 = ""
for i in range(len(res)):
if not ifnext:
ifnext = True
continue
if i<len(res)-1 and res[i]==res[i+1]:
res2 += "2" + res[i]
ifnext = False
else:
res2 += "1" + res[i]
return res2
res = "1"
if n==1:
return res
for i in range(n-1):
res = nextSay(res)
return res

print(countAndSay(5))

39.组合总和

给定一个无重复元素的数组和一个目标值,找出数组中所有可以使数字和为target的组合。
算法思想:典型的回溯算法解

C++ 版本

void getNext(vector<vector<int>> &res,vector<int> nums,vector<int> r,int target);

vector<vector<int>> combinationSum(vector<int> nums,int target){
vector<vector<int>> res;
vector<int> r = {};
getNext(res,nums,r,target);
return res;
}

int sumVector(vector<int> r){
int sumr=0;
for(int i=0;i<r.size();i++){
sumr = sumr + r[i];
}
return sumr;
}
void getNext(vector<vector<int>> &res,vector<int> nums,vector<int> r,int target){
if (sumVector(r)==target) {
sort(r.begin(), r.end());
if(find(res.begin(),res.end(),r)!=res.end()){
return;
}
res.push_back(r);
}
else if (sumVector(r)>target){
return;
}
for(int i=0;i<nums.size();i++){
r.push_back(nums[i]);
getNext(res, nums,r,target);
r.pop_back();
}
}
void printVector(vector<vector<int>> res){
for(int i=0;i<res.size();i++){
copy(res[i].begin(),res[i].end(),ostream_iterator<int>(cout," "));
cout<<endl;
}
cout<<endl;
}


int main(){
vector<int> nums = {2,3,5};
int target = 8;
vector<vector<int>> res = combinationSum(nums, target);
printVector(res);

}

Python 版本

def combinationSum(nums,target):
res = []
r = []
def toFind(r,target):
if sum(r)==target:
r.sort() # 后面pop()没有影响?
if r in res:
return
res.append(r[:])
return
if target-sum(r)<nums[0]:
return

for num in nums:
r.append(num)
toFind(r,target)
r.pop()
toFind(r,target)
return res

print(combinationSum([2,3,6,7],7))

根据题40,修订版本

def combinationSum(nums,target):
res = []
r = []
def toFind(r,target):
if sum(r)==target:
newr = r[:]
newr.sort()
if r in res:
return
res.append(newr[:])
return
if target-sum(r)<nums[0]:
return

for num in nums:
r.append(num)
toFind(r,target)
r.pop()
toFind(r,target)
return res

print(combinationSum([1,2,3,6,7],7))

40.组合求和

找出数组nums(未排序)中所有数据和为target的组合,每个数字在每个组合中只能使用一次。
算法思想:依然是回溯法,可以提升效率的方法:对初始数组大于target的值去除;对数组排序后可以应用多种判断条件。

C++ 版本

void getNext(vector<vector<int>> &res,vector<int> nums,vector<int> r,int target);

vector<vector<int>> combinationSum(vector<int> nums,int target){
vector<vector<int>> res;
vector<int> r = {};
getNext(res,nums,r,target);
return res;
}

int sumVector(vector<int> r){
int sumr=0;
for(int i=0;i<r.size();i++){
sumr = sumr + r[i];
}
return sumr;
}
void getNext(vector<vector<int>> &res,vector<int> nums,vector<int> r,int target){
if (sumVector(r)==target) {
sort(r.begin(), r.end());
if(find(res.begin(),res.end(),r)!=res.end()){
return;
}
res.push_back(r);
}
else if (sumVector(r)>target){
return;
}
for(int i=0;i<nums.size();i++){
r.push_back(nums[i]);
vector<int> newnums={};
if(i==0){
newnums.insert(newnums.end(),nums.begin()+1,nums.end());
}
else if (i==nums.size()-1){
newnums.insert(newnums.end(), nums.begin(),nums.end());
}
else{
newnums.insert(newnums.end(), nums.begin(),nums.begin()+i-1);
newnums.insert(newnums.end(), nums.begin()+i+1,nums.end());
}
getNext(res, newnums,r,target);
r.pop_back();
}
}
void printVector(vector<vector<int>> res){
for(int i=0;i<res.size();i++){
copy(res[i].begin(),res[i].end(),ostream_iterator<int>(cout," "));
cout<<endl;
}
cout<<endl;
}


int main(){
vector<int> nums = {10,1,2,7,6,1,5};
int target = 8;
vector<vector<int>> res = combinationSum(nums, target);
printVector(res);

}

Python 版本

这里先附上我之前的错误版本,看了好久,这一点明明我上一题注意到了,但是上题不管是否排序依然不影响正确结果(已修改)。深刻体会到了bug的可怕 哈哈。

def combinationSum(inputnums,target):
res = []
r = []
def toFind(r,target,nums):

if sum(r)==target:
r.sort()
if r in res:
return
res.append(r[:])
return
if sum(r)>target:
return
for i in range(len(nums)):
r.append(nums[i])

if i==0:
newnums = nums[i+1:]

toFind(r,target,newnums)

elif i<len(nums)-1:
newnums = nums[:i] + nums[i+1:]

toFind(r,target,newnums)

else:
newnums = nums[:i]
toFind(r, target, newnums)
r.pop()
return
toFind(r,target,inputnums)
return res
print(combinationSum([10,1,2,7,6,1,5],8))

正确修改:复制一个r列表

def combinationSum(inputnums,target):
res = []
r = []
def toFind(r,target,nums):

if sum(r)==target:
newr = r[:]
newr.sort()
if newr in res:
return
res.append(newr[:])
return
if sum(r)>target:
return
for i in range(len(nums)):
r.append(nums[i])

if i==0:
newnums = nums[i+1:]
toFind(r,target,newnums)

elif i<len(nums)-1:
newnums = nums[:i] + nums[i+1:]
toFind(r,target,newnums)

else:
newnums = nums[:i]
toFind(r, target, newnums)
r.pop()
return
toFind(r,target,inputnums)
return res
print(combinationSum([10,1,2,7,6,1,5],8))