Time limit Exceeded in if-else - c++

Following is a function which change the value of array according to conditions:
If the difference between the array element and the next multiple of 5 is less than 3, round up to the next multiple of 5.
If the value of array element is less than 38, no rounding occurs.
Code:
vector<int> gradingStudents(vector<int> grades) {
int n = grades.size();
int i = 0;
while(i<n)
{
if(grades.at(i)<38)
{
i++;
}
else if( (grades.at(i)+1) % 5==0 )
{
grades.at(i) += 1;
i++;
}
else if( (grades.at(i)+2) % 5 == 0 && grades.at(i)>=38)
{
grades.at(i) += 2 ;
i++;
}
}
return grades;
}
Hackerrank site saying " Time Limit Exceeded". I don't understand how can time limit exceeded when there is no loop (except the essential while loop). If I remove i++ from each if statement and put it outside all if statements then its working fine, but the no. of statements remain same. please help me out

Time Limit Exceeded happens most often when the input size if very large, and/ or your logic takes a long time to process. One place I see in your code is, if there was a place where no if statements were satisfied, it will never be because i wont be incremented. Basically your loop will run forever.
You can either increment i in the end of the while loop (because anyway you will increment it),
while(i<n)
{
if(grades.at(i)<38)
{
}
else if( (grades.at(i)+1) % 5==0 )
grades.at(i) += 1;
else if( (grades.at(i)+2) % 5 == 0)
grades.at(i) += 2;
i++;
}
Or use a for loop,
for(int i = 0; i < n; i++)
{
if(grades.at(i)<38)
{
}
else if( (grades.at(i)+1) % 5==0 )
grades.at(i) += 1;
else if( (grades.at(i)+2) % 5 == 0)
grades.at(i) += 2;
}

Your code only increments i when one of the conditions is met. It is not clear why you are doing this, because no matter what case the number i is, in the next iteration you want to check the next number not i again. Your conditions are not complete, in the sense that for example i=42 does not match any condition. Hence, your loop will get stuck once it encounters the first such number.
Your current issue of an potentially infinte loop can be solved via
while(i<n)
{
if(grades.at(i)<38)
{
}
else if( (grades.at(i)+1) % 5==0 )
{
grades.at(i) += 1;
}
else if( (grades.at(i)+2) % 5 == 0)
{
grades.at(i) += 2 ;
}
i++;
}
Or the equivalent for loop.

Related

Loop does not continue correctly

I have been programming in C++ for the past 3 years, and I have always used the continue keyword in loops with success. But right now, a simple code of mine with continue is not working properly. Here is the code that is showing the problem:
int main()
{
int num = 2, result = 0;
while (num > 1 && num < 50)
{
if (num % 2 != 0)
{
result += num;
}
else
{
continue;
}
num++;
}
cout << "The result is: " << result << endl;
return 0;
}
As stated above, this does not print anything on the console. When I remove the else statement with continue in it, it successfully calculates the result and prints the said result. Does anyone have any idea why the given code is not working correctly (or why the loop in it does not break)? Any sound answer would be much appreciated.
Loop is indeed continuing (continue works properly) correctly
Initially, num = 2, so if condition fails and goes to else. So it will call continue. Then again the loop starts from the beginning with num = 2. This continues forever.
In short, num value is not changing and if condition always fails.
It's a very simple issue. Look at this block of code properly:
else
{
continue;
}
Due to continue, n++ is never called because due to the non-changing value of n, num % 2 != 0 is always false. This is resulting in an infinite loop.
So to fix this issue, just remove the above block of code:
#include <iostream>
int main()
{
int num = 2, result = 0;
while (num > 1 && num < 50)
{
if (num % 2 != 0)
{
result += num;
}
/*else
{
continue;
}*/
num++;
}
std::cout << "The result is: " << result << std::endl;
return 0;
}
Also, consider not using the following in your code:
using namespace std;
..as it's considered as a bad practice. For more info on this, look up why is "using namespace std" considered as a bad practice.
You just have to remove your else part because of no use and terminated cause of continue keyword.
int main()
{
int num = 2, result = 0;
while (num > 1 && num < 50)
{
if (num % 2 != 0)
{
result += num;
}
num++;
}
std::cout << "The result is: " << result << std::endl;
return 0;
}
Since continue is just a thinly disguised goto, rewriting the loop with explicit gotos might make it clearer:
start:
if (num > 1 && num < 50)
{
if (num % 2 != 0)
{
result += num;
}
else
{
goto start;
}
num++;
goto start;
}
Now you see clearly that num isn't incremented when num % 2 != 0 is false.
Just remove the else branch.

What is wrong with this loop-based function that returns the position of an element?

