https://leetcode.com/problems/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?
方法1 动态规划,复杂度O(n2)
public int LengthOfLIS(int[] nums)
{
int n = nums.Length,res=1;
if (n == 0)
return 0;
int[] dp = new int[n];
for (int i = 0; i < n; i++)
{
dp[i] = 1;
for (int j = 0; j nums[j])
dp[i] = Math.Max(dp[i], dp[j] + 1);
}
res = Math.Max(res, dp[i]);
}
return res;
}
方法2 O(n log n) ,参考 https://segmentfault.com/a/1190000003819886
public class Solution
{
public int LengthOfLIS(int[] nums)
{
int n = nums.Length;
if (n == 0)
return 0;
// len表示当前最长的升序序列长度(为了方便操作tails我们减1)
int len = 0;
// tails[i]表示长度为i的升序序列其末尾的数字
int[] tails = new int[n];
tails[0] = nums[0];
// 根据三种情况更新不同升序序列的集合
for (int i = 1; i < n; i++)
{
if (nums[i] < tails[0])
tails[0] = nums[i];
else if (nums[i] > tails[len])
tails[++len] = nums[i];
else
// 如果在中间,则二分搜索
tails[binarySearch(tails, 0, len, nums[i])] = nums[i];
}
return len + 1;
}
private int binarySearch(int[] tails, int min, int max, int target)
{
while (min <= max)
{
int mid = (max + min) / 2;
if (tails[mid] == target)
return mid;
if (tails[mid] < target)
min = mid + 1;
if (tails[mid] > target)
max = mid - 1;
}
return min;
}
}
方法3
将原数组排序后转化为LCS的问题(LCS算法的C++实现)
public int LengthOfLIS(int[] nums)
{
int n = nums.Length, count = 0;
int[] nums2 = new int[n];
Array.Copy(nums, nums2, n);
Array.Sort(nums2);
int[,] compare = new int[n + 1, n + 1];//记录是否相等
int[,] direction = new int[n, n];//方向数组
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (nums[i] == nums2[j])
{
compare[i + 1, j + 1] = compare[i, j] + 1;
direction[i, j] = 2;
}
else
{
compare[i + 1, j + 1] = Math.Max(compare[i, j + 1], compare[i + 1, j]);
direction[i,j] = compare[i,j+1] >= compare[i+1,j] ? 1 : 0;
}
}
}
int k = n - 1, m = n - 1;
while (k>=0&&m>=0)
{
if (direction[k, m] == 0)
m--;
else if (direction[k, m] == 1)
k--;
else
{
k--;
m--;
count++;
}
}
return count;
}