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