algorithm:基于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))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值