数组(向量)中大于某个值的元素的起始索引和结束索引
Posted
技术标签:
【中文标题】数组(向量)中大于某个值的元素的起始索引和结束索引【英文标题】:starting index and ending index of elements in a array(vector) that are greater than a value 【发布时间】:2014-04-17 15:27:57 【问题描述】:给定一个这样的数组:
1, 3, 11, 2, 24, 13, 5....
数组长度可能大于 1000。
如果元素的值不合适,比如大于10,就用合适的值代替。在这种情况下,通过线性插值计算出合适的值。
例如:
Arr = 1, 3, 11, 2, 24, 13, 5....;
新数组应为:
NewArr = 1, 3, 3+(2-3)/2, 2, 2+(5-2)/3, 2+2*(5-2)/3, 5, ...
为了做到这一点,我必须知道不适当元素的开始和结束索引。
开始和结束索引应为 (2,2) 表示“11”和 (4,5) 表示“24, 13”
我试过for loop
。但效率不高。
然后我搜索了IPP API
,没有得到结果。 :(
有更好的主意吗?
感谢您的帮助,:)。
顺便说一句:IPP API
会是更好的选择。
更新:
示例代码:
int arr[] = 1, 3, 11, 2, 24, 13, 5....;
/// find the starting index and ending index of inappropriate values
/// (2,2) (4,5).
int i = 0;
std::map<int,int> Segments;
if(arr[i] > Threshold)
int b = i;
while(arr[i] > Threshold )
i ++;
int e = i;
Segments.insert(std::map<int,int>::value_type(b,e));
/// linear interpolation
for(std::map<int,int>::iterator i = 0; i != Segments.end(); i ++) /// len means the number of inappropriate segments
//// linear interpolation of each segments
int b = i->first;
int e = i->second;
int num = e - b + 1;
float step = (arr[e+1]-arr[b-1]) / num; // For short. The case that b=0 or e=len-1 is not considered.
for(int j = b; j <= e; j ++)
arr[j] = arr[j-1] + step;
更新2:
感谢你的帮助。但是根据这些问题的答案:Speed accessing a std::vector by iterator vs by operator[]/index? 和Why use iterators instead of array indices?,两种形式(for vs iterator)的效率几乎相同。所以iterator
可能还不够好。
我通常使用SIMD
如IPP API
作为优化选项。但我没弄明白,因为所有的find
API 都只获得指定元素的第一次出现。
如果有一天我弄清楚了,我会更新解决方案。 :)
【问题讨论】:
向我们展示一些你的代码怎么样? 您是否尝试过简单地使用例如std::replace_if
替换错误的值?虽然“大于 1000”可以表示从 1001 到无穷大的任何值,但在现代计算机上迭代数组中的数千个条目确实很快。
@JoachimPileborg,我必须通过线性插值计算新值。恐怕std::replace_if
行不通。
@Steve - 然后看看我作为答案给出的 std::transform 算法函数。函子会稍微复杂一点,但它应该可以工作。
【参考方案1】:
如果你想搜索一个特定的值,并从一个符合特定条件的向量中替换项目,那么可以使用 transform() 在一行中完成。
也可以使用replace_if(),但是鉴于您对问题的模糊描述,我不知道替换值是否需要根据原始值而变化(replace_if 需要一个恒定的替换值)。所以现在让我们使用 std::transform()。
#include <algorithm>
#include <vector>
struct Transformer
bool ThisNumberNeedsTransformation(int num)
// you fill this in. Return true if number needs to be changed, false otherwise
int TransformNumber(int num)
// you fill this in. Return the changed number, given the original number.
int operator()(int num)
if ( ThisNumberNeedsTransformation(num) )
return TransformNumber(num);
return num;
;
int main()
std::vector<int> intVector;
//...
std::transform(intVector.begin(), intVector.end(), intVector.begin(), Transformer());
基本上,结构体用作函数对象。对于 intVector 中的每个项目,函数对象将对该数字进行操作。如果数字符合条件,则转换并返回数字,否则返回原始数字。
由于您没有真正阐明更改数字的标准是什么,因此这种方法为您的问题的解决方案提供了更大的灵活性。您需要做的就是填写我在Transformer
结构中打开的两个函数,然后一切正常。
如果您的需求更复杂,可以扩展函数对象 Transformer 以包含成员变量,或者简单地说,可以像您想要的那样复杂。
还请记住,如果您正在为这些事情计时,为发布、优化构建计时。不要计时“调试”或未优化的构建。
【讨论】:
哇。感谢您的回答。但恐怕我必须通过线性插值来计算新值。这意味着我必须获得两个适当的值,它们位于不适当的值旁边。顺便说一句,release
和 full optimized
确实是一个好方法。
@Steve - 我编辑了我的答案。基本上你刚才所说的正是使用函数对象的原因——你的需求的复杂性可以直接编码到结构中。如果您需要“记住”值,则可以添加成员变量来跟踪这些值。
但是根据这些问题的答案:***.com/questions/2524233/… 和***.com/questions/131241/…,两种形式(for vs iterator)的效率几乎相同。恐怕iterator
可能不够好。【参考方案2】:
我不确定您所说的“不适当元素的开始和结束索引”是什么意思,所以我假设您只是指索引。
在这里使用向量是一个好方法:
std::vector<int> the_stuff 1, 3, 11, 2, 24, 13, 5, ... ;
std::vector<int>::iterator it = the_stuff.begin();
while (it != the_stuff.end()
if (*it > 10) // do stuff ;
etc.
你明白了。使用vector,它应该会让你的事情变得更容易。随意搜索/插入/获取索引/删除/等。
【讨论】:
【参考方案3】:如果将数字存储在 std::vector 中,则可以通过迭代器迭代数组。一旦你找到一个满足你的条件并且需要移除的元素,你可以移除它,同时将你的迭代器分配给下一个元素。这将是最有效的方式:
您的代码如下所示:
std::vector<int> intVector;
for(auto it = intVector.begin(); it != intVector.end(); ++it)
if (*it > 10)
it = intVector.erase(it);
【讨论】:
以上是关于数组(向量)中大于某个值的元素的起始索引和结束索引的主要内容,如果未能解决你的问题,请参考以下文章
Leetcode练习(Python):第162题:峰值元素是指其值大于左右相邻值的元素。 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。 数组