longestIncreasingSequence最长上升子序列问题

  1 package dp;
  2
  3 /**
  4  * 最长上升子序列问题
  5  */
  6 public class LongestIncreasingSubsequence
  7 {
  8     /**
  9      * 原始dp
 10      * @param arr
 11      * @return
 12      */
 13     public static int maxLength(int[] arr)
 14     {
 15         int[] len = new int[arr.length] ; //以i为结尾的最长上升子序列
 16         int[] mark = new int[arr.length] ;//标记以i为结尾的最长上升子序列的上一个节点所在的上上子序列位置
 17         len[0] = 1 ;
 18         mark[0] = -1 ;
 19
 20         int maxPos = 0 ;
 21         for(int i=1 ; i<len.length ; i++)
 22         {
 23             len[i] = 1 ;
 24             mark[i] = -1 ;
 25             for(int j=i-1 ; j>=0 ; j--)
 26             {
 27                 if(arr[j] < arr[i] && (len[j]+1) > len[i])
 28                 {
 29                     len[i] = len[j]+1 ;
 30                     mark[i] = j ;
 31                 }
 32
 33             }
 34             if(len[maxPos] < len[i])
 35                 maxPos = i ;
 36         }
 37
 38
 39         int maxP = maxPos ;
 40         while (maxP != -1)
 41         {
 42             System.out.println(arr[maxP]);
 43             maxP = mark[maxP] ;
 44         }
 45         return len[maxPos] ;
 46     }
 47
 48     /**
 49      * 使用二分加速的dp
 50      * @param arr
 51      * @return
 52      */
 53     public static int maxLength2(int[] arr)
 54     {
 55         int[] len = new int[arr.length] ; //以i为结尾的最长上升子序列
 56         int[] mark = new int[arr.length] ;//标记以i为结尾的最长上升子序列的上一个节点所在的上上子序列位置
 57         int[] m = new int[arr.length+1] ;//标记长度为x的子序列的最小值在arr中的位置
 58
 59         int mLength = 1 ;
 60         len[0] = 1 ;
 61         mark[0] = -1 ;
 62         m[1] = 0 ;
 63
 64         int maxPos = 0 ;
 65         for(int i=1 ; i<len.length ; i++)
 66         {
 67             len[i] = 1 ;
 68             mark[i] = -1 ;
 69
 70             int pos = binarySearch(arr , m , mLength , arr[i]) ;
 71             if(pos != -1)
 72             {
 73                 len[i] = len[pos]+1 ;
 74                 mark[i] = pos ;
 75             }
 76
 77             if(mLength < len[i])
 78             {
 79                 m[len[i]] = i ;
 80                 mLength++ ;
 81             }
 82             else if(arr[m[len[i]]] > arr[i])
 83             {
 84                 m[len[i]] = i ;
 85             }
 86
 87             if(len[maxPos] < len[i])
 88                 maxPos = i ;
 89         }
 90
 91
 92         int maxP = maxPos ;
 93         while (maxP != -1)
 94         {
 95             System.out.println(arr[maxP]);
 96             maxP = mark[maxP] ;
 97         }
 98         return len[maxPos] ;
 99     }
100
101     /**
102      * 寻找arr中比k小的最大数
103      * @param n 表示m的长度
104      * @param m 表示标记长度为x的子序列的最小值的位置的数组
105      * @return 该元素在arr中的位置(为标记函数而服务的)
106      */
107     private static int binarySearch(int[] arr , int[] m , int n , int k)
108     {
109         int lo = 1 ;
110         int hi = n ;
111
112         while (lo < hi)
113         {
114             int mid = lo + (hi-lo)/2 ;
115             if(arr[m[mid]] > k)
116                 hi = mid-1 ;
117             else if(arr[m[mid]] < k)
118                 lo = mid+1 ;
119             else
120             {
121                 if(mid == 1)
122                     return -1 ;
123                 else
124                     return m[mid-1] ;
125             }
126         }
127
128         if(lo == hi)
129         {
130             if(arr[m[lo]] > k)
131                 return m[lo-1] ;
132             else
133                 return m[lo] ;
134         }
135         else if(lo == n+1)
136                 return m[hi] ;
137         return -1 ;
138     }
139
140     public static void main(String[] args) {
141         int[] arr = new int[]{
142                 1,4,8,3,4,5
143         //    3,5,1,7,5,9,3,5
144         } ;
145 //                1, 7, 3, 5, 9, 4, 1
146
147         System.out.println(maxLength2(arr));
148     }
149 }

