最长递增子序列

最长递增子序列

  • 解法一:转化为最长公共子序列
  • 解法二:动态规划法
  • 解法三:有序辅助数组

解法一:转化为最长公共子序列

首先将数组排序,最长递增子序列转化为最长公共子序列问题。

  • 设数组 { 3, 9, 7, 1, 5, 8 } 为 A
  • 对数组 A 排序,排序后的数组为 B = { 1, 3, 5, 7, 8, 9 }
  • 于是,求数组 A 的最长递增子序列,就是求数组 A 与数组 B 的最长公共子序列

这个方法时间复杂度为 O ( n 2 ) O(n^2) O(n2)

解法二:动态规划法

解法一中转化问题后使用动态规划,这里不进行转化而直接在原问题上用动态规划。

最优子结构:
对于长度为N的数组 A [ N ] = { a 0 , a 1 , ⋯   , a n } A[N] = \{a_0,a_1,\cdots ,a_n\} A[N]={a0,a1,,an},令 L [ i ] L[i] L[i]为以 a i a_i ai结尾的最长递增子序列,那么有
L [ n ] = max ⁡ 0 ≤ i < n , a i < a n { L [ i ] + 1 } L[n]=\max_{0\le i\lt n,a_iL[n]=0i<n,ai<anmax{L[i]+1}

//得到L[i]
for(i = 0; i < len; i++){
	lis[i] = 1;
	for(j = 0; j < i; j++){
		if(a[i] > a[j] && lis[i] < lis[j] + 1)
			lis[i] = lis[j] + 1;
	}
}

这个方法时间复杂度为 O ( n 2 ) O(n^2) O(n2)

解法三:有序辅助数组

具体操作如下:

  • 建立一个辅助数组 a r r a y array array,依次读取数组元素 x x x与数组末尾元素 t o p top top比较:
    • x > t o p : x\gt top: x>top: x x x放在数组末尾
    • x < t o p : x\lt top: x<top:二分查找数组中第一个大于 x x x的数,并用 x x x替换

结束一遍遍历后, a r r a y array array中元素个数即为最长递增子序列的长度,与前面方法不同的是,方法三并不能得到最长递增子序列,而只能得到他的长度,但是时间复杂度达到了 O ( n log ⁡ n ) O(n\log n) O(nlogn)

算法正确性说明:

  • 首先, a r r a y array array中存放的是有序的元素,因此可以用二分查找
  • 其次,观察可以发现, a r r a y [ i ] array[i] array[i]中的元素的含义是长度为 i + 1 \bm{i+1} i+1的递增子序列的末尾元素的最小值,或者说
    a r r a y [ i ] = min ⁡ { a [ m i ]   ∣   ∃   m 0 < ⋯ < m i , a [ m 0 ] < ⋯ < a [ m i ] } {array[i]=\min_{}\{a[m_i]~|~ \exists ~m_0<\cdots array[i]=min{a[mi]   m0<<mi,a[m0]<<a[mi]}
  • 以上两条性质通过数学归纳法比较容易证明,算法的正确性也就一目了然了

这就是我第一篇博客的全部内容了。

你可能感兴趣的:(最长递增子序列)