【问题标题】:Arithmetic sequence - checking算术序列 - 检查
【发布时间】:2015-10-12 16:23:53
【问题描述】:

检查是否可以从指定的数字序列创建等差数列的最有效方法是什么?

目前我对序列进行排序,然后这样做:

#include<bits/stdc++.h>
using namespace std;

static bool sort_using_greater_than(float u, float v)
{
return u > v;
}


int main()
{
int licznik=0, i=0;
double number[100000];
while(~scanf("%f", &number[i]))
{
     i++;
     licznik++;
}
 sort(number,number+100, sort_using_greater_than);

for(int i = 1; i < licznik-1; i++)
{
    if(number[i] - number[i+1] != number[0] - number[1])
    {
        puts("NO");
        return 0;
    }
}
puts("YES");

}

测试用:

  1. 1.0 5.0

我的代码返回 YES,为什么?

enter code here
double search_min(double tab[], int n)
{
double min = tab[0];
for(int i = 1; i < n; i++)
{
    if(min > tab[i])
        min = tab[i];
return min;
}

还有,我怎样才能找到两个最小的元素?

【问题讨论】:

  • 你必须检查每个数字,所以复杂度是O(n)
  • 是刚刚排序或唯一的数字。如果它们也是独一无二的,并且你知道有多少,你可以在 O(1) 内完成
  • @ManosNikolaidis:仅在一种特殊情况下。
  • 否,但可以进行一些微优化:在循环外只计算一次diff = number[0] - number[1]。虽然优化编译器可能会为你做这件事,但这不是一个微不足道的优化。
  • 当用户可能无法输入 100 个数字时,为什么要sort(number,number+100, sort_using_greater_than);

标签: c++ algorithm math


【解决方案1】:

这个问题不清楚,但如果它的意思是“检查给定的数字是否可以从一个等差数列中重新排列”,那么就不需要排序了。

  • 找到最小的元素,O(N),让a;

  • 求第二小的,O(N),设b;

  • 在 O(N) 中清除 N 位数组;

  • 对于每个数字 c,计算 (c - a) / (b - a);如果这不是 [0,n-1] 范围内的整数,则答案是否定的。否则,在该索引处设置位(每个元素在 O(1) 内完成);

  • 检查所有位是否已设置为 O(N)。

整个过程耗时O(N)。

【讨论】:

  • 如何找到第二小的元素?
  • @Podolski:去掉最小的,再找最小的。
【解决方案2】:

O(n) 是最好的,因为你必须检查每个元素。

我已经在 C++14 标准代码中实现了 Yves Daoust 的算法(进行了一些小的优化)以及您自己的算法。

这是你的:

int main(int argc, char* argv[]) {

    if(argc == 1) return 0;

    //Copy command args to vector of strings.
    std::size_t number_count = argc - 1;
    std::vector<std::string> cmd_args(number_count);
    std::copy(argv + 1, argv + argc, cmd_args.begin());

    //Copy convert vector of strings to vector of ints.
    std::vector<int> values(number_count);
    auto v_begin = values.begin();
    for(auto s : cmd_args) {
        (*v_begin) = std::stoi(s);
        ++v_begin;
    }

    //Sort values in ascending order.
    std::sort(values.begin(), values.end());

    //Get smallest two values.
    std::pair<int, int> two_smallest_values(*values.cbegin(), *(values.cbegin() + 1));

    //Calculate differences between each successive number
    std::vector<int> differences(values.size() - 1);
    for(std::size_t i = 0; i < values.size() - 1; ++i) {
        differences[i] = std::abs(values[i] - values[i + 1]);
    }

    //All values in differences must be the same.
    if(std::all_of(differences.cbegin(), differences.cend(), [=](int i) { return i == *differences.cbegin(); })) {
        std::cout << "YES\n";
    } else {
        std::cout << "NO\n";
    }

    return 0;
}

这是 Yves Daoust 的算法:

int main(int argc, char* argv[]) {
    if(argc == 1) return 0;

    //Copy command args to vector of strings.
    std::size_t number_count = argc - 1;
    std::vector<std::string> cmd_args(number_count);
    std::copy(argv + 1, argv + argc, cmd_args.begin());

    //Copy convert vector of strings to vector of ints.
    auto v_begin = values.begin();
    for(auto s : cmd_args) {
        (*v_begin) = std::stoi(s);
        ++v_begin;
    }

    //Sort values in ascending order.
    std::sort(values.begin(), values.end());

    //Get smallest two values.
    std::pair<int, int> two_smallest_values(*values.cbegin(), *(values.cbegin() + 1));

    std::vector<bool> bits(values.size());

    bool result = true;

    int smallest_diff = (two_smallest_values.second - two_smallest_values.first);
    for(auto v : values) {
        int numerator = v - two_smallest_values.first;
        int denominator = smallest_diff;
        if(numerator % denominator != 0) {
            result = false;
            break;
        }
        std::size_t i = numerator / denominator;
        if(i < 0 || i >= values.size()) {
            result = false;
            break;
        }
        bits[i] = true;
    }

    if(result == false) {
        std::cout << "NO\n";
        return 0;
    }        

    //Convert vector of bools (bit-packed) to an unsigned int.
    unsigned long long bits_value = 0;
    unsigned long long i = 0;
    for(auto b : bits) {
        bits_value |= (b << i++);
    }

    //Optimization: Single calculation to determine if all bits are set:
    if(std::abs(bits_value - (std::pow(2.0, bits.size()) - 1) < 0.01)) {
        std::cout << "YES\n";
    } else {
        std::cout << "NO\n";
    }

    return 0;
}

【讨论】:

  • 我的解决方案的实现缺少一个基本要素:检查比率是否为整数。它似乎也仅限于 N=32 !?!
  • @YvesDaoust 已修复。 :)
  • 没那么简单,因为输入的数字是实数!
猜你喜欢
  • 2010-12-28
  • 2011-01-17
  • 2022-01-06
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多