基于贪心算法和二分搜索编写计算最长上升子序列方法的代码
时间: 2023-06-19 15:09:39 浏览: 54
以下是基于贪心算法和二分搜索的计算最长上升子序列的 Python3 代码:
```python
def lengthOfLIS(nums):
tails = [0] * len(nums)
size = 0
for x in nums:
i, j = 0, size
while i != j:
m = (i + j) // 2
if tails[m] < x:
i = m + 1
else:
j = m
tails[i] = x
size = max(i + 1, size)
return size
```
其中,`tails` 数组用于存储长度为 `i+1` 的上升子序列的末尾元素的最小值,`size` 记录当前最长上升子序列的长度。
我们遍历数组 `nums`,对于每个元素 `x`,在 `tails` 数组中查找第一个大于等于 `x` 的元素,使用二分搜索实现。如果找到了这样的元素,将其替换为 `x`,如果没有找到,将 `x` 加入到 `tails` 数组的末尾,此时最长上升子序列的长度加一。
最终返回 `size` 即可。
相关问题
基于贪心算法和二分搜索编写计算最长上升子序列方法的C语言代码
以下是基于贪心算法和二分搜索的C语言代码实现:
```c
#include <stdio.h>
//计算最长上升子序列的长度
int LIS(int arr[], int n) {
int len = 1; //当前最长上升子序列的长度
int tail[n]; //tail[i]存储长度为i+1的子序列的最后一个元素的值
tail[0] = arr[0];
for (int i = 1; i < n; i++) {
if (arr[i] > tail[len-1]) {
tail[len] = arr[i];
len++;
} else {
int l = 0, r = len-1;
while (l < r) {
int mid = (l + r) / 2;
if (tail[mid] < arr[i]) {
l = mid + 1;
} else {
r = mid;
}
}
tail[l] = arr[i];
}
}
return len;
}
int main() {
int arr[] = {10, 9, 2, 5, 3, 7, 101, 18};
int n = sizeof(arr) / sizeof(arr[0]);
printf("Length of LIS is %d\n", LIS(arr, n));
return 0;
}
```
该代码中,我们使用了tail数组来存储长度为i+1的子序列的最后一个元素的值。在遍历数组arr时,我们首先判断arr[i]是否大于tail[len-1],如果是,则将arr[i]加入到tail数组尾部,并将最长上升子序列长度len加1。如果arr[i]小于等于tail[len-1],则使用二分搜索在tail数组中寻找第一个大于等于arr[i]的元素,并将其替换为arr[i]。
在遍历完整个数组后,tail数组中存储的即为最长上升子序列的末尾元素。其长度即为最长上升子序列的长度。
基于贪心算法和二分搜索编写计算最长上升子序列的理解
计算最长上升子序列(Longest Increasing Subsequence,简称LIS)是一个经典的问题,可以用贪心算法和二分搜索来解决。
贪心算法的思想是,每次选择当前最优的解决方案,希望最终能够得到全局最优解。对于LIS问题,我们可以使用一个数组d来记录当前LIS的长度和最后一个元素的值。我们从左到右遍历数组,对于每个元素,我们可以将其插入到d数组中,有以下两种情况:
1.如果当前元素比d数组中最后一个元素还要大,我们可以直接将当前元素插入到d数组的末尾,并将LIS长度加1。
2.如果当前元素比d数组中最后一个元素小,我们可以使用二分搜索在d数组中找到第一个大于等于当前元素的位置,将该位置的值替换为当前元素。这样做的原因是,如果我们将d数组中的某个位置i替换为当前元素,那么以i结尾的LIS长度就会变成以当前元素结尾的LIS长度,而且这个新的LIS长度比原来的LIS长度更有可能变得更长。
最终,d数组的长度就是LIS的长度。
总的来说,贪心算法和二分搜索的结合能够高效地解决LIS问题,时间复杂度为O(nlogn)。