C++ 从左到右遍历数组,收集尽可能多的数字
CSES问题() 您将获得一个数组,该数组包含1到n之间的每个数字,且只包含一次。您的任务是按递增顺序收集从1到n的数字。 在每一轮中,从左到右遍历数组并收集尽可能多的数字。总共有多少轮? 限制条件:1≤N≤2.⋅10^5 这是我在c++上的代码:C++ 从左到右遍历数组,收集尽可能多的数字,c++,algorithm,sorting,sequence,C++,Algorithm,Sorting,Sequence,CSES问题() 您将获得一个数组,该数组包含1到n之间的每个数字,且只包含一次。您的任务是按递增顺序收集从1到n的数字。 在每一轮中,从左到右遍历数组并收集尽可能多的数字。总共有多少轮? 限制条件:1≤N≤2.⋅10^5 这是我在c++上的代码: int n, res=0; cin>>n; int arr[n]; set <int, greater <int>> lastEl; for(int i=0; i<n; i++) { cin>&
int n, res=0;
cin>>n;
int arr[n];
set <int, greater <int>> lastEl;
for(int i=0; i<n; i++) {
cin>>arr[i];
auto it=lastEl.lower_bound(arr[i]);
if(it==lastEl.end()) res++;
else lastEl.erase(*it);
lastEl.insert(arr[i]);
}
cout<<res;
int n,res=0;
cin>>n;
int-arr[n];
拉斯泰尔;
对于(int i=0;i>arr[i];
auto it=lastEl.下限(arr[i]);
如果(it==lastEl.end())res++;
else lastEl.擦除(*它);
最后插入(arr[i]);
}
让我详细地解释一下我的思考过程,这样下次当你面对同样的问题时,你会更容易
首先,我在面对这类问题时经常犯的一个错误是急于模拟过程。我所说的“模拟过程”是什么意思在问题陈述中提到?问题提到一个回合是为了最大限度地收集按一定顺序递增的数字。因此,您从1
开始,找到它,并看到下一个数字2
不在它之外,即2
不能与1
处于同一轮,并形成递增se顺序。因此,我们需要对2
进行另一轮。现在我们发现,2
和3
都可以在同一轮中收集,因为我们从左向右移动并以递增的顺序取数。但是我们不能取4
,因为它在2
之前开始。最后,对于4
和5
我们还需要一轮,总共三轮
现在,如果您以这种方式模拟该过程,问题变得非常容易解决。在第一轮中,您将查找以1
开头的递增序列的数字。在开始第二轮之前,您将删除这些数字。您将继续此方式,直到用尽所有数字
但是,模拟这个过程会导致时间复杂度,无法通过问题陈述中提到的约束。因此,我们需要找出另一种方法,在不模拟整个过程的情况下提供相同的输出
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char const *argv[])
{
int n;
cin >> n;
vector <int> v(n + 1), pos(n + 1);
for(int i = 1; i <= n; ++i){
cin >> v[i];
pos[v[i]] = i;
}
int total_rounds = 1; // we'll always need at least one round because the input sequence will never be empty
for(int i = 2; i <= n; ++i){
if(pos[i] < pos[i - 1]) total_rounds++;
}
cout << total_rounds << '\n';
return 0;
}
请注意,数字的位置在这里至关重要。为什么我们需要对2
进行另一轮?因为它在1
之前。我们不需要对3
进行另一轮,因为它在2
之后。同样,我们需要对4
进行另一轮,因为它在2
之前
因此,当考虑每个数字时,我们只需要关心它前面的数字在顺序中的位置。当考虑2
时,我们看1
的位置。1
是在2
之前还是之后?它在后面,我们不需要另一轮。但是如果它在前面,我们需要额外的一轮。对于每个数字,我们查看此条件,并在必要时增加轮数。这样,我们可以计算出总轮数,而无需模拟整个过程
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char const *argv[])
{
int n;
cin >> n;
vector <int> v(n + 1), pos(n + 1);
for(int i = 1; i <= n; ++i){
cin >> v[i];
pos[v[i]] = i;
}
int total_rounds = 1; // we'll always need at least one round because the input sequence will never be empty
for(int i = 2; i <= n; ++i){
if(pos[i] < pos[i - 1]) total_rounds++;
}
cout << total_rounds << '\n';
return 0;
}
#包括
#包括
使用名称空间std;
int main(int argc,char const*argv[]
{
int n;
cin>>n;
向量v(n+1),pos(n+1);
对于(inti=1;i>v[i];
pos[v[i]]=i;
}
int total_rounds=1;//我们总是需要至少一轮,因为输入序列永远不会为空
对于(int i=2;i)为什么代码中有一个set
?你能用简单的英语解释一下你的代码试图做什么?或者,它应该如何工作?而且,链接的问题只包含一个例子,所以你关于输出的陈述没有意义。我遍历了一次数组。如果元素arr[i]小于之前的所有元素,则我“打开”一个新序列,并将该元素保存为该序列中的最后一个元素。我将已打开序列的最后一个元素存储在集合中。如果元素arr[I]小于之前的一些元素,则我将使用其中最大的元素(但小于arr[I])获取已存在的序列,并用arr[i]替换此序列的最后一个元素。我指的是对下载的解决方案执行的三个测试。感谢您的反馈。噢,非常感谢!实际上,我误解了任务。我没有意识到每个子序列都必须由相邻的数字组成。