动态规划
BM62 斐波那契数列
public class Solution {
public int Fibonacci(int n) {
int a=0,b=1,c=0;
for(int i=0;i<n;i++){
c=a+b;
a=b;
b=c;
}
return a;
}
}
BM63 跳台阶
public class Solution {
public int jumpFloor(int n) {
int a=1,b=1,c=0;
for(int i=0;i<n;i++){
c=a+b;
a=b;
b=c;
}
return a;
}
}
BM64 最小花费爬楼梯
import java.util.*;
public class Solution {
public int minCostClimbingStairs (int[] cost) {
int n=cost.length;
int[] dp=new int[n];//dp[i]代表爬到这层,再向上爬需要耗费的最小值
dp[0]=cost[0];
dp[1]=cost[1];
for(int i=2;i<n;i++){
dp[i]=Math.min(dp[i-1],dp[i-2])+cost[i];
}
return Math.min(dp[n-1],dp[n-2]);
}
}
BM65 输出两个字符串的最长公共子序列(不连续)
import java.util.*;
public class Solution {
public String LCS (String s1, String s2) {
int m=s1.length(),n=s2.length();
int[][] dp=new int[m+1][n+1];
//dp[i][j] 的含义是 s1[0:i-1] 和 s2[0:j-1] 的最长公共子序列的长度。
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(s1.charAt(i-1)==s2.charAt(j-1)) dp[i][j]=dp[i-1][j-1]+1;
else dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
}
}
// return dp[m][n];
if(dp[m][n]==0) return "-1";
StringBuilder sb=new StringBuilder();
while(m>0 && n>0){
if(s1.charAt(m-1)==s2.charAt(n-1)){
sb.append(s1.charAt(m-1));
m--;
n--;
}else{
if(dp[m-1][n]>dp[m][n-1]) m--;
else n--;
}
}
return sb.reverse().toString();
}
}
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int n1 = text1.length(),n2 = text2.length();
int[][] dp = new int[n1 + 1][n2 + 1];
for (int i = 1; i <= n1; i++) {
for (int j = 1; j <= n2; j++) {
if (text1.charAt(i - 1) == text2.charAt(j - 1)) dp[i][j] = dp[i - 1][j - 1] + 1;
else dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
return dp[n1][n2];
}
}
BM66 输出两个字符串的最长公共子串(连续)
import java.util.*;
public class Solution {
public String LCS (String s1, String s2) {
int m=s1.length(),n=s2.length();
int[][] dp=new int[m+1][n+1];
int res=0,end=0;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(s1.charAt(i-1)==s2.charAt(j-1)){
dp[i][j]=dp[i-1][j-1]+1;
if(dp[i][j]>res){
res=dp[i][j];
end=i-1;
}
}
}
}
String s=s1.substring(end+1-res,end+1);
return s;
}
}
class Solution {
public int findLength(int[] A, int[] B) {
int m = A.length,n = B.length;
int[][] dp = new int[m + 1][n + 1];//dp[i][j]代表以A[i-1]与B[j-1]结尾的公共字串的长度
int res = 0;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (A[i - 1] == B[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
res = Math.max(res,dp[i][j]);
}
}
}
return res;
}
}
BM67 在m×n的矩阵上从左上角到右下角不同路径的数目
import java.util.*;
public class Solution {
public int uniquePaths (int m, int n) {
int[][] dp=new int[m][n];
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(i==0) dp[0][j]=1;
else if(j==0) dp[i][0]=1;
else dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
return dp[m-1][n-1];
}
}
BM68 在m×n的矩阵上从左上角到右下角的最小路径和
import java.util.*;
public class Solution {
public int minPathSum (int[][] matrix) {
int m=matrix.length,n=matrix[0].length;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(i==0 && j==0) continue;
else if(i==0) matrix[0][j]+=matrix[0][j-1];
else if(j==0) matrix[i][0]+=matrix[i-1][0];
else matrix[i][j]+=Math.min(matrix[i-1][j],matrix[i][j-1]);
}
}
return matrix[m-1][n-1];
}
}
BM69 把数字翻译成字符串(‘a’->1, ‘b->2’, … , ‘z->26’)
import java.util.*;
public class Solution {
public int solve (String nums) {
if(nums==null ||nums.length()==0) return 0;
int[] dp = new int[nums.length()+1];
dp[0]=1;//dp[i]表示nums[0,i-1]的译码方法有多少种。
dp[1]=nums.charAt(0)=='0'?0:1;
for(int i=2;i<dp.length;i++){
//nums[i-1]无法独立编码也无法nums[i-2]和nums[i-1]组合编码
if(nums.charAt(i-1)=='0' && (nums.charAt(i-2)=='0' || nums.charAt(i-2)>'2')) return 0;
//只能nums[i-2]和nums[i-1]组合编码
else if(nums.charAt(i-1)=='0') dp[i] = dp[i-2];
//nums[i-1]只能独立编码
else if(nums.charAt(i-2)=='0' || nums.charAt(i-2)>'2' || nums.charAt(i-2)=='2'&& nums.charAt(i-1)>'6' )
dp[i] = dp[i-1];
//两种编码方式都可以
else dp[i] = dp[i-1]+dp[i-2];
}
return dp[nums.length()];
}
}
BM70 兑换零钱
import java.util.*;
public class Solution {
public int minMoney (int[] arr, int aim) {
int[] dp=new int[aim+1];
Arrays.fill(dp,aim+1);
dp[0]=0;
for(int i=1;i<=aim;i++){
for(int j=0;j<arr.length;j++){
if(i>=arr[j]) dp[i]=Math.min(dp[i],dp[i-arr[j]]+1);
}
}
return dp[aim]>aim?-1:dp[aim];
}
}
BM71 最长上升子序列(不连续)
import java.util.*;
public class Solution {
public int LIS(int[] nums) {
int n=nums.length;
if(n<=1) return n;
int[] dp=new int[n];//dp[i]表示以nums[i]结尾的最长上升子序列的长度。
Arrays.fill(dp,1);
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
if(nums[i]>nums[j]) dp[i]=Math.max(dp[i],dp[j]+1);
}
}
int res=0;
for(int i=0;i<n;i++) res=Math.max(res,dp[i]);
return res;
}
}
BM72 连续子数组的最大和
public class Solution {
public int FindGreatestSumOfSubArray(int[] arr) {
for(int i=1;i<arr.length;i++){
arr[i]+=Math.max(arr[i-1],0);//以arr[i]结尾的连续子数组的最大和
}
int res=arr[0];
for(int i=1;i<arr.length;i++){
res=Math.max(res,arr[i]);
}
return res;
}
}
BM73 最长回文子串
import java.util.*;
public class Solution {
public int getLongestPalindrome(String s) {
int n = s.length();
//String res = "";
int res = 0;
for (int i = 0; i < 2 * n - 1; i++) {
int l = i / 2;
int r = l + i % 2;
while (l >= 0 && r < n && s.charAt(l) == s.charAt(r)) {
res=Math.max(res,r-l+1);
//String tmp = s.substring(l, r + 1);
//if (tmp.length() > res.length()) res = tmp;
l--;
r++;
}
}
return res;
}
}
647. 回文子串的数目
class Solution6472 {
public int countSubstrings(String s) {
int n = s.length();
int res = 0;
for (int i = 0; i < 2 * n - 1; i++) {
int l = i / 2;
int r = l + i % 2;
while (l >= 0 && r < n && s.charAt(l) == s.charAt(r)) {
res++;
l--;
r++;
}
}
return res;
}
}
BM75 编辑距离
import java.util.*;
public class Solution {
/*
dp[i][j] 代表 word1[0,i-1]位置转换成 word2[0,j-1]位置需要最少步数
当 word1[i] == word2[j],dp[i][j] = dp[i-1][j-1];
当 word1[i] != word2[j],dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1
其中,dp[i-1][j-1] 表示替换操作,dp[i-1][j] 表示删除操作,dp[i][j-1] 表示插入操作。
*/
public int editDistance(String word1, String word2) {
int n1=word1.length(),n2=word2.length();
int[][]dp=new int [n1+1][n2+1];
for(int j=1;j<=n2;j++) dp[0][j]=dp[0][j-1]+1;//插入
for(int i=1;i<=n1;i++) dp[i][0]=dp[i-1][0]+1;//删除
for(int i=1;i<=n1;i++){
for(int j=1;j<=n2;j++){
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-1][j]),dp[i][j-1])+1;
}
}
return dp[n1][n2];
}
}
BM76 正则表达式匹配
import java.util.*;
/*
最后来个归纳:
如果 p.charAt(j) == s.charAt(i) : dp[i][j] = dp[i-1][j-1];
如果 p.charAt(j) == '.' : dp[i][j] = dp[i-1][j-1];
如果 p.charAt(j) == '*':
如果 p.charAt(j-1) != s.charAt(i) : dp[i][j] = dp[i][j-2] //in this case, a* only counts as empty
如果 p.charAt(j-1) == s.charAt(i) or p.charAt(j-1) == '.':
dp[i][j] = dp[i-1][j] //in this case, a* counts as multiple a
or dp[i][j] = dp[i][j-1] // in this case, a* counts as single a
or dp[i][j] = dp[i][j-2] // in this case, a* counts as empty
*/
public class Solution {
public boolean match(String s, String p) {
//往原字符头部插入空格,这样得到 char 数组是从 1 开始,
//而且可以使得 f[0][0] = true,可以将 true 这个结果滚动下去
s = " " + s;
p = " " + p;
int n = s.length(),m = p.length();
boolean[][] dp = new boolean[n][m];//dp[i][j]表示s[0,i]与p[0,j]是否匹配
dp[0][0] = true;
if(p.charAt(1) == s.charAt(1) || p.charAt(1) == '.')dp[1][1] = true;
for(int i = 0;i < n;i++){
for(int j = 1;j < m;j++){
if(p.charAt(j) != '*'){
if(i > 0)dp[i][j] = dp[i-1][j-1] &&
(p.charAt(j) == s.charAt(i) || p.charAt(j) == '.');
}else {
if(i > 0) dp[i][j] = dp[i][j-2] || dp[i-1][j] &&
(p.charAt(j-1) == s.charAt(i) || p.charAt(j-1) == '.');
else{
dp[i][j] = dp[i][j - 2];
}
}
}
}
return dp[n-1][m-1];
}
}
BM77 最长的括号子串
import java.util.*;
public class Solution {
Stack<Integer> stack = new Stack<>();
public int longestValidParentheses(String s) {
if(s==null || s.length()==0) return 0;
char[] c = s.toCharArray();
int[] mark = new int[s.length()];
for(int i=0; i<s.length(); i++){
if(c[i]=='(') stack.push(i);//对于遇到的每个'(',我们将它的下标放入栈中
else{
if(!stack.isEmpty() && c[stack.peek()]=='('){
mark[stack.pop()] = 1;//与当前右括号所匹配的左括号
mark[i] = 1;//当前右括号
}
}
}
int max = 0,cur = 0;
for(int i:mark){
if(i==1){
cur ++;
max = Math.max(max,cur);
}else cur = 0;
}
return max;
}
}
BM78 打家劫舍(一)
import java.util.*;
public class Solution {
public int rob (int[] nums) {
int n=nums.length;
int[] dp=new int[n+1];
dp[0]=0;
dp[1]=nums[0];
for(int i=2;i<=n;i++){
dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i-1]);
}
return dp[n];
}
}
BM79 打家劫舍(二)
import java.util.*;
public class Solution {
public int rob (int[] nums) {
int n=nums.length;
//一个是从0到n-1,另一个是从1到n,然后返回两个结果最大的。
int rob1=getRob(Arrays.copyOfRange(nums,0,n-1));
int rob2=getRob(Arrays.copyOfRange(nums,1,n));
return Math.max(rob1,rob2);
}
private int getRob(int[] nums){
int n=nums.length;
int[] dp=new int[n+1];
dp[0]=0;
dp[1]=nums[0];
for(int i=2;i<=n;i++){
dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i-1]);
}
return dp[n];
}
}
BM80 买卖股票的最好时机(一)
import java.util.*;
public class Solution {
public int maxProfit (int[] prices) {
int cost=Integer.MAX_VALUE,res=0;
for(int price:prices){
cost=Math.min(price,cost);
res=Math.max(res,price-cost);
}
return res;
}
}
BM81 买卖股票的最好时机(二)
import java.util.*;
public class Solution {
public int maxProfit (int[] prices) {
int res=0;
for(int i=1;i<prices.length;i++){
if(prices[i]>prices[i-1]) res+=prices[i]-prices[i-1];
}
return res;
}
}
BM82 买卖股票的最好时机(三)
import java.util.*;
public class Solution {
public int maxProfit(int[] prices) {
int firstBuy = Integer.MIN_VALUE, firstSell = 0;
int secondBuy = Integer.MIN_VALUE, secondSell = 0;
for(int p : prices) {
firstBuy = Math.max(firstBuy, -p);
firstSell = Math.max(firstSell, firstBuy + p);
secondBuy = Math.max(secondBuy, firstSell - p);
secondSell = Math.max(secondSell, secondBuy + p);
}
return secondSell;
}
}