编程之美2.16 最长递增子序列:

写一个时间复杂度尽可能低的程序,求一个一维数组(N个元素)中的最长递增子序列的长度。例如:在序列1,-1,2,-3,4,-5,6-7中,其最长的递增子序列为1,2,4,6

分析:利用动态规划分析。用A[i]来更新maxLen和MaxV:,从A[0]~A[i-1]可能存在多个存在多个子问题的最优解,所以需要将他他们合并为一个。

1. 当A[i]>MaxV[maxLen](即子问题最优解的最小值)时,maxLen++ && MaxV[maxLen] = a[i]

  A[i]>MaxV[maxLen]时,A[i]必然比MaxV[0]-MaxV[maxLen]中所有的值都大,因此,比如不会更新这些已有的长度的尾部最小值
2. 当A[j]<A[i]<A[j+1]时,即存在一个更小的局部问题最优解,所以需要更新这个最优解。更新长度为j+1的记录,即:MaxV[j+1] =A[i]

   1).对于MaxV[0]-MaxV[j]的不用说了,A[i]比他们都大,他们都不会更新了,

   2).对于MaxV[j+1],刚好可以更新其值为A[i],

   3).对于MaxV[j+2]-MaxV[MaxLen]的元素由于递增子序列的后无效性,也不需要更新。对于长度相同的最长递增子序列, 我们可以将他们分到同一组中(合并为一组),并只记录它们最大元素的最小值MaxV[长度值], 如: (1,3, 4, 6) 和(-4, -2, -1, 8), 可以合并为(-4, -2, -1,6)

就是这样了,分析好对于每个A[i],如何更新maxLen和MaxV就ok了。

        // 用二分法查找是否存在 MaxV[k]<array[i]<MaxV[k+1]
        public static int BinarySearch(int[] array, int maxLength, int target)
        {   
            int left = 0;
            int right = maxLength - 1;
            int middle = 0;

            while (left <= right)
            {
                middle = (left + right) / 2;

                if (array[middle] == target)
                {
                    return middle;
                }
                else if (array[middle] < target)
                {
                    left = middle + 1;
                }
                else
                {
                    right = middle - 1;
                }
            }

            return array[middle] > target ? middle : middle + 1;
        }

        // 编程之美2.16 最长递增子序列  
        public static int GetMaxLength(int[] array)
        {
            int maxLen = 1;
            int[] MaxV = new int[array.Length];
            MaxV[0] = array[0];

            for (int i = 1; i < array.Length; i++)
            {
                if (array[i] > MaxV[maxLen - 1])
                {
                    maxLen++;
                    MaxV[maxLen-1] = array[i];
                }
                else  //if last_min[k]<array[i]<last_min[k+1]
                {
                    int pos = BinarySearch(MaxV,maxLen, array[i]);

                    if (pos >= 0) //存在 MaxV[k]<array[i]<MaxV[k+1],更新 MaxV[k+1]
                    {
                        MaxV[pos] = array[i];
                    }
                }
            }

            return maxLen;
        }

 

 

posted on 2013-12-19 16:49  higirle  阅读(399)  评论(0编辑  收藏  举报