leetcode_04 递归,回溯与分治

leetcode_04 递归,回溯与分治

一.递归

递归调用实现数字 1+2+3。。。

#include<iostream>
void compute_sum(int i,int &sum)
{
    if(i>3)
    {return;}
    sum=sum+i;
    compute_sum(i+1,sum);
}
int main()
{
    int sum=0;
    compute_sum(1,sum);
    printf("sum=%d\n",sum);
    return 0;
}

递归将链表放入数组中

#include<iostream>
#include<vector>
using namespace std;
struct ListNode
{
    int val;
    ListNode *next;
    ListNode(int x):val(x),next(NULL){}
};
void add_to_vector(ListNode *head,vector<int>&vec)
{
    if(!head)
        return;
    vec.push_back(head->val);
    add_to_vector(head->next,vec);
}
int main()
{
    ListNode a(1);
    ListNode b(2);
    ListNode c(3);
    ListNode d(4);
    ListNode e(5);
    a.next=&b;
    b.next=&c;
    c.next=&d;
    d.next=&e;
    vector<int>vec;
    add_to_vector(&a,vec);
    for(int i=0;i<vec.size();i++)
    {
        printf("[%d]",vec[i]);
    }
    printf("\n");
    return 0;
}

二.回溯

回溯法又称试探法,但当探索到某一步的时候,发现原先选择达不到目标,就退一步重新选择,这种走不通就退回再走的技术为回溯法。

例1.子集

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

示例 1:

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

输入:nums = [0]
输出:[[],[0]]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/subsets
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
第一步:设置输出各个子集

#include<stdio.h>
#include<vector>
using namespace std;
int main()
{
    vector<int>nums;
    nums.push_back(1);
    nums.push_back(2);
    nums.push_back(3);
    vector<int>item;//生成各个子集的数组
    vector<vector<int>>result;//生成最终的结果数组
    for(int i=0;i<nums.size();i++)
    {
        item.push_back(nums[i]);
        result.push_back(item);
    }
    for(int i=0;i<result.size();i++)
    {
        for(int j=0;j<result[i].size();j++)
        {
            printf("[%d].",result[i][j]);
        }
        printf("\n");
    }
    return 0;

}

第一步:递归输出各个子集

#include<stdio.h>
#include<vector>
using namespace std;
void generate(int i,vector<int>& nums,vector<int>&item,vector<vector<int>>&result)
{
    if(i>=nums.size())
    {
        return;
    }
    item.push_back(nums[i]);
    result.push_back(item);
    generate(i+1,nums,item,result);
}

int main()
{
    vector<int>nums;
    nums.push_back(1);
    nums.push_back(2);
    nums.push_back(3);
    vector<int>item;
    vector<vector<int>>result;
    generate(0,nums,item,result);
    for(int i=0;i<result.size();i++)
    {
        for(int j=0;j<result[i].size();j++)
            printf("[%d]",result[i][j]);
        printf("\n");
    }
    return 0;
}

class Solution
{
public:
    vector<vector<int>>subsets(vector<int>& nums)
    {
        vector<vector<int>>result;//存储最终结果
        vector<int>item;//回溯时,产生各个子集的数组
        result.push_back(item);
        generate(0,nums,item,result);//计算各个子集
        return result;
    }
private:
    void generate(int i,vector<int>& nums,vector<int>&item,vector<vector<int>> result)
    {
        if(i<=nums.size())
        {
            return;
        }
        item.push_back(nums[i]);
        result.push_back(item);
        generate(i+1,nums,item,result);
        item.pop_back();
        generate(i+1,nums,item,result);
    }
};

方法二:位运算

在这里插入图片描述

#include<vector>
#include<stdio.h>
using namespace std;
class Solution
{
public:
    vector<vector<int>>subsets(vector<int>&nums)
    {
        vector<vector<int>>result;
        int all_set=1<<nums.size();
        for(int i=0;i<all_set;i++)
        {
            vector<int>item;
            for(int j=0;j<nums.size();j++)
            {
                if(i&(1<<j))
                {
                    item.push_back(nums[i]);
                }
            }
            result.push_back(item);
        }
        return result;
    }
};
int main()
{``````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
    vector<int>nums;
    nums.push_back(1);
    nums.push_back(2);
    nums.push_back(3);
    vector<vector<int>>result;
    Solution solve;
    result=solve.subsets(nums);
    for(int i=0;i<result.size();i++)
    {
        if(result[i].size()==0)
            printf("[]");
        for(int j=0;j<result[i].size();j++)
            printf("[%d]",result[i][j]);
        printf("\n");
    }
    return 0;
}

例2 组合数之和

给定一个数组 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]
]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combination-sum-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

#include<iostream>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
class Solution
{
public:
    vector<vector<int>>combinationSum2(vector<int>&candidates,int target)
    {
      vector<vector<int>>result;
      vector<int>item;
      vector<vector<int>>res_set;
      sort(candidates.begin(),candidates.end());
      generate(0,candidates,result,item,res_set,0,target);
      return result;
    }
private:
    void generate(int i,vector<int>&nums,vector<vector<int>>result,vector<int>&item,set<vector<int>>&res_set,int sum,int target)
    {
        if(i>=nums.size()||sum>target)
        {
            return;
        }
        sum+=nums[i];
        item.push_back(nums[i]);
        if(target==sum&&res_set.find(item)==res_set.end())
        {
            result.push_back(item);
            res_set.insert(item);
        }
        generate(i+1,nums,result,item,res_set,sum,target);
        sum-=nums[i];
        item.pop_back();
        generate(i+1,nums,result,item,res_set,sum,target);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值