【LeetCode】Sama的个人记录_51

在这里插入图片描述

>>> 两个经典模板:
>>> 1. 回溯
>>> 2. 动态规划找回文串
class Solution {
    
    
    public List<List<String>> partition(String s) {
    
    
        traceBack(new ArrayList<>(), s, 0, getDp(s));
        return res;
    }

    private List<List<String>> res = new ArrayList<>();

    private void traceBack(List<String> temp, String s, int index, boolean[][] dp) {
    
    
        if (index == s.length()) {
    
    
            res.add(new ArrayList<>(temp));
            return;
        }
        for (int i = index; i < s.length(); i++) {
    
    
            if (dp[index][i]) {
    
    
                temp.add(s.substring(index, i + 1));
                traceBack(temp, s, i + 1, dp);
                temp.remove(temp.size() - 1);
            }
        }
    }

    private boolean[][] getDp(String s) {
    
    
        int len = s.length();
        boolean[][] dp = new boolean[len][len];
        for (int i = 0; i < len; i++) {
    
    
            dp[i][i] = true;
        }
        for (int j = 1; j < len; j++) {
    
    
            for (int i = 0; i < j; i++) {
    
    
                if (s.charAt(i) == s.charAt(j)) {
    
    
                    dp[i][j] = j - i < 3 ? true : dp[i + 1][j - 1];
                } else {
    
    
                    dp[i][j] = false;
                }
            }
        }
        return dp;
    }
}

 
 

在这里插入图片描述

>>> 记住一句话:求的是路径则用回溯,求的是路径的长度则用动态规划。
class Solution {
    
    
    public int minCut(String s) {
    
    
        int len = s.length();

        // 预处理回文串(第一次动态规划)
        boolean[][] isPalindrome = new boolean[len][len];
        for (int i = 0; i < len; i++) {
    
    
            isPalindrome[i][i] = true;
        }
        for (int j = 1; j < len; j++) {
    
    
            for (int i = 0; i < j; i++) {
    
    
                if (s.charAt(i) == s.charAt(j)) {
    
    
                    isPalindrome[i][j] = j - i < 3 ? true : isPalindrome[i + 1][j - 1];
                } else {
    
    
                    isPalindrome[i][j] = false;
                }
            }
        }

        // 求最少分割次数(第二次动态规划)
        int[] dp = new int[len];
        Arrays.fill(dp, Integer.MAX_VALUE);
        for (int i = 0; i < len; i++) {
    
    
            if (isPalindrome[0][i]) {
    
    
                dp[i] = 0;
            } else {
    
    
                for (int j = 1; j <= i; j++) {
    
    
                    if (isPalindrome[j][i]) {
    
    
                        dp[i] = Math.min(dp[i], dp[j - 1] + 1);
                    }
                }
            }
        }
        return dp[len - 1];
    }
}

 
 

在这里插入图片描述

>>> 大数相乘经典模板。说几个小细节帮助记忆:
>>>	1. 两数其中一个数为零,直接特判返回"0"
>>> 2. 长度为m和n的数字相乘,其长度最大为m*n
>>> 3. 没有必要完全模拟乘法竖式,先乘高位也是可以的,且这样遍历数组从下标0开始,比较优雅
>>> 4. 下标i和下标j的数字相乘,结果加到res的下标(i+j+1),进位进到res的下标(i+j)
class Solution {
    
    

    public String bigNumMultiply(String num1, String num2) {
    
    
    	// "0"的特判
        if (num1.equals("0") || num2.equals("0")) {
    
    
            return "0";
        }
        int len1 = num1.length();
        int len2 = num2.length();
        int[] res = new int[len1 + len2];
		// 模拟
        for (int i = 0; i < len1; i++) {
    
    
            for (int j = 0; j < len2; j++) {
    
    
                int n1 = num1.charAt(i) - '0';
                int n2 = num2.charAt(j) - '0';
                int n3 = res[i + j + 1] + n1 * n2;
                res[i + j + 1] = n3 % 10;
                res[i + j] += n3 / 10;
            }
        }
		// 去前缀0
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < res.length; i++) {
    
    
            if (i == 0 && res[i] == 0) {
    
    
                continue;
            }
            sb.append(res[i]);
        }
        return sb.toString();
    }
}

猜你喜欢

转载自blog.csdn.net/m0_46202073/article/details/114494433