LeetCode 300.Longest Increasing Subsequence 在一维数组中找最长序列(好题)

来源:互联网 发布:阿里云香港服务器能放 编辑:程序博客网 时间:2024/05/29 12:39

题目

Given an unsorted array of integers, find the length of longest increasing subsequence.

For example,
Given [10, 9, 2, 5, 3, 7, 101, 18],
The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more than one LIS combination, it is only necessary for you to return the length.

Your algorithm should run in O(n2) complexity.

Follow up: Could you improve it to O(n log n) time complexity?

首先是O(n2)的方法,利于动态规划

模拟过程如下:

 input[]: 10 92 5 3 7 10118

store[]: 1 1 1 2 23 4 4

public int lengthOfLIS(int[] nums) {if(nums==null || nums.length==0)return 0;int len = nums.length;int[] store = new int[len];for(int i=0;i<len;i++){store[i] = 1;for(int j = 0; j < i ;j++){if(nums[j]<nums[i]){store[i] = Math.max(store[i], store[j]+1);}}}int result = 1;for(int i=0;i<store.length;i++)result = Math.max(result, store[i]);return result;}

接下来扩展一下,把最长序列输出出来(可能多种,我只输出一个),思路是设定一个阈值(max=1),只要store[]中超过阈值的项写入列表List中,更新max,最后将max=1且比List[0]小的插入至List[0],长度加一,代码如下;
public List OutputOfLIS(int[] nums) {int max = 1;  //判断当前最大;List<Integer> result_list = new ArrayList<Integer>();if(nums==null || nums.length==0)return null;int len = nums.length;int[] store = new int[len];for(int i=0;i<len;i++){store[i] = 1;for(int j = 0; j < i ;j++){if(nums[j]<nums[i]){if(store[i]<store[j]+1&&store[j]+1>max){max = store[j]+1;store[i] = store[j]+1;if(!result_list.contains(nums[i]))result_list.add(nums[i]);}}}}if(result_list.size()>0){//把第一个补全for(int i=0;i<len;i++){if(nums[i]<result_list.get(0)){result_list.add(0, nums[i]);return result_list;}}}else return result_list;return result_list;}}

其次是O(nlogn)的方法,用的是栈和折半查找

思路部分参考http://blog.csdn.net/yorkcai/article/details/8651895
  开一个栈,将nums[0]入栈,每次取栈顶元素top和读到的元素nums[i](1<i<n)做比较,如果nums[i]> top 则将nums[i]入栈;如果nums[i]<= top则二分查找栈中的比nums[i]大的第1个数,并用nums[i]替换它。 最长序列长度即为栈的大小top。
 input[]: 109253710118
栈的构造过程
10
9  
2  
2  5  
2  3  
2  3  7  
2  3  7  101  
2  3  7  18  
代码如下
public int lengthOfLIS(int[] nums) {if(nums==null||nums.length==0)return 0;int[] stack = new int[nums.length];   //模拟一个栈 result代表栈的深度stack[0] = nums[0];for(int i=1;i<nums.length;i++)stack[i] = Integer.MAX_VALUE;    //赋值成为nums[0],MAX_VALUE,MAX_VALUE......int result = 0;for(int i=1;i<nums.length;i++){if(nums[i]>stack[result]){//当前元素比栈顶还大result ++;stack[result] = nums[i];//System.out.print("!!!:"+result+","+"     ");}else if(nums[i]<stack[result]){int mid = Arrays.binarySearch(stack, 0, result+1, nums[i]);//System.out.print("!!!:"+result+","+mid+"   ");if(mid<0)stack[-mid -1] = nums[i];}//for(int s=0;s<=result;s++)//System.out.print(stack[s]+"  ");//System.out.println();}return result+1; 
值得注意的,O(nlogn)
 input[]: 10925371016
栈的构造过程
10
9  
2  
2  5  
2  3  
2  3  7  
2  3  7  101  
2  3  6  101   //这一次替换了最长序列,与预期最长序列不同,但是长度却相同
分析:
当nums[i]>top时,top+1,与预期相同;
当nums[i]<top时, 这时num[i]会替换栈里面的某一个元素,top大小不变,但是序列发生了变化;
如果只求个数的话,这个算法比较高效;但如果要求打印出序列时,就只能用动态规划的方法。

1 0