【问题标题】:How can I reduce the time complexity of an algorithm in c++?如何降低 C++ 中算法的时间复杂度?
【发布时间】:2019-12-05 16:45:20
【问题描述】:

以下代码接受一个整数 t,然后再接受 3 个整数 t 次,并返回您可以从两个不同的整数中减去 1 的最大次数同时,当只剩下 1 个大于 0 的整数时程序停止。问题已经解决了,但是想降低代码的时间复杂度不知道怎么做。

#include <bits/stdc++.h>

using namespace std;

int main() {
long long t, r, g, b, arr[1000], count = 0;
bool isMax=true;
cin >> t;

for (long long i = 0; i < t; i++) {
    cin >> r >> g >> b;
    arr[0] = r;
    arr[1] = g;
    arr[2] = b;
    for (long long j = 0; j < 3; j++) {
        for (long long k = 0; k < 2; k++) {
            if (arr[k] > arr[k + 1]) {
                long long a = arr[k];
                long long b = arr[k + 1];
                arr[k] = b;
                arr[k + 1] = a;
            }
        }
    }
    count = 0;
    if (arr[2] == 1) {
        cout << 1 << endl;
    } else if (arr[0] + arr[1] <= arr[2]) {
        cout << arr[0] + arr[1] << endl;
    } else {
        while (arr[0] > 0) {
            while (isMax && arr[0] > 0) {
                arr[2]--;
                arr[0]--;
                count++;
                if (arr[2] < arr[1]) {
                    isMax = false;
                }
            }
            while (!isMax && arr[0] > 0) {
                arr[1]--;
                arr[0]--;
                count++;
                if (arr[1] < arr[2]) {
                    isMax = true;
                }
            }
        }
        while (arr[2] > 0 && arr[1] > 0) {
            arr[2]--;
            arr[1]--;
            count++;
        }
        cout << count << endl;
    }
}
}

如何在不使用所有这些增加时间复杂度的循环的情况下获得相同的输出?

编辑:我不希望我的代码为我重写,这是家庭作业,我想要的只是提示和帮助,这样我就可以降低时间复杂度,我不知道该怎么做。

编辑 2:在我的算法中,我按升序对 3 个数字进行排序,然后使用 while 循环检查最小数字 (s/arr[0]) 是否 > 0。之后,我再使用两个while 循环在最大和中等大小的数字之间交替(分别为 l/arr[2] 和 m/arr[1])并从变量 s 和 l 或 m 中减少(交替)。当 s 变为 0 时,这意味着我可以将 l 和 m 递减,直到其中一个等于 0,然后我打印 count 变量(我每次递减两个变量时递增 count)。

【问题讨论】:

  • 听起来像家庭作业?
  • 而不是向我们展示代码并要求我们为您重写它——因为这是一个关于算法和复杂性的问题——也许你可以向我们描述你的算法并询问如何制作的技巧它更优化?就目前而言,这看起来像是“为我编写代码”的家庭作业问题。
  • 我不想为我重写代码,我想知道如何降低时间复杂度。
  • 想一想:如何才能完全删除最内层的循环,在每次迭代中只增加/减少计数器?
  • 您可以通过使用不同的算法来降低复杂性。相同的算法具有固定的复杂度(假设实现没有搞砸)

标签: c++ algorithm time-complexity


【解决方案1】:

我不确定我是否正确理解了这个问题。但如果我这样做了,你可以通过以下方式优化算法:

int count = 0;
int a = 20, b = 10, c = 21;
sort(a, b, c); // Function that sorts the numbers, so that a is the smallest and c is the largest
count += a;  // count = 10
c -= a;  // a = 10, b = 20, c = 11
if(c < b) {
    float diff = b - c; // diff = 9
    float distribute = diff / 2; // distribute = 4.5
    count += b - ceil(distribute); // count = 25
}
else count += b;

你将不得不这 t 次,然后对计数变量求和,导致复杂度为 t。

【讨论】:

    【解决方案2】:

    假设您的代码是正确的,您可以准确地检查您的循环在做什么,并以更数学的方式看待它们。

    if ( arr[2] == 1 ) {
        cout << 1 << endl;
    } else if ( arr[0] + arr[1] <= arr[2] ) {
        cout << arr[0] + arr[1] << endl;
    } else {
        while ( arr[0] > 0 ) {
            if ( arr[2] > arr[1] ) {
                long long min = std::min( std::min( arr[0], arr[2] ), arr[2] - arr[1] + 1 );
                arr[0] -= min;
                arr[2] -= min;
                count += min;
            } else {
                long long min = std::min( std::min( arr[0], arr[1] ), arr[1] - arr[2] + 1 );
                arr[0] -= min;
                arr[1] -= min;
                count += min;
            }
    
        }
        count += std::min( arr[2], arr[1] );
        cout << count << endl;
    }
    

    假设你的程序是正确的,他对我尝试的所有输入产生相同的结果。

    【讨论】:

      【解决方案3】:

      我不确定我是否正确理解了这个问题,但是如果您想知道最大次数可以减去 1 直到从三元素集中的两个元素中达到零,我相信答案应该是相同的就像找到集合的中值元素一样。例如,如果我有一套

      10 20 30

      如果我总是选择从子集{20, 30} 中减去,我可以减去 1 的 最大 次是 20,而 最小 将是 10 ,如果我总是选择从子集中减去{10, 20}

      希望这会有所帮助! (假设我没有完全误解这个问题^_^“)

      Edit:

      在澄清评论之后,我相信您需要做的就是找到非最大元素的总和与最大元素之间的最小值。考虑以下示例:

      例如,如果给定集合 {80, 10, 210},则问题的答案是 90,因为我们可以从子集 {80, 10} 中减去 10,留下{70, 0, 210},我们可以进一步从子集中减去 70子集{70, 210},留给我们{0,0,140},我们不能再执行任何操作。 我们执行了 80+10 = 90 次减法 1 在这种情况下,max = 210 和 min+med = 90

      另一方面,考虑集合{2,2,2}。我们可以从子集{2,2} 中减去 2,留下{0,0,2},我们不能再执行任何操作。 在这种情况下,我们执行了 2 次减法 1 Max = 2 和 min+med = 4

      最后一个例子:考虑集合{2,3,5}。我们可以从子集{2,3} 中减去 2,留下{0,1,5},我们可以从子集{1,5} 中减去 1,得到{0,0,4},我们不能再执行任何操作。 在这种情况下,我们执行了 2+3=5 减法 1 Max = 5 和 min+med = 5

      如果您继续以这种方式执行示例,您应该能够说服自己解决方案始终为 min(max, min+median)

      【讨论】:

      • 你看我一开始也是这么想的,但事实证明 10 20 30 的最大值是 30 因为你可以从子集 {10, 30} 中减去 10 次,那么数组将是 { 0, 20, 20} 和 u 可以从子集 {20, 20} 中减去 20 次,将 20 与 10 相加得到 30。
      • @AlhuthaliHumaid -- 看看你是如何表达你的评论的。是否需要循环才能确定值为 30?还是只是一些直觉思维?
      • @AlhuthaliHumaid 我已根据您的评论编辑了我的答案
      猜你喜欢
      • 1970-01-01
      • 2014-04-21
      • 1970-01-01
      • 2012-07-28
      • 2011-06-15
      • 2021-03-30
      • 2023-03-06
      • 2016-01-08
      相关资源
      最近更新 更多