问题陈述
在冒泡排序中,每当我在数组中交换两个元素时(排序时),我在交换的元素之间绑一根绳子。我需要找到数组中最大集合的大小,其中没有任何元素在冒泡排序完成后与任何其他元素连接。
例如:{1,3,2}
冒泡排序的第一次迭代:
2和3交换,因此将2与3
联系起来{1,2,3}
第二次迭代
{1,2,3} 此迭代中没有交换,因此不要将任何元素与任何其他元素绑定
第3次迭代
{1,2,3} 此迭代中没有交换,因此不要将任何元素与任何其他元素绑定
在冒泡结束后,只有2和3绑在一起
这个例子的答案是2,因为最大集合的大小,其中没有任何元素没有与任何其他元素绑定。
可能的最大集合是{1,2}(因为1和2没有用绳子捆绑)和{1,3} {因为1和3没有用绳索捆绑}
此数组的可能子集为{1},{2},{3},{1,2},{1,3},{3,2} {1,3,2},{}
这些有效子集中的是{1},{2},{3},{1,2},{1,3}在这个有效子集{1,2}和{1,3}中是更大的子集两个子集的大小都是2.所以答案是2。
输入:
第一行输入包含T - 测试用例
每个测试用例的第一行包含n(1 <= n <= 100000) - 数组中的元素数
每个测试用例的第二行包含数组的n个元素
示例:
输入:(来自上面解释的例子)
1
3
1 3 2
输出:
2
MY APPROACH
我认为最大子集长度将是最长增长子序列的长度,这是我的代码获得错误的答案。请帮忙!
#include <iostream>
using namespace std;
int bs(int a[],int x,int lo,int hi)
{
while(hi-lo>1)
{
int mid=(hi+lo)/2;
if(a[mid]>=x)
hi=mid;
else
lo=mid;
}
return hi;
}
int main() {
int t;
cin>>t;
while(t--)
{
int n,m=1;
cin>>n;
int a[n+1];
for(int i=0;i<n;i++)
cin>>a[i];
int dp[n+1];
for(int i=0;i<n;i++)
dp[i]=0;
dp[0]=a[0];
for(int i=1;i<n;i++)
{
if(dp[0]>a[i])
dp[0]=a[i];
else if(a[i]>dp[m-1])
dp[m++]=a[i];
else
{
int x=bs(a,a[i],-1,m-1);
dp[x]=a[i];
}
}
cout<<m<<endl;
}
return 0;
}
答案 0 :(得分:1)
首先通过归纳观察每个连通分量是一个区间。
接下来观察,给定输入分为两部分,当且仅当第一部分中的每个元素小于或等于第二部分中的每个元素时,没有边缘跨越部分。
可以使用线性时间算法识别连接的组件。
def count(lst):
compmaxes = [] # holds the maximum of each connected component
for x in lst:
if not compmaxes or compmaxes[-1] <= x:
compmaxes.append(x)
else:
while len(compmaxes) > 1 and compmaxes[-2] > x:
del compmaxes[-2]
return len(compmaxes)