C++ 向量自定义和

C++ 向量自定义和,c++,arrays,algorithm,C++,Arrays,Algorithm,我需要从具有以下属性的整数数组中标识变量的位置: 此变量前的元素和此变量后的元素和相等 如果变量不存在,我将显示一条消息 例如,如果x={1,2,4,2,1},结果是位置为2的4,因为1+2==2+1。 有什么建议吗?在这个例子中很简单 if((x[0]+x[1])==(x[3]+x[4])) print position 2 但是对于n个变量呢 只是循环而已。您需要对每个索引前后的元素求和,然后比较这两个和: #include <iostream> #include <ve

我需要从具有以下属性的整数数组中标识变量的位置:

此变量前的元素和此变量后的元素和相等

如果变量不存在,我将显示一条消息

例如,如果x={1,2,4,2,1},结果是位置为2的4,因为1+2==2+1。 有什么建议吗?在这个例子中很简单

if((x[0]+x[1])==(x[3]+x[4]))
print position 2

但是对于n个变量呢

只是循环而已。您需要对每个索引前后的元素求和,然后比较这两个和:

#include <iostream>
#include <vector>
#include <numeric>

int main() {

    std::vector<int> x = {1, 2, 4, 2, 1};

    for ( unsigned idx = 0; idx < x.size(); ++idx )
        if ( std::accumulate(x.begin(), x.begin() + idx, 0) == std::accumulate(x.begin() + idx + 1, x.end(), 0) )
            std::cout << idx << std::endl;

    return 0;
}

只是循环而已。您需要对每个索引前后的元素求和,然后比较这两个和:

#include <iostream>
#include <vector>
#include <numeric>

int main() {

    std::vector<int> x = {1, 2, 4, 2, 1};

    for ( unsigned idx = 0; idx < x.size(); ++idx )
        if ( std::accumulate(x.begin(), x.begin() + idx, 0) == std::accumulate(x.begin() + idx + 1, x.end(), 0) )
            std::cout << idx << std::endl;

    return 0;
}
下面是解决方案

从数组beginingleft_sum开始,在一个变量中求和,并使用另一个右_sum从元素之和(第一个元素除外)进行推断。当两者相等时,断开循环并打印。否则,显示你的味精

#include <iostream>
#include <vector>
#include <numeric>
#include <cstddef>

int main()
{
    std::vector<int> vec {1,2,4,2,1};

    int left_sum = 0;
    int right_sum = std::accumulate(vec.cbegin()+1, vec.cend(), 0);

    bool Okay = false;
    std::size_t index = 1; // start from index 1 until n-1
    for( ; index < vec.size() - 1; ++index)
    {
        left_sum += vec[index-1];
        right_sum -= vec[index];
        if(left_sum == right_sum)
        {
            Okay = true;
            break;
        }
        // in the case of array of positive integers
        // if(left_sum > right_sum) break;
    }
    (Okay) ? std::cout << vec[index] << " " << index << std::endl: std::cout << "No such case!\n";
    return 0;
 }
下面是解决方案

从数组beginingleft_sum开始,在一个变量中求和,并使用另一个右_sum从元素之和(第一个元素除外)进行推断。当两者相等时,断开循环并打印。否则,显示你的味精

#include <iostream>
#include <vector>
#include <numeric>
#include <cstddef>

int main()
{
    std::vector<int> vec {1,2,4,2,1};

    int left_sum = 0;
    int right_sum = std::accumulate(vec.cbegin()+1, vec.cend(), 0);

    bool Okay = false;
    std::size_t index = 1; // start from index 1 until n-1
    for( ; index < vec.size() - 1; ++index)
    {
        left_sum += vec[index-1];
        right_sum -= vec[index];
        if(left_sum == right_sum)
        {
            Okay = true;
            break;
        }
        // in the case of array of positive integers
        // if(left_sum > right_sum) break;
    }
    (Okay) ? std::cout << vec[index] << " " << index << std::endl: std::cout << "No such case!\n";
    return 0;
 }

有几种方法可以做到这一点:

蛮力-不超过2次:

在数组中循环。 对于每个元素,计算该元素前后的总和。 如果它们匹配,则找到元素。 如果之前的和大于之后的和,请停止处理-未找到匹配项。 对于较大的阵列,这并不是真正有效的

1.5通行证:

