最长回文子字符串
中心扩散法
class Solution {
public String longestPalindrome(String s) {
int max=0;int maxleft=0;int maxright=0;int sum=0;
for(int i=0;i<s.length();i++){
int left=i;int right=i;
//向左寻找到第一个不与i相等的数
while(left>=0&&s.charAt(left)==s.charAt(i)){
sum=i-left+1;
if(max<sum){
max=Math.max(sum,max);
maxleft=left;
maxright=i;
}
left--;
}
//向右寻找到第一个不与i相等的数
while(right<=s.length()-1&&s.charAt(right)==s.charAt(i)){
sum=right-i+1;
if(max<sum){
max=Math.max(sum,max);
maxleft=i;
maxright=right;
}
right++;
}
//向两边扩散
while(left>=0&&right<=s.length()-1&&s.charAt(left)==s.charAt(right)){
sum=right-left+1;
if(max<sum){
max=Math.max(sum,max);
maxleft=left;
maxright=right;
}
left--;
right++;
}
}
return s.substring(maxleft,maxright+1);
}
}
动态规划
class Solution {
public String longestPalindrome(String s) {
int dp[][]=new int[s.length()][s.length()];//i,j范围内是否是回文子串
dp[s.length()-1][s.length()-1]=1;
int max=0;int l=0;int r=0;
for(int i=0;i<s.length();i++){
dp[i][i]=1;
}
for(int i=s.length()-2;i>=0;i--){
for(int j=i+1;j<s.length();j++){
if(s.charAt(i)==s.charAt(j)&&(dp[i+1][j-1]!=0||j-i==1)){
dp[i][j]=dp[i+1][j-1]+2;
}
if(max<dp[i][j]){
l=i;r=j;
}
max=Math.max(max,dp[i][j]);
}
}
return s.substring(l,r+1);
}
}
最长递增子序列(不一定连续)
class Solution {
public int lengthOfLIS(int[] nums) {
int dp[]=new int[nums.length];//0-i的递增子序列长度
Arrays.fill(dp,1);
int max=dp[0];
for(int i=1;i<nums.length;i++){
for(int j=0;j<i;j++){
if(nums[i]>nums[j]){
dp[i]=Math.max(dp[i],dp[j]+1);
}
}
System.out.println("i="+i);
System.out.println("dp[i]="+dp[i]);
max=Math.max(max,dp[i]);
}
return max;
}
}
编辑距离
class Solution {
public int minDistance(String word1, String word2) {
//dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]
//dp[i][0] :以下标i-1为结尾的字符串word1,和空字符串word2,最近编辑距离为dp[i][0]
int m = word1.length();
int n = word2.length();
int[][] dp = new int[m + 1][n + 1];
// 初始化
for (int i = 1; i <= m; i++) {
dp[i][0] = i;
}
for (int j = 1; j <= n; j++) {
dp[0][j] = j;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
// 因为dp数组有效位从1开始
// 所以当前遍历到的字符串的位置为i-1 | j-1
if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = Math.min(Math.min(dp[i - 1][j - 1], dp[i][j - 1]), dp[i - 1][j]) + 1;
}
}
}
return dp[m][n];
}
}
零钱兑换
class Solution {
public int coinChange(int[] coins, int amount) {
if(coins.length == 0)
return -1;
//dp[j]代表当钱包的总价值为j时,所需要的最少硬币的个数
int[] dp = new int[amount+1];
Arrays.fill(dp,amount+1);
dp[0]=0;
for(int i = 1;i<=amount;i++) {
for (int j = 0;j<coins.length;j++) {
if(coins[j]<=i)
dp[i] = Math.min(dp[i], dp[i-coins[j]]+1);
}
}
if(dp[amount] !=amount+1)
return dp[amount];
return -1;
}
}