链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
给你一个长度为n的数组,求最长的严格上升子序列的长度。
输入描述:
第一行一个整数n,表示数组长度。
第二行n个整数,表示数组中的元素。
1 <= n <= 100000
输出描述:
输出一行,表示答案。
输入:
5
1 2 2 2 3
输出:
3
答案:
#include<bits/stdc++.h>
using namespace std;
int dp[100001],a[100001];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
dp[1]=a[1];
int len=1;
for(int i=2;i<=n;i++)
{
if(a[i]>dp[len])
{
dp[++len]=a[i];
}
else
{
int j=lower_bound(dp+1,dp+1+len,a[i])-&dp[0];
dp[j]=a[i];
}
}
cout<<len;
}
描述:
这里用的动态规划的方法
其中
lower_bound(dp+1, dp+1+len, a[i])
:- 这部分代码调用了
lower_bound
函数,该函数在已排序的范围内查找第一个不小于给定值(这里是a[i]
)的元素。 dp+1
和dp+1+len
定义了查找的范围,即从dp
数组的第二个元素开始(如果dp
的索引从0开始,那么这实际上是跳过了第一个元素),到dp
数组的末尾(包括末尾)。a[i]
是我们要在dp
数组中查找或定位的值。
- 这部分代码调用了
-&dp[0]
:lower_bound
返回的是一个迭代器,指向第一个不小于a[i]
的元素。由于dp
是一个数组,我们可以将其迭代器视为指向数组元素的指针。-&dp[0]
实际上是在进行一个反向操作,将迭代器(或指针)转换回相对于dp
数组起始位置的索引。但是,这里的使用方式是不正确的,因为lower_bound
返回的迭代器(或指针)已经是相对于dp+1
的,所以我们不需要再减去&dp[0]
。正确的做法是直接使用lower_bound
返回的迭代器与dp
的起始迭代器(或指针)之差来得到索引。然而,由于dp
是数组,我们可以直接通过指针运算得到索引,即iterator - (dp + 1)
。- 正确的索引计算应该是
(lower_bound(dp+1, dp+1+len, a[i]) - (dp + 1))
,这将给出a[i]
应该插入的dp
数组的索引(从1开始计数,如果这是你的逻辑)。但是,如果dp
是从0开始使用的,你应该调整这个计算以反映这一点。
dp[j]=a[i];
:- 这行代码将
a[i]
的值赋给dp
数组中通过前面计算得到的索引j
所指向的位置。 - 需要注意的是,如果
j
的计算是基于从1开始的逻辑索引,并且dp
实际上是从0开始的数组,你可能需要调整j
的值(例如,通过j-1
)来正确赋值。
- 这行代码将
拓展:
upper_bound()
函数是 C++ 标准库中的一个算法,它用于在已排序的范围内查找第一个大于给定值的元素。这个函数定义在 <algorithm>
头文件中,并且通常与容器(如 std::vector
)或数组一起使用。
upper_bound()
函数的原型如下:
template< class ForwardIt, class T >
ForwardIt upper_bound( ForwardIt first, ForwardIt last, const T& value );
first
和last
是前向迭代器,分别指向要搜索的范围的起始和结束位置(注意,last
是不包含在内的)。value
是要比较的值。- 函数返回一个迭代器,指向第一个大于
value
的元素,如果所有元素都不大于value
,则返回last
。
与 lower_bound()
类似,upper_bound()
也要求给定的范围 [first, last)
是已排序的。如果范围未排序,则结果将是未定义的。
使用示例
假设我们有一个已排序的整数数组,并希望找到第一个大于给定值的元素的索引:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 4, 4, 5, 6, 9};
int value = 4;
// 使用 upper_bound 查找第一个大于 value 的元素
auto it = std::upper_bound(vec.begin(), vec.end(), value);
// 如果迭代器不是 vec.end(),则输出找到的元素的索引(注意,这里索引是从 0 开始的)
if (it != vec.end()) {
std::cout << "第一个大于 " << value << " 的元素的索引是: " << (it - vec.begin()) << std::endl;
std::cout << "该元素的值是: " << *it << std::endl;
} else {
std::cout << "没有大于 " << value << " 的元素" << std::endl;
}
return 0;
}