• [LeetCode题解]377. 组合总和 Ⅳ


    前言

    看完这篇题解,可以再看看这几个问题:

    题目描述

    377. 组合总和 Ⅳ

    题目:377. 组合总和 Ⅳ

    解题思路

    方法一:回溯 + 剪枝

    采用前三题的思路:回溯 + 剪枝。

    func combinationSum4(nums []int, target int) int {
        if len(nums) == 0 {
            return 0
        }
        sort.Ints(nums)
        if target < nums[0] {
            return 0
        }
        return backtrack(nums, target)
    }
    
    func backtrack(nums []int, target int) int {
        if target == 0 {
            return 1
        }
        res := 0
        for i:=0;i<len(nums);i++ {
            if target - nums[i] < 0 {
                break
            }
            res += backtrack(nums, target-nums[i])
        }
        return res
    }
    

    结果超时QAQ。。。

    超时了~

    方法二:回溯 + 剪枝 + 备忘录

    从方法一的代码生成的递归树可知,存在很多重复子问题。可以使用备忘录来降低时间复杂度。

    递归树

    var men []int
    func combinationSum4(nums []int, target int) int {
        if len(nums) == 0 {
            return 0
        }
        men = make([]int, target+1)
        sort.Ints(nums)
        if target < nums[0] {
            return 0
        }
        return backtrack(nums, target)
    }
    
    func backtrack(nums []int, target int) int {
        if target == 0 {
            return 1
        }
        if men[target] > 0{
            return men[target]
        }
        res := 0
        for i:=0;i<len(nums);i++ {
            if target - nums[i] < 0 {
                break
            }
            res += backtrack(nums, target-nums[i])
        }
        men[target] = res
        return res
    }
    

    但是结果仍然超时QAQ。。。

    又超时了~

    方法三:DP

    解决重复计算、重复子问题也可以使用 DP 来解决。

    第一步:找重复性

    通过递归树可知,存在重复计算了多次相同 target 的组合数。

    第二步:定义状态

    直接将问题转化为定义,dp[i] 表示 target=i 时的组合数。

    第三步:找出 DP 方程

    通过递归树得到 DP 方程如下:

    dp[i] = sum(dp[i - num] for num in nums and if i >= num)
    

    第四步:初始化状态

    dp[0] = 1 表示对于给定数组的 target = 0 的结果有 1 个,即空集。

    代码实现:

    func combinationSum4(nums []int, target int) int {
        dp := make([]int, target+1)
        dp[0] = 1
        for i:=1;i<=target;i++{
            for _,num := range nums {
                if i >= num {
                    dp[i] += dp[i-num]
                }
            }
        }
        return dp[target]
    }
    

    复杂度分析:

    • 时间复杂度:(O(n * target)),其中 n 是数组 nums 的长度。
    • 空间复杂度:(O(target))。使用 target + 1 长度的数组空间。
  • 相关阅读:
    SiteMesh入门(1-1)SiteMesh是什么?
    接口和抽象类有什么区别
    StringUtils工具类常用方法汇总(判空、转换、移除、替换、反转)
    StringUtils工具类常用方法汇总(截取、去除空白、包含、查询索引)
    加密方法与HTTPS 原理详解
    String.split()与StringUtils.split()
    自动生成注释
    linux下安装与部署redis
    mybatis批量保存的两种方式(高效插入)
    pagehelper的使用
  • 原文地址:https://www.cnblogs.com/liang24/p/13652760.html
Copyright © 2020-2023  润新知