leetcode 300.最长上升子序列(longest increasing subsequence)C语言

leetcode 300.最长上升子序列(longest increasing subsequence)C语言

1.description

https://leetcode-cn.com/problems/longest-increasing-subsequence/description/

给定一个无序的整数数组,找到其中最长上升子序列的长度。

示例:

输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。

说明:

可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
你算法的时间复杂度应该为 O(n^2) 。

进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?

2.solution

dp的状态定义类似53题,dp[i]表示以nums[i] 结尾的子序列的最大长度

#define MAX(a, b) ((a) > (b) ? (a) : (b))

int lengthOfLIS(int* nums, int numsSize){
    if(numsSize==0) return 0;
    
    int *dp = (int*)malloc(sizeof(int)*numsSize);

    int res = 1;
    for(int i=0; i<numsSize; ++i){
        dp[i] = 1; // dp数组都初始化为可能的最小值1
        for(int j=0; j<i; ++j){ // 每个nums[i]都和它前面的去比较,如果nums[i]大,j对应的dp值加一就是dp[i]的候选值
            if(nums[i] > nums[j]){
                dp[i] = MAX(dp[i], dp[j]+1);
            }
        }
        res = MAX(res, dp[i]); //问题的解是dp数组中的最大值
    }

    free(dp);

    return res;
}

O(NlogN)的二分查找法,原理和思路参考leetcodecn题解

int lengthOfLIS(int* nums, int numsSize){
    if(numsSize == 0) return 0;

    int *arr = (int*)malloc(sizeof(int)*numsSize);
    arr[0] = nums[0];
    int size = 1; // arr中元素个数

    for(int i=1; i<numsSize; ++i){
        int cur = nums[i];
        int low = 0, high = size - 1;
        int index = -1;
        while(low <= high){
            int mid = low + ((high - low)>>1);
            if (arr[mid] >= cur){
                if(mid == 0 || arr[mid-1] < cur){
                    index = mid;
                    break;
                }
                high = mid - 1;
            }else{
                low = mid + 1;
            }
        }
        
        if(index == -1){
            index = size;
            size++;
        }
        arr[index] = cur;
    }

    free(arr);

    return size;
}
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术工厂 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读