【问题标题】:Is there any way to merge two (or multiple) for loops to reduce the overall time complexity?有没有办法合并两个(或多个)for循环以降低整体时间复杂度?
【发布时间】:2021-05-05 02:36:26
【问题描述】:

实际上我已经解决了比较计算结果并返回最小值的问题。虽然我成功实现了逻辑并很好地执行了代码,但未能降低时间复杂度。

#include<iostream>
#include<algorithm>
#include<climits>

using namespace std;

int checkMinimum(int array[], int index)
{
  int result = INT_MAX;

  for(int i = 0; i < index; ++i)
    for(int j = 0; j < index; ++j)
      if(i != j && (min(result, ((array[i] & array[j]) ^ (array[i] | array[j]))) < result))
        result = min(result, ((array[i] & array[j]) ^ (array[i] | array[j])));

  return result;
}

void getMinimum()
{
  int index;
  cin >> index;
  int array[index];

  for(int i = 0; i < index; ++i)
    cin >> array[i];

  cout << checkMinimum(array, index) << endl;
}

int main()
{
  int limit;
  cin >> limit;
  while(limit--)
    getMinimum();

  return 0;
}

在研究了 for 循环并尝试将它们合并在一起之后根本无济于事,因为很难将循环的条件满足为一个。

#include<iostream>
#include<algorithm>
#include<climits>

using namespace std;

int checkMinimum(int array[], int index)
{
  int result = INT_MAX;

  for(int i = 0, j = index - 1; i != j; ++i, --j)
    if((min(result, ((array[i] & array[j]) ^ (array[i] | array[j]))) < result))
      result = min(result, ((array[i] & array[j]) ^ (array[i] | array[j])));

  return result;
}

void getMinimum()
{
  int index;
  cin >> index;
  int array[index];

  for(int i = 0; i < index; ++i)
    cin >> array[i];

  cout << checkMinimum(array, index) << endl;
}

int main()
{
  int limit;
  cin >> limit;
  while(limit--)
    getMinimum();

  return 0;
}

那么我怎样才能降低这个时间复杂度呢?

【问题讨论】:

  • 如果您需要对每个(i,j) 对进行操作,那么您需要进行index^2 操作。任何表达这一点的方法都不会改变这一事实。 (如果您要解决的问题有不同的解决方案,那完全是另一个问题。)
  • 时间复杂度也可能与编译器生成的实际代码在特定硬件平台上执行所花费的时间无关。您不会在大型数据集上战胜二次(或更糟)复杂性,但是即使它们是二次的,小型数据集的性能也可能接近硬件限制,并且这种性能有时会使不太复杂的算法在以某种方式导致的结果相形见绌更糟糕的代码。如今,算法的复杂性需要查看缓存位置 - 没有它,您就是在浪费时间。
  • 我在这段代码中在底层看到的最大问题是转发惩罚——在外观中不断使用结果变量正在扼杀性能。我看到的另一个问题是,这对我来说看起来像是一个 N*log(N) 算法,但它是以最天真的方式实现的,将它变成 N^2。提示:minimum 意味着排序会有所帮助,为此您可以以一种考虑二进制操作的方式表示数据,这样您就不必为每个元素执行 N 次。
  • 我要改进它的步骤:弄清楚可以使用哪种比较操作对数组进行排序(可能在每个数组副本上以不止一种方式),以便某些操作只执行一次在这些数组的第一个元素上将产生您想要的最小值。如果这个问题来自一个竞争性的编程网站,那么我相信你需要一个 NlogN 解决方案,因为其他一切都是微不足道的。
  • 所有数字都是正数还是负数?

标签: c++ algorithm for-loop data-structures time


【解决方案1】:

(array[i] &amp; array[j]) ^ (array[i] | array[j])等价于array[i] ^ array[j]&amp;^|都是按位运算,写一位真值表)。

要最小化异或,最重要的是高位一致。假设输入有几个数字0xxxx 和几个数字1xxxx。尝试与0xxxx1xxxx 配对是没有意义的;即使xxxx部分完全相同,异或是10000,而任何0xxxx与任何0xxxx的异或,或任何1xxxx与任何1xxxx的异或最多为@ 987654336@,小于10000

在每个组中的下一位和之后的位重复此逻辑,可以显示具有最小 XOR 的对按排序顺序彼此相邻出现。因此,您可以对数组进行排序并计算n − 1 相邻对的最小值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    • 2019-11-29
    • 1970-01-01
    • 2011-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多