【问题标题】:find a pair of elements with the same value with the largest distance between the elements找到具有相同值且元素之间距离最大的一对元素
【发布时间】:2020-07-23 07:18:15
【问题描述】:

我有一个'N'双值数组,但我试图找到一对相同的元素,它们之间的距离最远。

举个例子;

{1, 3, 5, 3, 7, 9, 10, 5, 6, 7, 1}
Output: (1,1) has the largest distance between them 

有没有人对我如何处理这个问题有任何想法,因为我完全被难住了?

提前致谢!

【问题讨论】:

  • 更像是“找到一对具有相同值的元素”
  • 比较 1st 和 2nd, 3rd, 4th ....,然后 2nd 和 1st, 3rd, 4th,... 然后 3rd 和 1st, 2nd, 4th,... 等等。如果相同的值,评价距离。这是一个简单的解决方案,效率不高,但足以让你摆脱“我完全被难住了”。
  • 知道我将如何去做吗?
  • Adam,你肯定已经为此编写了一些代码。发布您尝试改进问题的内容。
  • 我真的一无所有,这就是我来这里寻求帮助的原因

标签: c arrays runtime element


【解决方案1】:

代码可以尝试每一对。

但关键是要避免测试小于当前已知最大距离的对。

size_t max_common_element_distance(size_t n, const double *x) {
  size_t max_distance = 0;
  for (size_t i = 0; i < n; i++) {
    for (size_t j = i+1; j + max_distance < n; j++) {
      // test beyond the max distance for a better one.
      if (x[i] == x[j + max_distance]) {
        max_distance = j + max_distance - i;
        // Perhaps record other info here, like the index of the 2 elements 
        // to use as part of the "Output: ..." report
      }
    }
  }
  return max_distance;
}

更好的代码会以相反的方向运行j 循环,从n-max_distance-1 向下到i+1。但是听起来 OP 需要一个好的而不是那么复杂的起点。


Deeper:上面的复杂度顺序是O(n*n)。一个O(n*log(n)) 的解决方案是通过形成一个(值,索引)对列表,按值排序(然后按关系上的索引),然后遍历列表一次以找到最大索引差异。

#include <stdio.h>
#include <stdlib.h>

typedef struct {
  double value;
  size_t index;
} pair;

int pair_cmp(const void *a, const void *b) {
  const pair *pa = a;
  const pair *pb = b;
  int cmp = (pa->value > pb->value) - (pa->value < pb->value);
  if (cmp == 0) {
    cmp = (pa->index > pb->index) - (pa->index < pb->index);
  }
  return cmp;
}

size_t max_common_element_distance(size_t n, const double *x) {
  size_t max_distance = 0;
  if (n > 0) {
    pair y[n];
    for (size_t i = 0; i < n; i++) {
      y[i].index = i;
      y[i].value = x[i];
    }
    qsort(y, n, sizeof y[0], pair_cmp);
    size_t from, to;
    size_t first = 0;
    for (size_t i = 1; i < n; i++) {
      if (y[i].value == y[first].value) {
        size_t distance = y[i].index - y[first].index;
        if (distance > max_distance) {
          max_distance = distance;
          from = y[first].index;
          to = y[i].index;
        }
      } else {
        first = i;
      }
    }
    if (max_distance > 0) {
      printf("from:%zu to:%zu dist:%zu val:%g\n", from, to, max_distance, x[from]);
    }
  }
  return max_distance;
}

int main() {
  double val[] = {1, 3, 5, 3, 7, 9, 10, 5, 6, 7, 1};
  size_t n = sizeof val/ sizeof val[0];
  max_common_element_distance(n, val);
}

输出

from:0 to:10 dist:10 val:1

【讨论】:

    【解决方案2】:

    这是我的五分钱。:)

    #include <stdio.h>
    
    int main(void) 
    {
        int a[] = { 1, 3, 5, 3, 7, 9, 10, 5, 6, 7, 1 };
        const size_t N = sizeof( a ) / sizeof( *a );
    
        size_t first = 0, last = 0;
    
        for ( size_t i = 0; i < N - ( last - first ); i++ )
        {
            size_t j = N;
            while ( --j != i && a[j] != a[i] );
    
            if ( j != i )
            {
                if ( last - first < j - i )
                {
                    first = i;
                    last = j;
                }
            }
        }
    
        if ( first != last )
        {
            printf( "%d: ( %zu, %zu )\n", a[first], first, last );
        }
    
        return 0;
    }
    

    程序输出是

    1: ( 0, 10 )
    

    如果包含以下条件,循环可以更加优化

        if ( i == 0 || a[i] != a[last] )
    

    跳过已经考虑过的值。

    这是带有这个 if 语句的程序。

    #include <stdio.h>
    
    int main(void) 
    {
        int a[] = { 1, 3, 5, 3, 7, 9, 10, 5, 6, 7, 1 };
        const size_t N = sizeof( a ) / sizeof( *a );
    
        size_t first = 0, last = 0;
    
        for ( size_t i = 0; i < N - ( last - first ); i++ )
        {
            if ( i == 0 || a[i] != a[last] )
            {
                size_t j = N;
                while ( --j != i && a[j] != a[i] );
    
                if ( j != i )
                {
                    if ( last - first < j - i )
                    {
                        first = i;
                        last = j;
                    }
                }
            }           
        }
    
        if ( first != last )
        {
            printf( "%d: ( %zu, %zu )\n", a[first], first, last );
        }
    
        return 0;
    }
    

    这是插入测试输出以显示内部循环执行频率的同一程序。

    #include <stdio.h>
    
    int main(void) 
    {
        int a[] = { 1, 1, 1, 1, 2, 2, 2, 2, 2, 3 };
        const size_t N = sizeof( a ) / sizeof( *a );
    
        size_t first = 0, last = 0;
    
        for ( size_t i = 0; i < N - ( last - first ); i++ )
        {
            if ( i == 0 || a[i] != a[last] )
            {
                printf( "Inner loop for %d\n", a[i] );
    
                size_t j = N;
                while ( --j != i && a[j] != a[i] );
    
                if ( j != i )
                {
                    if ( last - first < j - i )
                    {
                        first = i;
                        last = j;
                    }
                }
            }           
        }
    
        if ( first != last )
        {
            printf( "%d: ( %zu, %zu )\n", a[first], first, last );
        }
    
        return 0;
    }
    

    程序输出是

    Inner loop for 1
    Inner loop for 2
    2: ( 4, 8 )
    

    所以内部循环只执行了两次。

    【讨论】:

    • 这个输出 (0,10) 但我试图找到一对相同的元素来找到它们之间的距离
    • @Adam 输出显示重复的值以及重复该值的索引。 1: ( 0, 10 )。所以差异 10 - 0 给出了数组中的最大距离。拥有第一个和最后一个值,您可以输出您想要的内容。有什么问题?!
    • 我很抱歉我弄错了我现在明白了非常感谢您的帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 2017-01-29
    • 2021-11-03
    相关资源
    最近更新 更多