【Leetcode】Longest Increasing Subsequence

Longest Increasing Subsequence

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?
Leetcode题目链接

==中科院软件所软工中心2016年保研夏令营考了这道题==
解题的关键的回溯

DP解法
int lengthOfLIS(vector<int>& nums)//返回的是最长増序子序列的长度
{
    int size = nums.size();//解决长度为0时候的特殊情况
    if(!size) return 0;
    int subLens[size];//定义一个子数组用来存放结果序列
    subLens[0] = 1;//
    int maxLen = 1;//最长的长度,就是结果

    for(int i = 1; i < size; ++i)
    {
        subLens[i] = 1;
        for(int j = i-1; j >= 0; --j)
        {
            if(nums[i] > nums[j]) subLens[i] = max(subLens[i], subLens[j]+1);
            maxLen = max(maxLen, subLens[i]);
        }
    }
    return maxLen;
}
以上的解法的复杂度是O(N^2),使用了一个子数组存放前边的所有结果,并通过循环解决这个最优解
BinarySearch解法(leetcode上边找的,好像是错的,但是通过了leetcode的测试,可能是测试用例不太全面)
class Solution {
private:
    int binarySearch(int* nums, int size, int target)
    {
        int l=0, r=size-1;
        while(l < r)
        {
            int m = (l+r)/2;
            if(nums[m] > target) r = m-1;
            else if(nums[m] < target) l = m+1;
            else break;
        }
        if(nums[l] < target) return l+1; //ensure the index is pointed to the position whose element is equal to or bigger than the target;
        else return l;
    }


public:
    //AC - 4ms - using stack to collect the LIS;
    int lengthOfLIS(vector<int>& nums)
    {
        int size = nums.size();
        int top = -1;
        int *arr = (int*)malloc(sizeof(int)*size);//这个辅助数组并不能解决这个子序列问题,会有一种特殊情况导致这个序列变成不是自增的,比如:1,2,3,4,5,6,7,8,9,5;这个序列到了最后的结果变成了:1  5  3  4  5  6  7  8  9,最终这个就不能进行二叉搜索了,这个算法可以通过leetcode的测试,但是不能用
        for(int i = 0; i < size; i++)
        {
            int pos = binarySearch(arr, top+1, nums[i]);
            //情况1:辅助数组中所有的数据都比这个nums[i]小,那么返回的是top+1,top+1记录了最终的结果长度,那么下边执行 if(pos > top) arr[++top] = nums[i];操作,append一个数进去;
            //情况2:找到了和这个数字一模一样的数字,就在这个数组中间,那么执行arr[pos] = nums[i];,这里pos指向的是一个数字,这里就会出现上边说的情况,这样子就不能进行二叉搜索了
            if(pos > top) arr[++top] = nums[i]; //a new element should be appended;;
            else arr[pos] = nums[i]; //make the element pos pointing to smaller;
        }
        return top+1;
    }
};

二叉搜索解法的java解法(复杂度O(NlogN))和上边c++的解法是一样的
public class Solution {
    public int lengthOfLIS(int[] nums) {            
        int[] dp = new int[nums.length];
        int len = 0;

        for(int x : nums) {
            int i = Arrays.binarySearch(dp, 0, len, x);//如果数组a中如果没有key,则返回值为某个负值,表示为了保持排序状态,此目标元素应该插入的位置“-(插入点)-1”;如果找到了key,则返回key所在元素下标。
//插入点是指,第一个大于查找对象的元素在数组中的位置,如果数组所有元素都小于要查找的对象,插入点就等于a.size().

            if(i < 0) i = -(i + 1);
            dp[i] = x;
            if(i == len) len++;
        }

        return len;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值