我遇到了以下问题,
您将获得一个包含 n 个元素的数组 A。这些元素现在被添加到一个新的列表L中,该列表最初是空的,根据给定的q查询以一定的顺序排列。
打印每个元素添加到列表L后形成的所有组中的最大组值。
我的方法是使用map
int g[a.size()+2]; //+2 because queries start with index 1, and g[i] corresponds to a[i-1]
for(int i=0;i<a.size()+2;i++)
g[i]=-1;
int gno=1;
map<int,vector<int> > m;
vector<int> ans;
int mx=0;
for(unsigned int i=0;i<queries.size();i++){
int q = queries[i];
if(g[q-1]==-1 && g[q+1]==-1){
//create new group with current eleent as first element
g[q] = gno; //gno is the group number.
vector<int> v;
v.push_back(1);
v.push_back(a[q-1]);
m[gno]=v;
mx = max(mx,m[gno][0]*m[gno][1]);
gno++;
}
else if(g[q-1]!=-1 && g[q+1]==-1){
//join current element to left group
g[q] = g[q-1];
m[g[q]][0]++;
m[g[q]][1] = max(m[g[q]][1],a[q-1]);
mx = max(mx,m[g[q]][0]*m[g[q]][1]);
}
else if(g[q-1]==-1 && g[q+1]!=-1){
//join current element to right group
g[q] = g[q+1];
m[g[q]][0]++;
m[g[q]][1] = max(m[g[q]][1],a[q-1]);
mx = max(mx,m[g[q]][0]*m[g[q]][1]);
}
else{
//join both groups to left and right
g[q]=g[q-1];
int g1 = g[q];
int i;
m[g[q]][0] += 1 + m[g[q+1]][0];
m[g[q]][1] = max(m[g[q]][1],max(a[q-1],m[g[q+1]][1]));
for(i=q+1;g[i]==g[i+1];i++){
g[i]=g1;
}
g[i]=g1;
mx = max(mx,m[g[q]][0]*m[g[q]][1]);
}
ans.push_back(mx);
}
.
让我们从两个简化的假设开始:
i
被“查询”,它就永远不会再被查询了。(下面我将进一步说明如何不需要这些假设,但目前这将简化情况。)
因此,每当我们“查询”索引i
时,有四种情况:
i-1
当前是一个组的右endpoint(我指的是它的最大索引),i 1
当前是另一个组的左endpoint。
i
弥合它们之间的差距。i
。i
。在所有情况下,需要注意的关键是,我们只对组的endpoint感兴趣。因此,我们不需要从索引到其组的一般映射。 。 。这很好,因为当我们合并两个组时,然后去更新一个组中的每个索引以指向另一个组将是昂贵的。
所以我们只需要三个映射:
std::unordered_map<int, int> map_from_left_endpoint_to_right_endpoint;
std::unordered_map<int, int> map_from_right_endpoint_to_left_endpoint;
std::unordered_map<int, int> map_from_left_endpoint_to_largest_value;
为了区分这四种情况,我们使用< code > map _ from _ right _ endpoint _ to _ left _ endpoint . find(I-1)(它返回一个迭代器,指向< code>i-1是其右endpoint的组的左endpoint,如果适用的话;否则,它返回< code > map _ from _ right _ endpoint _ to _ left _ endpoint . end()。然后,当条目变得不再适用时(由于组在给定的方向上被扩展或合并),除了(显然)插入新的条目,并更新现有条目的值之外,我们删除条目。
除了这些值,我们还需要一个
int maximum_group_value = 0;
每当我们扩展一个组或合并两个组时,我们都会检查结果组的值(即其largestvalue*(rightendpoint-lefftendpoint1
)是否大于maximumgroupvalue。如果是,我们更新maximum_group_value并返回它;如果不是,则按原样返回maximumgroupvalue。
现在,如果允许重复,那么给定的索引< code>i可能在它已经属于一个组之后被“查询”呢?
最简单的方法是简单地跟踪已经被查询的< code > I ;但是,如果需要,更好的方法可能是将< code > map _ from _ left _ endpoint _ to _ right _ endpoint 从< code>std::unordered_map更改为< code>std::map,然后像这样使用:
bool is_already_in_a_group(
std::map<int, int> const & map_from_left_endpoint_to_right_endpoint,
int const i) {
// get iterator to first element *after* index (or to 'end()' if no such):
auto iter = map_from_left_endpoint_to_right_endpoint.upper_bound(index);
// if that pointer points to 'begin()', then there are no elements
// at or before index:
if (iter == map_from_left_endpoint_to_right_endpoint.begin()) {
return false;
}
// otherwise, move iterator to point to the last element whose key is
// less than or equal to index:
--iter;
// . . . and check whether the value of that element is greater than
// or equal to index (meaning that [key, value] spans index):
return iter->second >= index;
}
检查mapfromleft_endpoint_to_right_endpoint
中小于或等于i的最大键是否映射到大于或等于
i的值。
这为我们上面的案例分析增加了第五种情况——“如果
i
已经在一个组中,什么也不做并返回maximum_group_value
”——但除此之外,没有任何效果。
请注意,如果我们愿意,同样的方法还可以让我们消除
map_from_right_endpoint_to_left_endpoint
:通过将返回语句更改为返回
iter,可以轻松地将上述函数调整为 int get_left_endpoint_for_right_endpoint
此时,定义一个包含三个字段(
left_endpoint
、right_endpoint
和largest_value
)的Group
类是明智的,并且只保留一个map_from_left_endpoint_to_group
。
最后——如果允许负值,使得“最大组值”实际上可以作为查询的结果而减少怎么办?(例如,如果数组元素是
[-1,-10]
并且查询是i=0
,i=1
,那么结果是maximum_group_value=-1
,maximum_group_value=-2
。)在这种情况下,我们需要跟踪所有当前组的值,因为它们中的任何一个都可能突然变成最大值。
为此,我们可以维护一堆按值排序的组,而不是存储单个
int maximum_group_value
,每次创建/扩展/合并组时都会将其推送到其中。(我们可以只使用标准::向量
作为优化,我们还可以存储
intmaximum_group_value
,并在遇到非负数组元素后消除堆(因为一旦给定组包含非负数组元素,其值就不会再减少,显然最大组值将是其中一个组的值)。
实际上,我不会构建list L。寻找如何处理新值的时间成本可能太高:它本身是一个新组吗?它扩展了现有的组吗?两个组需要合并成一个组吗?如果第一个值相距很远,您将有许多组,并且您需要用每个新的传入值迭代它们:这是没有效率的。
我会先收集所有值,然后才看看它们如何适合组。
有两种收集值的方法:
>
将它们存储在列表中,并在收集完所有值后,按升序对列表进行排序
标记大小为 n 的布尔值数组中的条目。这样,您就不必对其进行排序,但之后您确实需要迭代整个数组以按升序查找值。
当 q 远小于 n 时,方法 1 将是最好的。方法 2 对于更大的 q 会更好。
使用这两种方法,您将能够按升序迭代找到的值,同时您可以识别组、它们的值,并跟踪最大的组值。只需要一次扫描即可找到答案。
我有一个arraylist的arraylist,每个arraylist都有相同的点,例如,当您打印时,这是输出 在打印之前,我要删除其x值不等于数组列表索引的所有点 所以输出应该是 我尝试使用remove方法和for循环以及其他方法,但都不起作用。 有人能帮忙吗?
我需要从一个列表中追加一些重复的值到一个子列表中,让我用一个例子来解释: 我有一个名为的变量,它包含大写字母字符串和符号。 我的最终目标是拥有这个数组: 在示例中,我需要将所有的符号分组到原始中的子列表中,我想过在数组中迭代,找到当前附近的所有符号,然后创建第二个数组,但我想也许还有更多的pythonic我可以做的,有什么想法吗?
我是Java和Stack Overflow的新手,我有一个关于排列的问题。 方法:我使用中的对象生成。每个的大小从(可能最小为1)到,并包含具有唯一名称属性的自定义生成对象。 问题:现在我的问题是如何在我的外部(y轴)中获得从第一个到最后一个的所有可能对象组合的排列(我想我们可以说这是x轴)? 我试着举一个简单的例子: : 1.1|1.2|1.3 : 2.1 : 3.1|3.2 这里,这些位于外部
给定一个< code>n数和sum 的列表,将这些数分成< code >两个组,使得每组中的数之和小于或等于s。如果可以分组,则打印< code>YES,如果不能分组,则打印< code>NO。 例如,如果< code>n=3,s=4和< code>n数是< code>2,4,2。在这种情况下,输出为< code>YES,因为可以形成两个组< code>(2,2)和(4)。 我的解决方案如下。 是
问题内容: 我正在使用H2-DB访问静态数据库… 我有一张桌子,看起来像: 它的名单很多,有很多国家,其中大多数只有国家和州(例如德国在这里,而州是城市),也有一个城市(在这里是美国)… 问题是现在,当我查询 为了得到州(或城市)的排序列表,我收到一条错误消息,说 如果该行有一个城市,我需要整行,否则我只需要State列,但是查询后我可以知道,是否使用了city列,所以我必须查询“ *”的“ ST
问题内容: 我有一个这样的(标签,计数)元组列表: 由此,我想对所有具有相同标签的值求和(相同的标签始终相邻),并以相同的标签顺序返回列表: 我知道我可以用以下方法解决它: 但是,有没有更Pythonic /优雅/有效的方法来做到这一点? 问题答案: 可以做你想做的: