*算法训练(leetcode)第三十三天 | 322. 零钱兑换、279. 完全平方数、*139. 单词拆分

322. 零钱兑换

leetcode题目地址

dp数组存储amount=j时的最少硬币数。
状态转移方程: d p [ j ] = m i n ( d p [ j ] , d p [ j − c o i n s [ i ] ] + 1 ) dp[j] = min(dp[j], dp[j-coins[i]]+1) dp[j]=min(dp[j],dp[jcoins[i]]+1)
因为是取最小,所以初始化需要赋值为最大值。根据题目数据范围可知:coins[i]>=1,因此可以组成amount的硬币数至多amount个。所有将dp数组初始化为amount+1。dp[0]需要初始化为0,因为amount=0时不需要取硬币,因此硬币数为0。

时间复杂度: O ( n ∗ m ) O(n*m) O(nm)
空间复杂度: O ( n ) O(n) O(n)

// c++
class Solution {
public:
    
    int coinChange(vector<int>& coins, int amount) {
        if(amount==0) return 0;
        vector<int> dp(amount+1, amount+1);
        dp[0] = 0;
        for(int i=0; i<coins.size(); i++){
            for(int j=coins[i]; j<=amount; j++){
                dp[j] = min(dp[j], dp[j-coins[i]]+1);
            }
            /*
            // 输出dp数组
            for(int j=0;j<=amount;j++) cout<<dp[j]<<" ";
            cout<<endl;
            */
        }
       
        return dp[amount]==amount+1?-1:dp[amount];
        
    }
};

279. 完全平方数

leetcode题目地址

和上题思路完全一致,只是需要自行初始化一个完全平方数数组,相当于上题的硬币数组。

时间复杂度: O ( n ∗ n ) O(n*\sqrt{n}) O(nn )
空间复杂度: O ( n ) O(n) O(n)

版本一(存储平方数)

// c++
class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n+1, n+1);
        vector<int> square;
        for(int i=0; i<=sqrt(n); i++){
            square.emplace_back(i*i);
        }
        dp[0] = 0;
        for(int i=1; i<square.size(); i++){
            for(int j=square[i]; j<=n; j++){
                dp[j] = min(dp[j], dp[j-square[i]]+1);
            }
            /*
            // 输出dp数组
            for(int j=0;j<=n;j++) cout<<dp[j]<<" ";
            cout<<endl;
            */
        }
        
        return dp[n];
    }
};

版本二(不存储平方数)

// c++
class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n+1, n+1);
        
        dp[0] = 0;
        for(int i=1; i*i<=n; i++){
            for(int j=i*i; j<=n; j++){
                dp[j] = min(dp[j], dp[j-i*i]+1);
            }
            /*
            // 输出dp数组
            for(int j=0;j<=n;j++) cout<<dp[j]<<" ";
            cout<<endl;
            */
        }
        
        return dp[n];
    }
};

*139. 单词拆分

leetcode题目地址

一开始想的是用回溯暴力搜索,动规毫无思路……

思路

时间复杂度: O ( n 3 ) O(n^3) O(n3)
空间复杂度: O ( n ) O(n) O(n)

// c++
class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> wordset(wordDict.begin(), wordDict.end());
        vector<bool> dp(s.size()+1, false);
        dp[0] = true;
        for(int i=1; i<=s.size(); i++){
            for(int j=0; j<i; j++){
                string str = s.substr(j, i-j);
                if(wordset.find(str)!=wordset.end() && dp[j]){
                    dp[i] = true;
                }
            }
        }
        return dp[s.size()];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值