LeetCode刷题day005 (Jieky)

上一篇博客问题解

/*
最长上升子序列(LIS)问题:给定长度为n的序列a,从a中抽取出一个子序列,这个子序列需要单调递增。问最长的上升子序列(LIS)的长度。
  e.g. 1,5,3,4,6,9,7,8的LIS为1,3,4,6,7,8,长度为6。
*/

import java.util.Arrays;

public class Test02 {
     
    public static void main(String[] args){
     
        // 最坏情况,数列是降序的,最长升序子序列长度为1
        int[] f = {
     1,1,1,1,1,1,1,1,1,1,1};
        int[] a = {
     1,5,3,4,6,9,7,8,1,2,3};

        for (int x = 0; x < a.length;x++){
     
            for (int p = 0; p < x ;p++){
     
                if(a[p] < a[x]){
     
                    // 计算f[x]结尾的子序列长度时,其之前的以f[p]结尾的子序列长度是已知的
                    // p是与f[x]求解直接相关的量,x是当前的局面,f(p)是p->x的状态转移方程
                    f[x] = Math.max(f[p]+1,f[x]);
                }
            }
        }

        int ans = -1;
        for(int x = 0;x < a.length;x++){
     
            // 目标f(T)
            ans = Math.max(ans,f[x]);
        }
        // 遗留一个问题,如何输出这个子序列
        System.out.println(ans);
        System.out.println("---------------------------");

        // 找出f中最大值,其包含的子序列一定在左边,找到比该值小1的下标
        int end = f.length;
        int pre = -1;
        int list[] = new int[ans];
        int count = 0;
        while (true){
     
            int idx = -1;
            for (int i=0,max=-1;i<end;i++){
     
                // a[i] < pre 保证当前的输出不会比上一次的输出大
                if (f[i] > max && (pre==-1 || a[i] < pre)) {
     
                    // 下标对应的值越大越好,但是不能比上一次的大
                    max = f[i]; idx = i;
                }else if (f[i] == max && a[i] < a[idx] && (pre==-1 || a[i] < pre)){
     
                    // 如果下标对应子序列长度相等,下标在a中对应的值小的获胜
                    max = f[i]; idx = i;
                }
            }
            // 保存上一次的值
            pre = a[idx];
            // 限定下一次寻找的上限
            end = idx;
            list[count++] = a[idx];
            // 跳出循环在输出之后
            if (end == 0) break;
        }
        System.out.println(new StringBuffer(Arrays.toString(list)).reverse());
    }
}

LeetCode第5题

/*
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example 1: Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.

Example 2:
Input: "cbbd"
Output: "bb"
*/

public class LongestPalindromicSubstring{
     
	public static void main(String[] args){
     
		String str1 = "babad";
		String str2 = "cbbd";
		String str3 = "d";
		String str4 = "abc435cba";
		String str5 = "abc2333cba";
		String str6 = "abcdefg";
		
		LongestPalindromicSubstring lps = new LongestPalindromicSubstring();
		String ans = lps.longestPalindrome03(str5);
		
		System.out.println(ans);
	}
	
	// 使用了动态规划思想,从长度为1的子串开始判断
	// 各种长度为1的子串然后向两边延伸,这样只要判断新延伸的两个字符是否相等
	// 初始长度为2的子串同理。以len=1的延伸囊括乐奇数长度,len=2的延伸囊括的偶数长度
	public String longestPalindrome03(String s) {
     
		int length = s.length();
		boolean[][] P = new boolean[length][length];
		int maxLen = 0;
		String maxPal = null;
		//遍历所有的长度
		for (int len = 1; len <= length; len++) 
			// 遍历所有长度下的所有可能的开始下标
			for (int start = 0; start < length; start++) {
     
				// 求出start开始长度为len的尾索引end
				int end = start + len - 1;
				// 下标已经越界,结束本次循环
				if (end >= length) break;
				// 长度为 1 和 2 的不能判断P[start + 1][end - 1],其因为不存在,
				// 而只要判断s.charAt(start) == s.charAt(end)
				P[start][end] = (len == 1 || len == 2 || P[start + 1][end - 1]) && s.charAt(start) == s.charAt(end); 
				if (P[start][end] && len > maxLen) {
     
					maxPal = s.substring(start, end + 1);
				}
			}
		return maxPal;
	}
	
	//根据会问串的定义,正反读是一样的,那么我们把问题转化为求公共最大子串
	// https://blog.csdn.net/u010397369/article/details/38979077
	public String longestPalindrome02(String s){
     
		
		// 判断字符串是否为null、空串
		if (s == null || s.equals("")){
     
			return null;
		}
		
		String str1 = new String(s);
		// 将字符串逆序
		String str2 = new StringBuffer(s).reverse().toString();
		
		// 将字符串转化为数值,方便处理
		char[] strChar1 = str1.toCharArray();
		char[] strChar2 = str2.toCharArray();
		
		// 生成字符串匹配矩阵
		int[][] matrix = new int[strChar1.length][strChar2.length];
		
		int maxLen = -1;
		// 记录翻转前的尾索引
		int maxRear = -1;
		// 记录翻转后的尾索引
		int reverseRear = -1;
		for (int i = 0 ;i < strChar1.length;i++){
     
			for (int j = 0;j < strChar2.length;j++){
     
				if (strChar1[i] == strChar2[j]){
     
					if (i > 0 && j > 0){
     
						// 这里用到了动态规划思想,请看上一篇博客
						// 这里只使用到了上一列/行的信息
						matrix[i][j] = matrix[i-1][j-1] + 1;
					}else{
     
						matrix[i][j] = 1;
					}
					
					// 保留最大回文长度及其尾元素索引
					if (matrix[i][j] > maxLen){
     
						// 检查是否是真的回文
						if((strChar1.length - 1 - i) + (matrix[i][j] - 1) == j){
     
							maxLen = matrix[i][j];
							maxRear = i;
							reverseRear = j;
						}
					}
				}
			}
		}
		// 返回最大回文串前,检查是否是真的回文
		// 判断放在这里很危险,会漏掉解,例如:"abc2333cba"
		// String ans = null;
		// if ((strChar1.length - 1 - maxRear) + (maxLen - 1) == reverseRear){
     
			// ans = str1.substring(maxRear - maxLen + 1,maxRear+1);
		// }
		return str1.substring(maxRear - maxLen + 1,maxRear+1);
	}
	
	// 暴力破解
	public boolean isPalindromic(String s){
     
		int len = s.length();
		for(int i = 0;i < len/2;i++){
     
			if(s.charAt(i) != s.charAt(len-1-i)){
     
				return false;
			}
		}
		return true;
	}
	public String longestPalindrome01(String s){
     
		int len = s.length();
		int maxLen = -1;
		String ans = null;
		for (int i =0 ;i< len;i++){
     
			for (int j = i + 1;j <= len;j++){
     
				// substring是左闭右开的
				boolean flag = isPalindromic(s.substring(i,j));
				if (flag && s.substring(i,j).length() > maxLen){
     
					maxLen = s.substring(i,j).length();
					ans = s.substring(i,j);
				}
			}
		}
		return ans;
	}
}

你可能感兴趣的:(LeetCode,java,leetcode)