This function looks for an integer 'key' in a given vector from a position 'start'. It returns the position of key if it finds it. But if it does not find key, it should return -1.
However, it is only returning -1 as the output. The function works fine if the else statement is removed, but obviously I need it.
So what is wrong in this function? Please explain in simple terms, I am new to C++. Thank you for all your help.
int Sequential_Search(const vector<int>&v, int key, int start){
int result = 0;
int i;
for(i = start; i < v.size(); i++){
if(v[i] == key){
result = i;
}
else{
result = -1;
}
}
return result;
}
This is pretty easy to understand:
for(i = start; i < v.size(); i++){
if(v[i] == key){
result = i;
}
else{
result = -1;
}
}
Let's say your vector contains [1, 2, 3, 4] and you search 2 starting at index 0: here is what your code is doing:
i = 0: (v[i] : 1) == 2 -> false: result = -1
i = 1: (v[i] : 2) == 2 -> true: result = 1
i = 2: (v[i] : 3) == 2 -> false: result = -1
i = 3: (v[i] : 4) == 2 -> false: result = -1
When you've found your value, you still continue to read other value whereas you should stop.
Either using break or directly returning (return i) in the v[i] == key condition;
Either by checking result in the for condition (result == -1 && i < v.size())
Per comment remark: the case with break and return (the last one is not so hard):
int Sequential_Search(const vector<int>&v, int key, int start){
int result = -1; // important for 'break'
for(int i = start; i < v.size(); i++){
if(v[i] == key){
result = i; break;
}
}
return result;
}
int Sequential_Search(const vector<int>&v, int key, int start){
for(int i = start; i < v.size(); i++){
if(v[i] == key){
return i;
}
}
return -1;
}
When the loop finds the key, it sets result = i - but it doesn't stop looping. On the next iteration, v[i] is likely not equal to key, and the loop resets result to -1. The function returns -1 unless key just happens to match the last element.
The reason this is failing with the else statement is because there are many scenarios that the key would not be the last item in the vector.
If the key is 3 and the vector of ints if <1,3,4>, the for loop will loop through 3 times total. On the first iteration, it will go into the else statement since we did not find the key at the 0th index. Result is -1. On the second iteration, we found the key! Set result to i = 1. The third iteration will go into the else statement again, and set the result back to -1.
To fix this, you can use 'break' to leave the for loop as soon as you find result. Set result to I and then follow that with break; This will ensure that if the result is found, you will not go into the else statement again and reset it to -1.

how to cout the longest permanent sequence (increasing or decreasing) in c++?

I have to make a program in C++ what can manage a sequence optionally with from 2 to 1000 element. At the end the program has to cout the longest increasing or decreasing sequence's numbers of element.
Examples:
6;1;2;3;2;4;1; output: 3; (because: 1;2;3 is the longest with 3 elements)
6;4;3;1;5;2;1; output: 4; (because: 6;4;3;1 is the longest with 4 elements)
I tired the following code and kind of working. The problem is that it cant give the longest one it gives the number of last sequence every time.
Unfortunately i cant find the bug or problem. Could anyone help please?
int counting = 1;
int counting_max = 0, counting_min = 0;
for (int i = 1; i < n; ++i) {
if(block[i] < block[i+1]) {
if(block[i]-block[i-1]>0) {
counting++;
if(counting>counting_max) {
counting_max = counting;
}}
else {
counting = 1;
}
}
if(block[i] > block[i+1]) {
if(block[i]-block[i-1]<0) {
counting++;
if(counting>counting_min) {
counting_min = counting;
}}
else {
counting = 1;
}
}
}
if(counting_max >= counting_min) {
cout<< counting_max;
}
else {
cout<< counting_min;
}
return 0;}
In my code I didn't share the first part because i guess it works properly.
The first is just a while and for function to call for the elements number and after the exact numbers in a block.
So in my code the block contains the numbers.
In the code you have posted your outer loop creates an out-of-bounds access of the block array, since you're accessing block[i+1] in the loop. That's likely the reason that your code is producing correct answers in one direction and not in the other.
Beyond that there are some other problems you might come across with this approach:
You probably don't need to keep track of two separate counters if in the end you take the largest. You could just keep track of the largest sequence regardless of if it increases or decreases.
Since you test the relationships between three elements in the array to see if the sequence is increasing/decreasing, you will have to add extra logic to handle when the list has fewer than three elements.
You need to be careful of when the same number repeats, as this probably does not count as increasing or decreasing.
Here's a revised version that covers these points:
int counting = std::min(n, 1);
int counting_max = counting;
for (int i = 0; i < n - 1; ++i) {
if (
block[i] < block[i + 1] &&
(counting < 2 || block[i] > block[i - 1])
) {
counting++;
} else if (
block[i] > block[i + 1] &&
(counting < 2 || block[i] < block[i - 1])
) {
counting++;
} else if (block[i] == block[i + 1]) {
counting = 1;
} else {
counting = 2;
}
if (counting > counting_max) {
counting_max = counting;
}
}
cout << counting_max << "\n";
Try this alternate code: counting_max is finding longest ascending sequence and counting_min is finding longest descending sequence(by decrementing its loop counter) and at the end, we compare them to find the ultimate longest(supposing we have n-1 elements, if not change it accordingly)
for (int i=1,j=n-2; i<n && j>=0; ++i,--j) {
if (block[i] - block[i - 1]>0) {
counting++;
if (counting>counting_max)
counting_max = counting;
}
else
counting = 1;
if (block[j] - block[j + 1]>0) {
counting_back++;
if (counting_back>counting_min)
counting_min = counting_back;
}
else
counting_back = 1;
}
if (counting_max >= counting_min)
cout << counting_max;
else
cout << counting_min;

