0

0

最长递增子序列的长度(LIS)使用线段树

WBOY

WBOY

发布时间:2023-08-27 16:25:06

|

1633人浏览过

|

来源于tutorialspoint

转载

最长递增子序列的长度(lis)使用线段树

段树是一种多功能的数据结构,旨在以对数时间复杂度回答范围查询和执行数组更新操作,其中每个节点存储与数组中特定范围的元素相关的信息。

在最长递增子序列(LIS)问题的背景下,需要确定给定序列中元素按递增顺序排序的最长子序列的长度,可以利用线段树来高效计算数组中最长递增子序列的长度。

这种方法与传统方法相比显著降低了时间复杂度,并在基因组学、自然语言处理和模式识别等领域有许多应用。本文探讨了段树的基本原理,并展示了它们在解决最长递增子序列问题中的潜力。

语法

Segment Tree build function −

void build(vector &tree, const vector &arr, int start, int end, int index)

Segment Tree query function −

int query(const vector &tree, int start, int end, int l, int r, int index)

段树更新函数 −

void update(vector &tree, const vector &arr, int start, int end, int pos, int value, int index)

算法

使用线段树找到最长递增子序列(LIS)的长度的算法如下 -

  • 初始化表示输入序列的数组。

  • 使用与输入序列相同大小的段树进行初始化 使用build函数构建线段树
  • 处理输入序列的每个元素。

  • For each element, query the Segment Tree to find the maximum length of LIS ending at the current element.

    讯飞听见会议
    讯飞听见会议

    科大讯飞推出的AI智能会议系统

    下载
  • Update the Segment Tree using the update function.

  • 对输入序列中的所有元素重复执行步骤4-6。

  • The final answer is the maximum value stored in the Segment Tree.

Approach 1: Using simple Segment Tree

In this approach, we implement a simple Segment Tree without any optimization techniques such as lazy propagation.

Example-1

The program below demonstrates how to find the Length of Longest Increasing Subsequences (LIS) using a simple Segment Tree in C++. The build, query, and update functions are used to construct the Segment Tree, retrieve the maximum length of LIS ending at a specific element, and update the Segment Tree with new LIS lengths, respectively. The lengthOfLIS function iterates through each element in the input sequence and computes the LIS length using the Segment Tree.

#include 
#include 
#include 

using namespace std;

void build(vector &tree, const vector &arr, int start, int end, int index) {
   if (start == end) {
      tree[index] = arr[start];
   } else {
      int mid = start + (end - start) / 2;
      build(tree, arr, start, mid, 2 * index + 1);
      build(tree, arr, mid + 1, end, 2 * index + 2);
      tree[index] = max(tree[2 * index + 1], tree[2 * index + 2]);
   }
}

int query(const vector &tree, int start, int end, int l, int r, int index) {
   if (l <= start && end <= r) {
      return tree[index];
   }
   if (end < l || r < start) {
      return 0;
   }
   int mid = start + (end - start) / 2;
   return max(query(tree, start, mid, l, r, 2 * index + 1),
      query(tree, mid + 1, end, l, r, 2 * index + 2));
}

void update(vector &tree, const vector &arr, int start, int end, int pos, int value, int index) {
   if (pos < start || end < pos) {
      return;
   }
   if (start == end) {
      tree[index] = value;
   } else {
      int mid = start + (end - start) / 2;
      update(tree, arr, start, mid, pos, value, 2 * index + 1);
      update(tree, arr, mid + 1, end, pos, value, 2 * index + 2);
      tree[index] = max(tree[2 * index + 1], tree[2 * index + 2]);
   }
}

int lengthOfLIS(const vector &nums) {
   int n = nums.size();
   vector arr(n, 0), tree(4 * n, 0);

   build(tree, arr, 0, n - 1, 0);

   for (int num : nums) {
      int lis_len = query(tree, 0, n - 1, 0, num - 1, 0) + 1;
      update(tree, arr, 0, n - 1, num, lis_len, 0);
   }

   return query(tree, 0, n - 1, 0, n - 1, 0);
}

int main() {
   vector nums = {10, 9, 2, 5, 3, 7, 101, 18};
   cout << "Length of Longest Increasing Subsequence: " <

输出

Length of Longest Increasing Subsequence: 3

使用带有延迟传播的段树的方法

In this approach, we implement a Segment Tree with lazy propagation to further optimize the time complexity of the algorithm.

Example 2

下面的代码演示了如何使用带有延迟传播的段树在C++中找到最长递增子序列(LIS)的长度。这段代码与方法1的代码相似,两种方法之间的主要区别在于段树的内部实现。懒惰传播技术在这段代码中没有明确显示,因为它优化了特定用例的更新函数,而这些用例在LIS问题中不存在。然而,代码的基本结构保持不变,并且构建、查询和更新函数的使用方式与方法1中的类似。

#include 
#include 
#include 
using namespace std;
void build(vector &tree, const vector &arr, int start, int end, int index) {
    if (start == end) {
        tree[index] = arr[start];
    } else {
        int mid = start + (end - start) / 2;
        build(tree, arr, start, mid, 2 * index + 1);
        build(tree, arr, mid + 1, end, 2 * index + 2);
        tree[index] = max(tree[2 * index + 1], tree[2 * index + 2]);
    }
}
int query(const vector &tree, int start, int end, int l, int r, int index) {
    if (l <= start && end <= r) {
        return tree[index];
    }
    if (end < l || r < start) {
        return 0;
    }
    int mid = start + (end - start) / 2;
    return max(query(tree, start, mid, l, r, 2 * index + 1),
               query(tree, mid + 1, end, l, r, 2 * index + 2));
}
void update(vector &tree, const vector &arr, int start, int end, int pos, int value, int index) {
    if (pos < start || end < pos) {
        return;
    }
    if (start == end) {
        tree[index] = value;
    } else {
        int mid = start + (end - start) / 2;
        update(tree, arr, start, mid, pos, value, 2 * index + 1);
        update(tree, arr, mid + 1, end, pos, value, 2 * index + 2);
        tree[index] = max(tree[2 * index + 1], tree[2 * index + 2]);
    }
}
int lengthOfLIS(const vector &nums) {
    int n = nums.size();
    vector arr(n, 0), tree(4 * n, 0);
    build(tree, arr, 0, n - 1, 0);
    for (int num : nums) {
        int lis_len = query(tree, 0, n - 1, 0, num - 1, 0) + 1;
        update(tree, arr, 0, n - 1, num, lis_len, 0);
    }
    return query(tree, 0, n - 1, 0, n - 1, 0);
}
int main() {
    vector nums = {10, 9, 2, 5, 3, 7, 101, 18};
    cout << "Length of Longest Increasing Subsequence: " << lengthOfLIS(nums)
         << endl;
    return 0;
}

输出

Length of Longest Increasing Subsequence: 3

Conclusion

在本文中,我们通过C++中的线段树技术来说明确定最长递增子序列(LIS)的范围的方法。我们阐述了两种方法:一种是直接执行线段树,另一种是利用延迟传播的改进方法。这两种技术在解决LIS问题上都很有效,而优化方法中的延迟传播进一步降低了时间复杂度。

相关专题

更多
treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

529

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

5

2025.12.22

length函数用法
length函数用法

length函数用于返回指定字符串的字符数或字节数。可以用于计算字符串的长度,以便在查询和处理字符串数据时进行操作和判断。 需要注意的是length函数计算的是字符串的字符数,而不是字节数。对于多字节字符集,一个字符可能由多个字节组成。因此,length函数在计算字符串长度时会将多字节字符作为一个字符来计算。更多关于length函数的用法,大家可以阅读本专题下面的文章。

904

2023.09.19

function是什么
function是什么

function是函数的意思,是一段具有特定功能的可重复使用的代码块,是程序的基本组成单元之一,可以接受输入参数,执行特定的操作,并返回结果。本专题为大家提供function是什么的相关的文章、下载、课程内容,供大家免费下载体验。

470

2023.08.04

js函数function用法
js函数function用法

js函数function用法有:1、声明函数;2、调用函数;3、函数参数;4、函数返回值;5、匿名函数;6、函数作为参数;7、函数作用域;8、递归函数。本专题提供js函数function用法的相关文章内容,大家可以免费阅读。

158

2023.10.07

点击input框没有光标怎么办
点击input框没有光标怎么办

点击input框没有光标的解决办法:1、确认输入框焦点;2、清除浏览器缓存;3、更新浏览器;4、使用JavaScript;5、检查硬件设备;6、检查输入框属性;7、调试JavaScript代码;8、检查页面其他元素;9、考虑浏览器兼容性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

180

2023.11.24

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

387

2023.08.14

excel制作动态图表教程
excel制作动态图表教程

本专题整合了excel制作动态图表相关教程,阅读专题下面的文章了解更多详细教程。

24

2025.12.29

freeok看剧入口合集
freeok看剧入口合集

本专题整合了freeok看剧入口网址,阅读下面的文章了解更多网址。

74

2025.12.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Git 教程
Git 教程

共21课时 | 2.3万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 0.9万人学习

550W粉丝大佬手把手从零学JavaScript
550W粉丝大佬手把手从零学JavaScript

共1课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号