//http://blog.csdn.net/code_pang/article/details/8757380

//http://blog.csdn.net/chenwenshi/article/details/6027086

时间: 2024-10-10 19:23:02

longestIncreasingSequence最长上升子序列问题的相关文章

14-高效求最长公共子序列(二维数组存不下)

/*                                   See LCS again时间限制:1000 ms  |  内存限制:65535 KB难度:3 描述 There are A, B two sequences, the number of elements in the sequence is n.m; Each element in the sequence are different and less than 100000. Calculate the length

POJ 2533 - Longest Ordered Subsequence(最长上升子序列) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=2533 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK)

最长公共子序列的代码实现

关于最长公共子序列(LCS)的相关知识,http://blog.csdn.net/liufeng_king/article/details/8500084 这篇文章讲的比较好,在此暂时不再详说. 以下是我代码实现两种方式:递归+递推: 1 #include <bits/stdc++.h> 2 using namespace std; 3 int A[100]; 4 int B[100]; 5 6 //int B[]={2,3,5,6,9,8,4}; 7 int d[100][100]={0};

HDU 3998 Sequence (最长递增子序列+最大流SAP,拆点法)经典

Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1666    Accepted Submission(s): 614 Problem Description There is a sequence X (i.e. x[1], x[2], ..., x[n]). We define increasing subsequ

算法面试题 之 最长递增子序列 LIS

找出最长递增序列 O(NlogN)(不一定连续!) 参考 http://www.felix021.com/blog/read.php?1587%E5%8F%AF%E6%98%AF%E8%BF%9E%E6%95%B0%E7%BB%84%E9%83%BD%E6%B2%A1%E7%BB%99%E5%87%BA%E6%9D%A5 我就是理解了一下他的分析 用更通俗易懂的话来说说题目是这样 d[1..9] = 2 1 5 3 6 4 8 9 7 要求找到最长的递增子序列首先用一个数组b[] 依次的将d里面

NYOJ 36 &amp;&amp;HDU 1159 最长公共子序列(经典)

链接:click here 题意:tip:最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列. 输入 第一行给出一个整数N(0<N<100)表示待测数据组数 接下来每组数据两行,分别为待测的两组字符串.每个字符串长度不大于1000. 输出 每组测试数据输出一个整数,表示最长公共子序列长度.每组

poj1159 Palindrome(最长公共子序列)

Palindrome Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 52966   Accepted: 18271 Description A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a

动态规划(4)——最长上升子序列(作业题NYOJ201)

作业题 描述 小白同学这学期有一门课程叫做<数值计算方法>,这是一门有效使用数字计算机求数学问题近似解的方法与过程,以及由相关理论构成的学科-- 今天他们的Teacher S,给他们出了一道作业题.Teacher S给了他们很多的点,让他们利用拉格朗日插值公式,计算出某严格单调函数的曲线.现在小白抄下了这些点,但是问题出现了,由于我们的小白同学上课时走了一下神,他多抄下来很多点,也就是说这些点整体连线不一定还是严格递增或递减的了.这可怎么处理呢.为此我们的小白同学制定了以下的取点规则: 1.取

最长公共子序列(LCS)问题

最长公共子串(Longest Common Substirng)和最长公共子序列(Longest Common Subsequence,LCS)的区别为:子串是串的一个连续的部分,子序列则是从不改变序列的顺序,而从序列中去掉任意的元素而获得新的序列:也就是说,子串中字符的位置必须是连续的,子序列则可以不必连续. 1.序列str1和序列str2 ·长度分别为m和n: ·创建1个二维数组L[m.n]: ·初始化L数组内容为0 ·m和n分别从0开始,m++,n++循环: - 如果str1[m] ==