Учитывая массив как это:
{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;
}
Update2:
Спасибо за вашу помощь. Но на основании ответов на эти вопросы:Скорость доступа к std :: vector с помощью итератора по сравнению с оператором [] / index? а также Зачем использовать итераторы вместо индексов массива?, Эффективность двух форм (для итератора) практически одинакова. Так iterator
может быть не достаточно хорош.
Я обычно использовал SIMD
такие как IPP API
как вариант оптимизации. Но я не понял этого, так как все find
API только получить первое вхождение указанного элемента.
Я обновлю решение, если выясню когда-нибудь. 🙂
Если вы хотите найти определенное значение и заменить элементы из вектора, которые соответствуют определенным критериям, то это можно сделать в одной строке с помощью 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 может быть расширен за счет включения переменных-членов или, проще говоря, может быть настолько сложным, насколько вы захотите это сделать.
Также помните, если вы рассчитываете эти вещи, время релиза, оптимизированная сборка. Не время «отладки» или неоптимизированных сборок.
Я не совсем уверен, что вы подразумеваете под «начальным и конечным индексом неподходящих элементов», поэтому я предполагаю, что вы просто имеете в виду индекс.
Использование вектора здесь будет хорошим подходом:
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.
}
Вы поняли идею. Использовать вектор, и это должно сделать все намного проще для вас. поиск / вставка / получение индексов / удаление / и т. д. на досуге.
Если вы храните свой номер в std :: vector, вы можете перебирать массив через итератор. Как только вы найдете элемент, который соответствует вашему условию и требует удаления, вы можете удалить его и одновременно назначить свой итератор следующему элементу. Это будет самый эффективный способ:
Вот как будет выглядеть ваш код:
std::vector<int> intVector;
for(auto it = intVector.begin(); it != intVector.end(); ++it)
{
if (*it > 10)
{
it = intVector.erase(it);
}
}