下降路径最小和
给你一个 n x n
的 方形 整数数组 matrix
,请你找出并返回通过 matrix
的下降路径 的 最小和 。
下降路径 可以从第一行中的任何元素开始,并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列(即位于正下方或者沿对角线向左或者向右的第一个元素)。具体来说,位置 (row, col)
的下一个元素应当是 (row + 1, col - 1)
、(row + 1, col)
或者 (row + 1, col + 1)
。
class Solution {
public int minFallingPathSum(int[][] matrix) {
int n = matrix.length;
int m = matrix[0].length;
int[][] dp = new int[n + 1][m + 1];
for (int i = 0; i < m; i++)
dp[0][i] = matrix[0][i];
for (int i = 1; i < n; i++) {
for (int j = 0; j < m; j++) {
// 根据当前位置,拿到上一行位置上当前下一个位置的数据,比较得到一个最小值
int left = j > 0 ? dp[i - 1][j - 1] : Integer.MAX_VALUE;
int now = dp[i - 1][j];
int right = j < m - 1 ? dp[i - 1][j + 1] : Integer.MAX_VALUE;
//将最小值与当前值相加
int minV = Math.min(left, Math.min(now, right));
dp[i][j] = matrix[i][j] + minV;
}
}
//比较最后一行中,得到实际上最小的值
int minV = Integer.MAX_VALUE;
for (int i = 0; i < m; i++) {
minV = Math.min(minV, dp[n - 1][i]);
}
return minV;
}
}
最大正方形
在一个由 '0'
和 '1'
组成的二维矩阵内,找到只包含 '1'
的最大正方形,并返回其面积。
class Solution {
public int maximalSquare(char[][] matrix) {
int maxSide = 0;
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return maxSide;
}
int n = matrix.length;
int m = matrix[0].length;
int[][] dp = new int[n + 1][m + 1];
int maxV = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (matrix[i][j] == '1') {
if (i == 0 || j == 0) {
dp[i][j] = 1;
} else {
//找当前位置上、左、左上三个位置,判断是否都为1,代表是一个正方形
int minV = Math.min(dp[i][j - 1], Math.min(dp[i - 1][j], dp[i - 1][j - 1]));
dp[i][j] = minV + 1;
}
maxV = Math.max(maxV, dp[i][j]);
}
}
}
return maxV * maxV;
}
}
最长回文串
给你一个字符串 s
,找到 s
中最长的回文子串
示例 1:
输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。示例 2:
输入:s = "cbbd" 输出:"bb"
下面是多种解题方法
1、暴力判断
class Solution {
public String longestPalindrome(String s) {
String res = "";
int n = s.length();
if (n == 1)
return s;
for (int i = 0; i < n; i++) {
for (int j = n ; j > i; j--) {
String str = getPalindrome(s.substring(i, j));
res = str.length() > res.length() ? str : res;
}
}
return res;
}
String getPalindrome(String s) {
int len = s.length() - 1;
int start = 0;
while (start <= len && s.charAt(start) == s.charAt(len)) {
start++;
len--;
}
return start >= len ? s : "";
}
}
2、中心扩散方法,先左右判断是否可回文,最后再从左右后节点判断回文
class Solution {
public String longestPalindrome(String s) {
if (s == null || s.length() == 0) {
return "";
}
int strLen = s.length();
int left = 0;
int right = 0;
int len = 1;
int maxStart = 0;
int maxLen = 0;
for (int i = 0; i < strLen; i++) {
left = i - 1;
right = i + 1;
while (left >= 0 && s.charAt(left) == s.charAt(i)) {
len++;
left--;
}
while (right < strLen && s.charAt(right) == s.charAt(i)) {
len++;
right++;
}
while (left >= 0 && right < strLen && s.charAt(right) == s.charAt(left)) {
len = len + 2;
left--;
right++;
}
if (len > maxLen) {
maxLen = len;
maxStart = left;
}
len = 1;
}
return s.substring(maxStart + 1, maxStart + maxLen + 1);
}
}
3、动态规划:记录left到right是否为回文串,减少判断次数
class Solution {
public String longestPalindrome(String s) {
if(s == null || s.length() == 1) return s;
int len = s.length();
int maxStart = 0;
int maxLen = 1;
int maxEnd = 0;
// dp[i][j] 代表的是dp数组中i位置到j位置,是否为回文串的判断值
boolean[][] dp = new boolean [len][len];
for(int r = 1; r < len; r++){
for(int l = 0; l < r;l++){
if(s.charAt(l) == s.charAt(r) && (r-l <= 2 || dp[l+1][r-1])){
dp[l][r] = true;
if(r - l + 1 > maxLen){
maxLen = r - l +1;
maxStart = l;
maxEnd = r;
}
}
}
}
return s.substring(maxStart,maxStart + maxLen);
}
}
单次拆分
给你一个字符串 s
和一个字符串列表 wordDict
作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s
则返回 true
。
注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。
示例 1:
输入: s = "leetcode", wordDict = ["leet", "code"] 输出: true 解释: 返回 true 因为 "leetcode" 可以由 "leet" 和 "code" 拼接成。示例 2:
输入: s = "applepenapple", wordDict = ["apple", "pen"] 输出: true 解释: 返回 true 因为 "applepenapple" 可以由 "apple" "pen" "apple" 拼接成。 注意,你可以重复使用字典中的单词。示例 3:
输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"] 输出: false
dp直接暴力判断做就行了
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
int len = s.length();
boolean[] dp = new boolean[len + 1];
dp[0] = true;
for (int i = 0; i <= len; i++) {
for (String word : wordDict) {
int wordLen = word.length();
// 从i-wordLen 位置到 i位置的字符串,判断是否能与字典表中匹配
if (i >= wordLen && dp[i - wordLen] && word.equals(s.substring(i - wordLen, i))) {
dp[i] = true;
}
}
}
return dp[len];
}
}