刷leetcode198题时,遇到动态规划的问题,重新预习加复习了一次动态规划的相关知识。
动态规划(Dynamic Programming):
- 基于一个递推公式及一个或多个初始状态
- 当前子问题的解由上一次子问题的解推出
- 找到状态之间的转移方式,即转到状态转移方程。(这一点特别重要)
最常见的例子:LIS(Longest Increasing Subsequence)
设d(i):表示前i个数中的以A[i]结尾的最长非降子序列的长度
d(i = max{ 1, d(j)+1 }, 其中j < i,A[J] <= A[i]
找到递推关系式后根据关系式写出代码。
public class LIS{
public int lis(int [] a){
int leng = a.length;
int [] b = new int[leng];
int len = 1;
for(int i = 0; i < leng; i++){
b[i] = 1;
for(int j = 0; j < i; j++){
if( (a[i] > a[j]) && (b[i] < (b[j] + 1)))
b[i] = b[j] +1;
}
if(len < b[i]) len = b[i];
}
return len;
}
public static void main(String [] args){
LIS li = new LIS();
int [] a = {4,5,1,2,3,7,8,9};
System.out.print("The longest increasing subsequence length is " + li.lis(a));
}
}
上述算法的复杂度为O(n^2),可化简至O(nlgn)
public class LIS{
public int find_position(int [] arr, int s, int e, int key){
int mid;
if(arr[e] < key) return e+1;
while(s < e){
mid = s +(e-s)/2;
if(arr[mid] <= key)
s = mid + 1;
else e =mid;
}
return s;
}
public int lis(int [] d){
int i = 0, len =1;
int n = d.length;
int [] end = new int [n];
end[1] = d[0];
for(i = 1; i< n; i++){
int pos = find_position(end, 1, len, d[i]);
end[pos] = d[i];
if(pos > len) len = pos;
}
return len;
}
public static void main(String [] args){
LIS list1 = new LIS();
int [] a = {2,1,5,3,6,4,8,9,7};
int len = list1.lis(a);
System.out.println("The longest increasing subsequence' s length is " + len);
}
}