最长递增子序列和最长公共子序列

一、最长递增子序列

例如:{5,3,4,8,6,7 } 最长递增子序列的长度为4,序列为{3、4、6、7}
用a[i]记录原始数据数组。
用d[i]来记录到a[i]这个数据为止时的最大递增子序列的长度,初始化为1.

import java.util.Scanner;

public class Test1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		 Scanner s = new Scanner(System.in);  
	        int n = s.nextInt(); // 序列中数的个数  
	        int[] a = new int[n];  
	        int[] d = new int[n];  
	        for (int i = 0; i < n; i++) {  
	            a[i] = s.nextInt();  
	            d[i] = 1; //用来记录到第i个数据为止时的最长递增子序列长度
	        }  
	        
	        for(int i=1;i<n;i++) {
	        	for (int j=0;j<i;j++) {
	        		//遍历a[i]前面的数据a[j],所有小于a[i]的数d[j]+1,再取这些d[j]中的最大值。
	        		if(a[j]<a[i]) {
	        			d[i]=Math.max(d[i],d[j]+1);
	        		}
	        	}
	        
	        }
	        System.out.println(d[n-1]);  
	}


}

二、最长公共子序列

例如:数组 A{5,6, 7, 1, 2, 8},
排序得到数组 A‘{1, 2, 5, 6, 7, 8},
然后找出数组A和A’的最长公共子序列即可。
显然这里最长公共子序列为{5, 6, 7, 8},也就是原数组A最长递增子序列。

以下解释图片来自其他博客:
如图所示:公共子序列为BCBA,令i=0;j=0的行列全为0,其他网格相同则加1,不同则找左边或者上边的最大值填入。即可统计出最大的公共子序列长度。
[外链图片转存失败(img-FR6lDEz1-1567672217104)(https://img-my.csdn.net/uploads/201207/29/1343545894_4901.PNG)]
状态方程如下:
[外链图片转存失败(img-A9Da79R8-1567672217106)(https://img-my.csdn.net/uploads/201207/29/1343545870_7376.PNG)]

来个题练练:
https://www.nowcoder.com/questionTerminal/28c1dc06bc9b4afd957b01acdf046e69来源:牛客网
给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?输出需要删除的字符个数。

输入描述:
输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.
输出描述:
对于每组数据,输出一个整数,代表最少需要删除的字符个数。

输入输出
abcda2
google2
遇到这个题,直接正反比对,但我愣是没想到这个,双循环比对,记录个数,然后只过了部分答案。看别人的解析才知道用这个!
import java.util.Scanner;

/** 
* @author heye 
* @date 2018年3月24日 上午10:50:21 
* @version 1.0 */

public class Main{
	public static void main(String[] args) {
		Scanner c = new Scanner(System.in);
		String string1 ="";
		while(c.hasNext()) {
			//输入字符串
			string1= c.nextLine();
			//输入字符串的倒序
			String string2 = new StringBuffer(string1).reverse().toString();

			char[] ds1 = string1.toCharArray();
			char[] ds2 = string2.toCharArray();
			int len = ds1.length;
			//记录个数,空一行一列出来,int数组初始化均为0
			int[][] arr = new int[len+1][len+1];
			for(int i=1;i<=len;i++) {
				for(int j = 1;j <=len ; j++) {
					if(ds1[i-1] == ds2[j-1]) {
						arr[i][j]= arr[i-1][j-1]+1;
					}else {
						arr[i][j] =Math.max(arr[i-1][j],arr[i][j-1]);
					}
				}
			}
			//最长公共子序列为arr[len][len],答案是删掉字符数
			System.out.println(len-arr[len][len]);
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值