简体   繁体   中英

How can I reduce the time complexity of an algorithm in c++?

The following code takes in an integer t and then takes in 3 more integers t times and returns the maximum number of times you can subtract 1 from two different integers at the same time, whereas the program stops when there is only 1 integer above 0 remaining. I have solved the problem, but I want to reduce the time complexity of the code and I don't know how.

#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;
    }
}
}

How can I get the same output without using all these loops that increase the time complexity?

Edit: I don't want my code re-written for me, this is homework and all I want are tips and help so I can reduce the time complexity, which I don't know how to do.

Edit 2: In my algorithm, I sort the 3 numbers in ascending order, then I use a while loop to check if the smallest number (s/arr[0]) is > 0. After that, I use two more while loops to alternate between the largest and medium-size numbers (l/arr[2] and m/arr[1] respectively) and decrement from both variables s and l or m (alternating). When s becomes 0, that will mean I can just decrement l and m till one of them equals 0, and then I print the count variable (I increment count every time I decrement two of the variables).

I'm not sure I understood the problem correctly but if you want to know the maximum number of times you can subtract 1 until hitting zero from two elements in a three element set, I believe the answer should be the same as finding the median element of the set. For example, if I have the set

10 20 30

The maximum amount of times I can subtract 1 is 20, if I always chose to subtract from the subset {20, 30} , while the minimum would be 10 , if I always choose to subtract from the subset {10, 20} .

Hope this helps! (Assuming I didn't totally misunderstand the question ^_^ ")

Edit:

After the clarifying comment, I believe all you need to do is find the minimum between the sum of the non-maximum elements and the maximum element. Consider the following examples:

If you are given the set {80, 10, 210} for example, the answer to your problem is 90, because we can subtract 10 from the subset {80, 10 }, leaving us with {70, 0, 210} where we can further subtract 70 from the subset {70, 210} , leaving us with {0,0,140} , where we can perform no more operations. We have performed 80+10 = 90 subtractions by 1 In this case, max = 210 and min+med = 90

On the other hand, the consider the set {2,2,2} . We can subtract 2 from the subset {2,2} , leaving us with {0,0,2} , where we can perform no more operations. In this case, we have performed 2 subtractions by 1 Max = 2 and min+med = 4

Last example: consider the set {2,3,5} . We can subtract 2 from the subset {2,3} , leaving us with {0,1,5} , where we can the subtract 1 from the subset {1,5} , resulting in {0,0,4} , where we can perform no more operations. In this case, we have performed 2+3=5 subtractions by 1 Max = 5 and min+med = 5

If you continue performing examples in this vein, you should be able to convince yourself that the solution is always going to be min(max, min+median) .

Assuming your code is correct, you can examine exactly what your loops are doing, and look at them more mathematically.

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;
}

Assuming your program was correct,t his produces the same results for all inputs I tried.

Im not sure if i understood the problem correctly. But if i did you could optimize the algorithem the following way:

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;

You would have to this t times and then sum the count variables, resulting in a complexity of t.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM