目录
语法
算法
Approach 1: Using simple Segment Tree
Example 2
输出
使用带有延迟传播的段树的方法
Conclusion
首页 后端开发 C++ 最长递增子序列的长度(LIS)使用线段树

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

Aug 27, 2023 pm 04:25 PM
长度 最长递增子序列 线段树

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

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

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

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

语法

Segment Tree build function −

void build(vector<int> &tree, const vector<int> &arr, int start, int end, int index)
</int>
登录后复制

Segment Tree query function −

int query(const vector<int> &tree, int start, int end, int l, int r, int index)
登录后复制

段树更新函数 −

void update(vector<int> &tree, const vector<int> &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.

  • 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 <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void build(vector<int> &tree, const vector<int> &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<int> &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<int> &tree, const vector<int> &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<int> &nums) {
   int n = nums.size();
   vector<int> 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<int> 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
登录后复制
登录后复制

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

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中的类似。

<int>#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void build(vector<int> &tree, const vector<int> &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<int> &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<int> &tree, const vector<int> &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<int> &nums) {
    int n = nums.size();
    vector<int> 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<int> nums = {10, 9, 2, 5, 3, 7, 101, 18};
    cout << "Length of Longest Increasing Subsequence: " << lengthOfLIS(nums)
         << endl;
    return 0;
}
</int>
登录后复制

输出

Length of Longest Increasing Subsequence: 3
登录后复制
登录后复制

Conclusion

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

以上是最长递增子序列的长度(LIS)使用线段树的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

PHP数组长度限制是多少? PHP数组长度限制是多少? Mar 13, 2024 pm 06:30 PM

PHP中数组的长度并没有固定的限制,它可以根据系统的内存大小来动态调整。在PHP中,数组是一种非常灵活的数据结构,可以存储任意数量的元素,每个元素可以是任意类型的值,甚至可以是另一个数组。PHP数组的长度限制主要取决于系统的内存大小和PHP配置的内存限制。一般来说,如果系统的内存足够大,并且PHP的内存限制足够高,数组的长度可以很大。但是,如果系统内存不足或

PHP数组长度是否受限制? PHP数组长度是否受限制? Mar 13, 2024 pm 06:36 PM

PHP数组长度是否受限制?需要具体代码示例在PHP中,数组长度并不受到固定的限制,可以根据系统内存的实际限制来动态调整数组大小。PHP中的数组是一种动态数组,因此可以根据需要动态增长或缩小。在PHP中,数组是一种有序映射的数据结构,可以用数组下标或关联数组的键值来访问数组元素。下面我们来看具体的代码示例来演示PHP数组长度是否受限制。首先,我们可以通过以下代

给定一个数组,求两个字符串长度之和的最大值,这两个字符串没有相同的字符 给定一个数组,求两个字符串长度之和的最大值,这两个字符串没有相同的字符 Aug 29, 2023 pm 06:45 PM

本文的目的是实现一个程序,以最大化给定数组中没有公共字符的一对字符串的长度总和。根据定义,字符串是字符的集合。问题陈述实现一个程序,以最大化给定数组中没有公共字符的一对字符串的长度总和。示例1LetusconsidertheInputarray:a[]=[“efgh”,“hat”,“fto”,“car”,“wxyz”,“fan”]Outputobtained:8说明字符串“abcd”和“wxyz”中没有共同字符。结果,两个字符串相加的长度为4+4,等于8,是所有可行对中最长的长度。示例2Letu

如何使用C++中的最长递增子序列算法 如何使用C++中的最长递增子序列算法 Sep 19, 2023 pm 05:21 PM

如何使用C++中的最长递增子序列算法,需要具体代码示例最长递增子序列(LongestIncreasingSubsequence,简称LIS)是一个经典的算法问题,其解决思路可以应用于多个领域,如数据处理、图论等。在本文中,我将为大家介绍如何使用C++中的最长递增子序列算法,并提供具体的代码示例。首先,我们来了解一下最长递增子序列的定义。给定一个序列a1,

解析len函数的用途和重要性的多个视角 解析len函数的用途和重要性的多个视角 Dec 28, 2023 am 08:38 AM

len函数的作用与意义从不同角度解读len函数是Python编程语言中常用的函数之一。它主要用于返回一个容器对象(例如字符串、列表、元组等)的长度或元素个数。这个简单的函数在编写程序时起着非常重要的作用,有着多个角度可以解读其作用与意义。本文将从性能、可读性和容器类型的角度对len函数进行解读,并提供具体的代码示例。一、性能角度在处理大规模数据时,程序的性能

golang中如何验证输入文本的长度 golang中如何验证输入文本的长度 Jun 24, 2023 am 11:52 AM

在golang中,验证输入文本的长度是一个常见的需求。通过验证,我们可以确保输入的文本符合特定的要求,并且长度在我们期望的范围内。在本文中,我们会探讨如何使用golang验证输入文本的长度。首先,我们需要了解一下golang中常用的字符串函数。其中,len()函数用于计算字符串的长度。例如,以下代码可以计算字符串"helloworld"的长度:str:=

如何在Java中找到斜边的长度? 如何在Java中找到斜边的长度? Sep 09, 2023 pm 10:33 PM

斜边是指直角三角形中与直角相对的最长边。可以使用毕达哥拉斯定理找到斜边的长度。根据毕达哥拉斯定理,两条边长度的平方和等于第三条边长度的平方,即a2+b2=c2其中,a、b、c表示直角三角形的三条边。So,Hypotenuse=Math.sqrt(Math.pow(base,2)+Math.pow(height,2))在本文中,我们将看到如何使用Java编程语言找到斜边的长度。展示给你一些实例Instance-1的中文翻译为:实例-1假设底长和高分别为3和4。然后通过使用勾股定理公式,Length

包含恰好X个元音字母的长度为K的子串的数量 包含恰好X个元音字母的长度为K的子串的数量 Sep 01, 2023 am 08:57 AM

在这个问题中,我们需要找到长度为K且正好包含K个元音的子串的总数。我们将看到解决问题的两种不同方法。我们可以使用一种简单的方法来检查每个长度为K的子串中元音的数量。此外,我们可以使用滑动窗口方法来解决该问题。问题陈述——我们给出了一个长度为N的字符串str,包含小写和大写字母字符。我们需要统计长度为K且正好包含X个元音的子串的总数。示例输入–str="TutorialsPoint",K=3,X=2输出–6解释–长度为3且恰好包含2个元音的子串是:'uto'、'ori'、'ri

See all articles