动态规划总结

1、动态规划试题

给定两个字符串str1和str2,
返回这两个字符串的最长公共子序列长度
比如 : str1 = “a12b3c456d”,str2 = “1ef23ghi4j56k”
最长公共子序列是“123456”,所以返回长度6
public static int maxCommonQueue(String s1,String s2){
	if(s1==null || s2==null || s1.length==0 || s2.length==0){
		return 0;
	}
	char str1=s1.toCharArray();
	char str2=s2.toCharArray();
	return process(str1,str2,str1.length-1,str2.length-1);
}
public static int process(char[] str1,char[] str2 ,int len1,int len2){
	if(len1==0 && len2==0){
	return str1[0]==str2[0]?1:0
	}else if(len1==0){
		if(str1[0] == str2[0]){
			return 1;
		}else{
			return process(str1,str2,len1,len2-1);
		}
	}else if(len2==0){
		if(str2[0]==str1[len1]){
			return 1;
		}else{
			return process(str1,str2,len1-1,len2);
		}
	}else{
		int p1=process(str1,str2,len1-1,len2);
		int p2=process(str1,str2,len1,len2-1);
		int p3=str1[len1]==str2[len2]?(1+process(str1,str2,len1-1,len2-1)):0;
		return Math.max(p1,Math.max(p2,p3));
	}
}

优化算法:

public static int dp(String s1,String s2){
	if(s1==null || s2==null || s1.length==0 || s2.length==0){
		return 0;
	}
	int len1=s1.length;
	int len2=s2.length;
	char[] str1=s1.toCharArray();
	char[] str2=s2.toCharArray();
	int[][] dp=new int[len1+1][len2+1];
	dp[0][0]=str1[0]==str2[0]?1:0;
	for(int i=1;i<len1;i++){
		dp[i][0]=str[len2]==str1[0]?1:dp[len1-1][0];	
	}
	for(int j=1;j<len2;j++){
		dp[0][j]=str1[len1]==str2[0]?1:dp[0][len2-1]
	}
	for(int i=1;i<len1;i++){
		for(int j=1;j<len1;j++){
			int p1=dp[i-1][j];
			int p2=dp[i][j-1];
			int p2=str1[i]==str2[j]?(1+dp[i-1][j-1]):0;
			dp[i][j]=Math.max(p1,Math.max(p2,p3));
		}
	}
	return dp[len1-1][len2-1];
}

2、返回最长的回文字符串

给定一个字符串str,返回这个字符串的最长回文子序列长度
比如 : str = “a12b3c43def2ghi1kpm”
最长回文子序列是“1234321”或者“123c321”,返回长度7
public static int maxLength(String s){
	if(s==null || s.length()=0){
		return 0;
	}
	char[] str=s.toCharArray();
	return process(str,0,str.length-1);
}
public static int process(char[] str,int L,int R){
	if(L==R){
		return 1;
	}
	if(L==R-1){
		return str[L]==str[R-1]?2:1;
	}
	int p1=process(str,L+1,R-1);
	int p2=process(str,L+1,R);
	int p3=process(str,L,R-1);
	int p4=str[L]==str[R]?(2+process(L+1,R-1)):0;
	return Math.max(Math.max(p1,p2),Math.max(p3,p4));
}

优化:

public static int maxLength(String s){
	if(s==null || s.length()==0){
		return 0;
	}
	char[] str=s.toCharArray();
	int N=str.length;
	int[][] dp=new int[N][N];
	dp[N-1][N-1]=1;
	for(int i=0;i<N-1;i++){
		dp[i][i]=1;
		dp[i][i+1]=str[i]==str[i+1]?2:1;
	}
	for(int i=N-3;i>=0;i--){
		for(int j=i+2;i<N;i++){
			int p1=dp[i+1][j-1];
			int p2=dp[i+1][j];
			int p3=dp[i][j-1];
			int p4=str[i]==str[j]?(2+dp[i+1][j-1]):0;
			dp[i][j]=Math.max(Math.max(p1,p2),Math.max(p3,p4));
		}
	}
	return dp[0][N-1]
}

贪心算法

一个整数区间 [a, b]  ( a < b ) 代表着从 a 到 b 的所有连续整数,包括 a 和 b。
 *
 * 给你一组整数区间intervals,请找到一个最小的集合 S,使得 S 里的元素与区间intervals中的每一个整数区间都至少有2个元素相交。
 *
 * 来源:力扣(LeetCode)
 * 链接:https://leetcode.cn/problems/set-intersection-size-at-least-two

解题思路:对每个集合的末尾从小到大排列,如果末尾相等就按照第一个位置的数从大到小排列,

public static int minCommonNumber(int[][] list){
	Arrays.sort(list,(a,b)->(a[1] != b[1]): (a[1]-b[1]) ? (b[0]-a[0]));
	int length-=list.length;
	int pos=list[0][1];
	int pre=pos-1;
	int ans=2;
	for(int i=1;i<length;i++){
		if(list[i][0]>pre){
			if(list[i][0]>pos){
				ans+=2;
				pre=list[i][1]-1;
			}else{
				pre=pos;
			}
			pos=list[i][1];
		}
	}
	return ans;
}

有效括号

给定一个只包含三种字符的字符串:( ,) 和 *,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:
任何左括号 ( 必须有相应的右括号 )。
任何右括号 ) 必须有相应的左括号 ( 。
左括号 ( 必须在对应的右括号之前 )。
* 可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符串。
一个空字符串也被视为有效字符串。
  链接:https://leetcode.cn/problems/valid-parenthesis-string

解题思路:利用贪心算法判断其最大值和最小值的范围,如果最小值等于0证明为有效字符串

public boolean checkValidString(String str){
	char[] s=str.toCharArray();
	int min=0;
	int max=0;
	for(char x:s){
		if(x=='('){
			max++;
			min++;
		}else{
			if(x==')' && max==0){
				return false;
			}
			max+=x==')'?-1:1;
			if(min>0){
				min--;
			}
		}
	}
	return min==0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值