数组(向量)中大于某个值的元素的起始索引和结束索引

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 可能还不够好。

我通常使用SIMDIPP 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 以包含成员变量,或者简单地说,可以像您想要的那样复杂。

还请记住,如果您正在为这些事情计时,为发布、优化构建计时。不要计时“调试”或未优化的构建。

【讨论】:

哇。感谢您的回答。但恐怕我必须通过线性插值来计算新值。这意味着我必须获得两个适当的值,它们位于不适当的值旁边。顺便说一句,releasefull 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);
    

【讨论】:

以上是关于数组(向量)中大于某个值的元素的起始索引和结束索引的主要内容,如果未能解决你的问题,请参考以下文章

如何通过C ++中的数据获得向量的索引

提取数组中非 NaN 元素的索引和值的正确方法

c#如何查找string数组的某一个值的索引

Java中数组获取最大值

Leetcode练习(Python):第162题:峰值元素是指其值大于左右相邻值的元素。 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。 数组

字符串方法