深度优先搜索算法(dfs)

1. combination sum

https://leetcode.com/problems/combination-sum/
Example 1:

Input: candidates = [2,3,5], target = 8,
A solution set is:
[
  [2,2,2,2],
  [2,3,3],
  [3,5]
]

candidates中每个数都是惟一的。
我的大概想法就是先排序,然后从小往大搜索,有两种选择:

  1. 不选当前数,指针右移
  2. 选当前数,指针不变

我的解法:(比较慢)

class Solution {
public:
    vector<vector<int>> res;
    vector<int> nums;
    int M;
    int getHashCode(vector<int>& nums){
        int hashCode=0;
        int base=1;
        for(int i=0;i<nums.size();i++){
            hashCode+=base*nums[i];
            base*=M;
        }
        return hashCode;
    }
    set<int> numsSet;
    void dfs(vector<int>& candidates,int target,int i){
        int sum= accumulate(nums.begin() , nums.end() , 0);
        if(sum==target){
            int hashCode=getHashCode(nums);
            if(numsSet.count(hashCode)==0){
                res.push_back(nums);
                numsSet.insert(hashCode);
            }
        }
        else if(sum>target || i>candidates.size())
            return;
        else{
            nums.push_back(candidates[i]);
            dfs(candidates,target,i+1);
            nums.pop_back();
            if(i+1<candidates.size())
                dfs(candidates,target,i+1);
        }
        
    }
    int max(int a,int b){
        return a>b?a:b;
    }
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        sort(candidates.begin(),candidates.end());
        int ix=max(0,candidates.size()-1);
        M=candidates[ix];
        dfs(candidates,target,0);
        return res;
    }
};

较快解法:
这个算法不像我的算法为两个分支去搜索,而是通过for循环去遍历。

class Solution {
public:
    void dfs(int remain, int cur_idx, vector<int>& path, const vector<int>& cans, vector<vector<int>>& res) {
        if(remain == 0) {
            res.push_back(path);
            return;
        }
        if(remain < 0) return;
        for(int i = cur_idx; i < cans.size(); ++i){
            if(cans[i] > remain) break;
            path.push_back(cans[i]);
            dfs(remain - cans[i], i, path, cans, res);
            path.pop_back();
        }
    }

    vector<vector<int>> combinationSum(vector<int>& cands, int target) {
        vector<vector<int>> res;
        vector<int> cur_path;
        if(cands.empty()) return res;
        sort(cands.begin(), cands.end());
        dfs(target, 0, cur_path, cands, res);
        return res;
    }
};

2. Combination Sum II

https://leetcode.com/problems/combination-sum-ii/
我的C++报错:

class Solution {
public:
    vector<vector<int>> res;
    vector<int> nums;
    int M;
    int getHashCode(vector<int>& nums){
        int hashCode=0;
        int base=1;
        for(int i=0;i<nums.size();i++){
            hashCode+=base*nums[i];
            base*=M;
        }
        return hashCode;
    }
    set<int> numsSet;
    void dfs(vector<int>& candidates,int target,int i){
        int sum= accumulate(nums.begin() , nums.end() , 0);
        if(sum==target){
            int hashCode=getHashCode(nums);
            if(numsSet.count(hashCode)==0){
                res.push_back(nums);
                numsSet.insert(hashCode);
            }
        }
        else if(sum>target || i>candidates.size())
            return;
        else{
            nums.push_back(candidates[i]);
            dfs(candidates,target,i+1);
            nums.pop_back();
            if(i+1<candidates.size())
                dfs(candidates,target,i+1);
        }
        
    }
    int max(int a,int b){
        return a>b?a:b;
    }
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        sort(candidates.begin(),candidates.end());
        int ix=max(0,candidates.size()-1);
        M=candidates[ix];
        dfs(candidates,target,0);
        return res;
    }
};

我用Python重写了一遍

class Solution:
    res = []
    nums = []

    def dfs(self,remain,index,candidates):
        if remain==0:
            import copy
            self.res.append(copy.deepcopy(self.nums))
            return
        elif remain<0:
            return
        else:
            for i in range(index,len(candidates)):
                if remain-candidates[i]<0:
                    break
                self.nums.append(candidates[i])
                self.dfs(remain-candidates[i],index+1,candidates)  # index 不 +1 的话,就是上一题的情况
                self.nums.pop()


    def combinationSum2(self, candidates:list, target: int) :
        if not candidates:
            return candidates
        candidates.sort()
        self.dfs(target,0,candidates)
        return list(set(map(tuple,map(sorted,self.res))))

本地运行正确,提交还是报错,玄学
放弃挣扎,题解是这样的:

class Solution(object):
    # slight modification on Combination Sum problem
    def dfs(self, nums, target, index, path, ans):
        if target < 0:
            return None
        if target == 0 and (path not in ans):
            ans.append(path)
        for i in range(index, len(nums)):
            if nums[i] > target:
                break
            self.dfs(nums, target-nums[i], i+1, path+[nums[i]], ans)
    
    def combinationSum2(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        ans = []
        candidates.sort() # this is for the break in dfs function, which makes it much faster
        self.dfs(candidates, target, 0, [], ans)
        return ans

意思是入了栈就不能再出栈了。

3. Permutations

https://leetcode.com/problems/permutations/
感觉最简单的方法就是C++的next_permutation了

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        vector<vector<int>> ans;
        do{
            ans.push_back(nums);
        }while(next_permutation(nums.begin(),nums.end()));
        return ans;
    }
};

其实本质是dfs的排列树

class Solution {
public:
    vector<vector<int>> ans;
    void dfs(vector<int>& nums,int ix){
        if(ix==nums.size()){
            ans.push_back(nums);
            return;
        }else{
            for(int i=ix;i<nums.size();i++){
                swap(nums[i],nums[ix]);
                dfs(nums,ix+1);
                swap(nums[i],nums[ix]);
            }
        }
    }
    
    vector<vector<int>> permute(vector<int>& nums) {
        dfs(nums,0);
        return ans;
    }
};

3. Permutations II

https://leetcode.com/problems/permutations-ii/

这题如果用next_permutation 来做的话,其实也是可以的。
如果是用上题的排列树的话,需要注意一个去重的问题。
用最容易去重的python实现:

class Solution:
    ans=[]
    def dfs(self,nums,ix):
        if ix==len(nums):
            self.ans.append(nums[:])
            return
        else:
            for i in range(ix,len(nums)):
                nums[i],nums[ix]=nums[ix],nums[i]
                self.dfs(nums,ix+1)
                nums[i],nums[ix]=nums[ix],nums[i]
    
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        self.ans=[]  # 多点测试,不用这个变量会累积
        self.dfs(nums,0)
        # return self.ans
        return list(map(list,set(map(tuple,self.ans))))
        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本系统的研发具有重大的意义,在安全性方面,用户使用浏览器访问网站时,采用注册和密码等相关的保护措施,提高系统的可靠性,维护用户的个人信息和财产的安全。在方便性方面,促进了校园失物招领网站的信息化建设,极大的方便了相关的工作人员对校园失物招领网站信息进行管理。 本系统主要通过使用Java语言编码设计系统功能,MySQL数据库管理数据,AJAX技术设计简洁的、友好的网址页面,然后在IDEA开发平台中,编写相关的Java代码文件,接着通过连接语言完成与数据库的搭建工作,再通过平台提供的Tomcat插件完成信息的交互,最后在浏览器中打开系统网址便可使用本系统。本系统的使用角色可以被分为用户和管理员,用户具有注册、查看信息、留言信息等功能,管理员具有修改用户信息,发布寻物启事等功能。 管理员可以选择任一浏览器打开网址,输入信息无误后,以管理员的身份行使相关的管理权限。管理员可以通过选择失物招领管理,管理相关的失物招领信息记录,比如进行查看失物招领信息标题,修改失物招领信息来源等操作。管理员可以通过选择公告管理,管理相关的公告信息记录,比如进行查看公告详情,删除错误的公告信息,发布公告等操作。管理员可以通过选择公告类型管理,管理相关的公告类型信息,比如查看所有公告类型,删除无用公告类型,修改公告类型,添加公告类型等操作。寻物启事管理页面,此页面提供给管理员的功能有:新增寻物启事,修改寻物启事,删除寻物启事。物品类型管理页面,此页面提供给管理员的功能有:新增物品类型,修改物品类型,删除物品类型。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值