Return Statement positioning

I am writing some function which basically takes in input a range and a 1D vector. It looks at each number in the range of values given of the vector such that:
1) If the number to the left of it is 0 they swap positions.
2) If the number to the left of it is equal to it they add.
Now up till now this was good. The issue arises when I am trying to add return statements:
1) It should return True after all iterations are complete and at least one of the if conditions is entered in each iteration.
2) It should return false after all iterations are complete and none of the conditions are entered.
Now if I put these return statements in the loops they would terminate this function here but this is not desirable since it needs to go through all the iterations first. Is the current code comparable with this or do I need to redo it in a different manner ( if not where could the return statements go?)
bool proc_num(std::vector<int>&v, int LB, int UB) {
bool check = false;
for( int i=LB+2 ; i<UB; i++) {
for(int j = i-1; j>LB; j--) {
if(v[j] == 0){
v[j] = v[i];
check = true;
} else if(v[j] == v[i]) {
v[j]= v[j]+v[i];
v[i] = 0;
check = true;
}
}
}
return check;
}
You can simply add a boolean to make sure that at least one of the if conditions are entered.

C++ code for checking for prime numbers not working

I'm having trouble with this C++ code. The integer num is a number that I want to check if it is prime. However this program is always returning false. It's probably something simple but I can't find anything.
for(int i=2;i<num;i++){ //primes are allowed to be divided by 1 so we start at 2
if(num % i == 0){ //can be divided by a number other than itself or 1 so we trip out
return false;
} else if(i == num){ //if we've already done checks as high as possible and not tripped out yet then report success
return true;
}
}
i == num will never occur, since your loop condition is i<num. Try:
for(int i=2;i<num;i++){ //primes are allowed to be divided by 1 so we start at 2
if(num % i == 0){ //can be divided by a number other than itself or 1 so we trip out
return false;
} else if(i == num-1){ //if we've already done checks as high as possible and not tripped out yet then report success
return true;
}
}
As pointed out below, the else condition here is redundant, and you only need to check from 2 to sqrt(num) - since the remaining factors have already been checked.
There are more improvements that can be made depending on how complex you want to make the problem. Most methods in reality use probabilistic algorithms.
You don't have to check every number, as a lot of them can easily be ruled out. For example, after checking that num is not divisible by 2, you can skip all other even numbers. That saves you half the tests.
We also definitely know that any other factor must be less than num/2 (or really sqrt(num), but that is harder to compute). That knowledge can save us another half of the tests.
So now we have:
if (num % 2 == 0)
return false;
for(int i = 3; i < num / 2; i += 2){
if(num % i == 0){ //can be divided by a number other than itself or 1 so we trip out
return false;
}
}
// arriving here we have found no factors, so it must be a prime
return true;
A small optimization for Will Ness's code, just calculate the sqrt of the number outside the for. The condition check executes many times and has no sense to calculate sqrt each time.
if( num == 2 ) return true;
if( num < 2 || num % 2 == 0 ) return false;
int sqrt = sqrt(num);
for( int i=3; i<=sqrt; i+=2 ){
if(num % i == 0){
return false;
}
}
return true;
So far I think that this is the most efficient way!
bool CheckPrime(int num) {
bool yayornay = true;
for(int i = 2; i < num; i++) {
if(num % i == 0) {
yayornay = false;
break;
}
}
return yayornay;
}
bool isprime(int n)
{
if(n<2) return false;
if(n==2)return true;
for(int i=2;i<=sqrt(n);i++)
if(n%i==0) return false;
return true;
}
Here's the proper way to write what you meant:
int i=2; // move declaration out
for(/*int i=2*/;i<num;i++){
if(num % i == 0){
return false;
} // else // and the final test too
}
if(i == num){
return true;
}
But that's not efficient. You only have to check for i's not exceeding of sqrt(num). Plus, if you check num%2, there's no more need to check any other even numbers, so you can use an increment of 2. Or you can even count by 6:
if( num == 2 || num == 3 ) return true;
if( num < 2 || num % 2 == 0 || num % 3 == 0 ) return false;
for( int i=5, j=7, lim=sqrt(num); i<=lim; i+=6, j+=6 ){
if( num % i == 0 || num % j == 0 ){
return false;
}
}
return true;
(notice: this is more efficient than another answer here, which says it's an "optimization" of an initial version of this answer).