力扣动态规划篇

发布于:2024-03-10 ⋅ 阅读:(81) ⋅ 点赞:(0)

以下思路来自代码随想录和官方题解。

70.爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 12 个台阶。你有多少种不同的方法可以爬到楼顶呢?

输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1+ 12. 2 阶

输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
4. 1+ 1+ 15. 1+ 26. 2+ 1
class Solution {
    public int climbStairs(int n) {
        int[] dp = new int[n + 1];
        dp[0] = 1;
        dp[1] = 1;
        for (int i = 2; i <= n; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }
}

118.杨辉三角

给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。
在这里插入图片描述

输入: numRows = 5
输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]

输入: numRows = 1
输出: [[1]]
class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> result = new ArrayList<>(); 
        List<Integer> row1 = new ArrayList<>(); 
        row1.add(1); // 第一行只有一个元素,值为1
        result.add(row1); 
        if (numRows == 1) { // 如果只需要生成一行,直接返回结果
            return result;
        }
        List<Integer> row2 = new ArrayList<>(); 
        row2.add(1); // 第二行的第一个元素为1
        row2.add(1); // 第二个元素也为1
        result.add(row2); // 将第二行添加到结果中
        if (numRows == 2) { // 如果只需要生成两行,直接返回结果
            return result;
        }

        // 从第三行开始生成
        for (int i = 2; i < numRows; i++) {
            List<Integer> list = new ArrayList<>(); 
            // 当前行的第一个元素为1
            list.add(1); 
            for (int j = 1; j < i; j++) {
                // 计算当前行的中间元素,等于上一行的左上方元素与上方元素的和
                Integer temp = result.get(i - 1).get(j - 1) + result.get(i - 1).get(j);
                list.add(temp); 
            }
            // 当前行的最后一个元素为1
            list.add(1); 
            result.add(list); 
        }
        return result;
    }
}

279.完全平方数

给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。

输入:n = 12
输出:3 
解释:12 = 4 + 4 + 4

输入:n = 13
输出:2
解释:13 = 4 + 9
class Solution {
    public int numSquares(int n) {
        int[] f = new int[n + 1]; 
        for (int i = 1; i <= n; i++) { // 遍历 1 到 n
            int minn = Integer.MAX_VALUE; // 初始化 minn 为最大整数值
            for (int j = 1; j * j <= i; j++) { // 遍历 1 到 i 的平方根
                minn = Math.min(minn, f[i - j * j]); // 更新 minn 为 f[i - j * j] 和 minn 中的较小值
            }
            // 将 f[i] 设置为 minn + 1
            f[i] = minn + 1; 
        }
        return f[n]; 
    }
}


139.单词拆分

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true

注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。

输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以由 "leet""code" 拼接成。

输入: s = "applepenapple", wordDict = ["apple", "pen"]
输出: true
解释: 返回 true 因为 "applepenapple" 可以由 "apple" "pen" "apple" 拼接成。
     注意,你可以重复使用字典中的单词。
     
输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
输出: false
class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        Set<String> set = new HashSet<>(wordDict);
        boolean[] dp = new boolean[s.length()+1];
        // 初始化dp[0]为true,表示空字符串可以由空单词组成
        dp[0] = true;

        for(int i=1;i<=s.length();i++){
            for(int j=0;j<i;j++){
                // 如果dp[j]为true且s的子串s.substring(j,i)在wordDict中
                if(dp[j] && set.contains(s.substring(j,i))){
                    // 将dp[i]设置为true,表示s的前i个字符可以由wordDict中的单词组成
                    dp[i] = true;
                    break;
                }
            }
        } 
        return dp[s.length()];
    }
}

647.回文子串

给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。

回文字符串 是正着读和倒过来读一样的字符串。

子字符串 是字符串中的由连续字符组成的一个序列。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

输入:s = "abc"
输出:3
解释:三个回文子串: "a", "b", "c"

输入:s = "aaa"
输出:6
解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"
//获取字符串s的长度n,并初始化答案ans为0。
//使用一个for循环遍历所有可能的回文中心位置,范围是0到2 * n - 1。
//对于每个中心位置i,计算左右边界l和r。如果i是偶数,则l = i / 2,r = l + 1;如果i是奇数,则l = i / 2,r = l。
//使用while循环检查当前中心位置是否为回文子串的中心。如果l >= 0且r < n且s.charAt(l) == s.charAt(r),则说明当前中心位置是回文子串的中心。
//如果当前中心位置是回文子串的中心,将左边界l减1,右边界r加1,并将答案ans加1。
//当for循环结束后,返回答案ans。
class Solution {
    public int countSubstrings(String s) {
        int n = s.length(), ans = 0;
        for (int i = 0; i < 2 * n - 1; ++i) {
            int l = i / 2, r = i / 2 + i % 2;
            while (l >= 0 && r < n && s.charAt(l) == s.charAt(r)) {
                --l;
                ++r;
                ++ans;
            }
        }
        return ans;
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到