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.