计算所有元素的总和。 把那个总数除以2/2。 从头开始再次对元素求和,直到达到一半。 检查是否找到有效的元素。 仅限单程正数:

保留两个连续总和:一个从开始的总和1开始,另一个从结束的总和2开始。 设置sum1=第一个元素,sum2=最后一个元素。 检查两个元素中最小的一个,并将下一个/上一个元素添加到该元素中。 循环直到位置满足,并检查元素是否为有效结果。 对于每种方法,您都必须首先进行litlle检查,以查看数组是否太小

需考虑的特殊情况:

空数组:返回false 包含1个元素的数组:返回元素 包含2个非零元素的数组:返回false 什么是全零,还是零的组在中间?请参阅重复数据消除程序的评论 负面因素:单程版本在这里不起作用见Cris Luengo的评论 负面因素一般:不可靠,考虑3 + 1 - 1 + 1 - 1 + 3 + 1见Deduplicator的评论
有几种方法可以做到这一点:

蛮力-不超过2次:

在数组中循环。 对于每个元素,计算该元素前后的总和。 如果它们匹配,则找到元素。 如果之前的和大于之后的和,请停止处理-未找到匹配项。 对于较大的阵列,这并不是真正有效的

1.5通行证:

计算所有元素的总和。 把那个总数除以2/2。 从头开始再次对元素求和,直到达到一半。 检查是否找到有效的元素。 仅限单程正数:

保留两个连续总和:一个从开始的总和1开始,另一个从结束的总和2开始。 设置sum1=第一个元素,sum2=最后一个元素。 检查两个元素中最小的一个,并将下一个/上一个元素添加到该元素中。 循环直到位置满足,并检查元素是否为有效结果。 对于每种方法,您都必须首先进行litlle检查,以查看数组是否太小

需考虑的特殊情况:

空数组:返回false 包含1个元素的数组:返回元素 包含2个非零元素的数组:返回false 什么是全零,还是零的组在中间?请参阅重复数据消除程序的评论 负面因素:单程版本在这里不起作用见Cris Luengo的评论 负面因素一般:不可靠,考虑3 + 1 - 1 + 1 - 1 + 3 + 1见Deduplicator的评论
谢谢你的回答。我终于成功了。我用3表示循环,s0表示元素前面的和,s1表示元素后面的和

 for(i=0;i<n;i++)
    {s1=0;
    s0=0;
        for(int j=0;j<i-1;j++)
                s0=s0+v[j];
        for(int k=i;k<n;k++)
            s1=s1+v[k];
        if(s0==s1)
            {cout<<endl<<"Position i="<<i;
            x++;}

    }
    if(x==0)
        cout<<"doesnt exist";

谢谢你的回答。我终于成功了。我用3表示循环,s0表示元素前面的和,s1表示元素后面的和

 for(i=0;i<n;i++)
    {s1=0;
    s0=0;
        for(int j=0;j<i-1;j++)
                s0=s0+v[j];
        for(int k=i;k<n;k++)
            s1=s1+v[k];
        if(s0==s1)
            {cout<<endl<<"Position i="<<i;
            x++;}

    }
    if(x==0)
        cout<<"doesnt exist";

试图用std::algorithm构建解决方案, n+lg n而不是n+~n/2

警告未测试的代码

bool HasHalfSum(int& atIndex, const std::vector<int>& v) {
  std::vector<int> sum;
  sum.reserve(v.size);

  std::partial_sum(v.begin(), v.end(), std::back_iterator(sum));
  // 1,3,7,9,10

  int half = sum.back() / 2; // 5

  auto found = std::lower_bound(sum.begin(), sum.end(), half);

  if (found != sum.begin() && std::prev(found) == sum.back() - *found) {
    index = std::distance(sum.begin(), found);
    return true;
  }

  return false;
}

试图用std::algorithm构建解决方案, n+lg n而不是n+~n/2

警告未测试的代码

bool HasHalfSum(int& atIndex, const std::vector<int>& v) {
  std::vector<int> sum;
  sum.reserve(v.size);

  std::partial_sum(v.begin(), v.end(), std::back_iterator(sum));
  // 1,3,7,9,10

  int half = sum.back() / 2; // 5

  auto found = std::lower_bound(sum.begin(), sum.end(), half);

  if (found != sum.begin() && std::prev(found) == sum.back() - *found) {
    index = std::distance(sum.begin(), found);
    return true;
  }

  return false;
}

那么,分两步进行:

对所有元素求和。 自始至终: 如果总和等于当前元素,则成功! 从总和中减去两次,一次表示不在右边,一次表示在左边。 使用标准算法和范围,并且很容易编写:

auto first_balanced(std::span<const int> x) noexcept {
    auto balance = std::accumulate(begin(x), end(x), 0LL);
    for (auto&& n : x) {
        if (balance == n)
            return &n;
        balance -= 2 * n;
    }
    return end(x);
}

那么,分两步进行:

对所有元素求和。 自始至终: 如果总和等于当前元素,则成功! 从总和中减去两次,一次表示不在右边,一次表示在左边。 使用标准算法和范围,并且很容易编写:

auto first_balanced(std::span<const int> x) noexcept {
    auto balance = std::accumulate(begin(x), end(x), 0LL);
    for (auto&& n : x) {
        if (balance == n)
            return &n;
        balance -= 2 * n;
    }
    return end(x);
}


您是否尝试过循环?循环数组中的所有元素并测试您为每个索引指定的条件,计算具有较小索引的前面值和具有较大索引的后面值的和。如果两个和相等,则找到匹配项。如果没有,请继续下一个索引。重复此操作,直到找到匹配项或考虑所有索引。您可以从两个变量开始,在=0之前;之后=一切的总和;。然后访问每个元素,并使用访问的元素调整这些值。如果结果匹配,则停止。是否尝试循环?循环数组中的所有元素并测试为每个索引指定的条件,计算索引较小的前一个值和索引较大的后一个值的和。如果两个和相等,则找到匹配项。如果没有,请继续下一个索引。重复此操作,直到找到匹配项或考虑所有索引。您可以从两个变量开始,在=0之前;之后=一切的总和;。然后访问每个元素,并使用访问的元素调整这些值。如果结果匹配,请停止。这是一个On*n解决方案。但这是一个On*n解决方案。当left\u sum>right\u sum时,可以通过断开来进行一些优化。另外,请看我的单程通行证示例:@Danny_ds您是对的。让我更新一下。谢谢,顺便说一句。你知道除以二是非常有效的,然后你只需要加一个和?ifleft\u sum>right\u sum break;如果允许使用负数组元素,则零件是错误的。@CrisLuengo正确点,已编辑。我只考虑过这个案子。谢谢你指出还有一种情况是,如果数组的大小小于3怎么办?我把它留给OP去考虑。当left\u sum>right\u sum时,你可以通过中断来优化一点。另外,请看我的单程通行证示例:@Danny_ds您是对的。让我更新一下。谢谢,顺便说一句。你知道除以二是非常有效的,然后你只需要加一个和?ifleft\u sum>right\u sum break;如果允许使用负数组元素,则零件是错误的。@CrisLuengo正确点,已编辑。我只考虑过这个案子。谢谢你指出还有一种情况是,如果数组的大小小于3怎么办?我把它留给OP去考虑。这是蛮力方法,对于更大的阵列不是很有效。看看@Jejo的答案。这让您很好地了解了如何优化它。这是蛮力方法,对于更大的阵列不是很有效。看看@Jejo的答案。这让您很好地了解了如何对此进行优化。顺便说一句,由于分支预测和缓存,1.5次传递可能比1次传递更有效。如果存在负数组元素,我不确定单次传递方法是否有效。@Duplicator True,我也在考虑这个问题。然而,我想我在某个地方读到,现代CPU的一级缓存处理反向内存访问几乎和正向访问一样好。但事实上,分支预测和更细的循环可能会产生差异。例如,Otoh在循环中有更多的指令可以使它们以与循环展开相同的时钟周期执行。所以这将是一个有趣的测试。顺便说一句,由于分支预测和缓存,1.5次传递可能比1次传递更有效。我不确定单次传递方法在存在负数组元素的情况下是否有效。@Duplicator True,我也在考虑这个问题。然而,我想我在某个地方读到,现代CPU的一级缓存处理反向内存访问几乎和正向访问一样好。但事实上,分支预测和更细的循环可能会产生差异。例如,Otoh在循环中有更多的指令可以使它们以与循环展开相同的时钟周期执行。所以这将是一个有趣的测试。