本题使用回溯法,深度优先搜索。使用隐式条件来进行加速。

public class Solution
    {
        int bestp = 0;
        int[] x;
        Dictionary<int, int> dic = new Dictionary<int, int>();

        void Backtrack(int[] nums, int t)
        {
            if (t >= nums.Length)
            {
                var sum = 0;
                for (int i = 0; i < nums.Length; i++)
                {
                    if (x[i] == 1)
                    {
                        //Console.Write(nums[i]+"   ");
                        sum++;
                    }                    
                }
                //Console.WriteLine();
                bestp = Math.Max(bestp, sum);
                return;
            }

            if (dic.Count == 0 || dic.LastOrDefault().Value < nums[t])
            {
                x[t] = 1;
                dic.Add(t, nums[t]);
                Backtrack(nums, t + 1);
                dic.Remove(t);
            }
            if (dic.Count + nums.Length - (t + 1) > bestp)
            {
                x[t] = 0;
                Backtrack(nums, t + 1);
            }
        }

        public int LengthOfLIS(int[] nums)
        {
            if (nums.Length < 2)
            {
                return nums.Length;
            }
            
            x = new int[nums.Length];
            Backtrack(nums, 0);

            return bestp;
        }
    }

 补充一个使用动态规划的方法,使用python实现,但是效率不是很高:

 1 class Solution:
 2     def lengthOfLIS(self, nums: 'List[int]') -> 'int':
 3         n = len(nums)
 4         if n==0:
 5             return 0
 6         maxnum = 0
 7         dp = [1] * n
 8         for i in range(n):
 9             for j in range(i):
10                 if nums[i] > nums[j]:
11                     dp[i] = max(dp[i],dp[j] + 1)
12                     print(dp[i])
13             maxnum = max(maxnum,dp[i])
14         return maxnum

思路分析:双层循环,时间复杂度是O(n^2)。

dp[i]表示在nums中,以nums[i]为结尾的自增子序列的长度。

第13行是在外层循环,每次循环结束的时候更新,全局的最长自增子序列的长度,也就是所求。

内层循环,是从当前位置i,向前寻找[0,i-1]闭区间。如果在nums中,i前面有一个元素j,满足nums[i] > nums[j],则可以在以j为结尾的自增子序列上,增加1的长度,构成新的自增子序列,而dp[i]只保存这些可能构成的新自增子序列中最大的长度。 

 

补充一个java的实现,使用二分查找加速查询,提升效率

 1 class Solution {
 2         public int lengthOfLIS(int[] nums) {
 3             int n = nums.length;
 4             int[] tails = new int[n];
 5             int len = 0;
 6             for (int num : nums) {
 7                 int index = binarySearch(tails, len, num);
 8                 tails[index] = num;
 9                 if (index == len) {
10                     len++;
11                 }
12             }
13             return len;
14         }
15 
16         private int binarySearch(int[] tails, int len, int key) {
17             int l = 0, h = len;
18             while (l < h) {
19                 int mid = l + (h - l) / 2;
20                 if (tails[mid] == key) {
21                     return mid;
22                 } else if (tails[mid] > key) {
23                     h = mid;
24                 } else {
25                     l = mid + 1;
26                 }
27             }
28             return l;
29         }
30     }

posted on 2018-10-04 19:49  Sempron2800+  阅读(183)  评论(0编辑  收藏  举报