如何计算一系列数字中的谷数?

时间:2014-10-29 04:11:56

标签: c algorithm

给定一系列数字,谷被定义为序列中由较高值包围(向左和向右)的区域。任务是找到序列中的谷数。 例如,

{9,8,7,7,8,9} has one valley at {7,7}
{9,8,7,7,8,6,9} has two valleys at {7,7} and {6}
{7,8,9,8,7} has no valleys

我必须计算山谷数量的代码如下:

#include <stdio.h>
#define SIZE 40
int main()
{
   int input;
   int store[SIZE];
   int i = 0;
   int j;
   int valley = 0;
   int count = 0;

   printf("Enter sequence: ");
   scanf("%d", &input);
   while(input != -1)
   {
     store[i] = input;

     i++;

     scanf("%d", &input);
   }

   count = count + i;
   for(i = 1; i < count; i++)
   {
     for(j = i; j < i + 1; j++)
     {

       if((store[j-1] > store[j]) && (store[j] < store[j+1]))
       {
         valley = valley + 1;
         break;
      }
    }
  }

  printf("Number of valleys: %d", valley);

  return 0;
}

如果输入为“3 2 1 2 3”,我可以显示正确的答案。但是,如果在数字等于另一个并且它们并排(例如,“3 1 1 2”)之间,则程序将计算错误的答案。 我如何编写程序以便能够显示正确数量的山谷?

3 个答案:

答案 0 :(得分:1)

查看从下到上的坡度变化。

不是双嵌套for循环,而是沿着寻找从下到上的斜率变化。考虑任何0的斜率与前一斜率相同。

size_t Valley(const int *store, size_t count) {
  size_t valley = 0;
  int slope = -1;
  size_t i;

  // Find first down slope
  for (i = 1; i < count; i++) {
    if (store[i] < store[i - 1]) {
      break;
    }
  }

  for (; i < count; i++) {
    int newslope = (store[i] > store[i - 1]) - (store[i] < store[i - 1]);
    // Loop for slope changes
    if (newslope == -slope) {
      if (newslope > 0)
        valley++;
      slope = newslope;
    }
  }

  return valley;
}

测试代码。

void Vtest(const int *store, size_t count) {
  size_t n = Valley(store, count);
  printf("%zu %zu\n", count, n);
}

void Vtests(void) {
  int a1[] = { 9, 8, 7, 7, 8, 9 };
  Vtest(a1, sizeof a1 / sizeof a1[0]);
  int a2[] = { 9, 8, 7, 7, 8, 6, 9 };
  Vtest(a2, sizeof a2 / sizeof a2[0]);
  int a3[] = { 7, 8, 9, 8, 7 };
  Vtest(a3, sizeof a3 / sizeof a3[0]);
  int a4[] = { 3, 2, 1, 2, 3 };
  Vtest(a4, sizeof a4 / sizeof a4[0]);
  int a5[] = { 8, 7, 7, 8, 6 };
  Vtest(a5, sizeof a5 / sizeof a5[0]);
}

int main(void) {
  Vtests();
  return 0;
}

Output
6 1
7 2
5 0
5 1
5 1

答案 1 :(得分:0)

问题在于:

if((store[j-1] > store[j] )&&(store[j] < store[j+1]))

在两个比较中,您使用的是索引j,因此该程序仅查找长度为1的山谷。尝试此修改:

if((store[i-1] > store[i] )&&(store[j] < store[j+1]))

我也不确定,break;在这种情况下是正确的。但目前尚不清楚,如果3 1 2 3 - 一个(1)或两个(11 2),答案是正确的。从你的第一个例子我们可以看出,正确的答案是一个,但从定义来看并不明显。

答案 2 :(得分:0)

根据您定义谷值是否为给定点左/右的IMMEDIATE值,您可能需要调整所提供的Valley功能由chux如下:

size_t Valley (const int *store, size_t count) {

    ...

    i++;
    for (; i < count; i++) {
        int newslope = (store[i] > store[i - 1]) - (store[i] < store[i - 1]);
        if (newslope == -slope) {
            if (newslope > 0)
                valley++;
        }
        slope = newslope;
    }
    ...
}

<强>输出:

$ ./bin/valleyt
6 0
7 1
5 0
5 1
5 0

这是chux提供的答案的补充,输入数据正如他在答案中提供的那样。此代码仅将的定义限制为由3个相邻点创建。 (从负面到正斜率的变化的一般答案的特殊情况,其间插入等效点)