So I'm pretty new to C++ and I'm trying to generate Fibonacci numbers using recursion right? Except when I try to index to the next value I need to increase the index, and the function won't let me increase it.
How I know, is that I've run it in debug mode and stepped over the function - it continuously loops inside the fibGen function with i staying at a constant value of 1 (When I call fibGen in my main function the parameters are (startingSeq, 1, 13), where startingSeq is another vector with values {1,1}
The code builds and compiles fine, but when I run it I get a memory alloc error, which is obv caused by the infinite loop it seems to have.
What have I done wrong? Why doesn't the 'i' increase?
I've tried increasing i by having i++ inside the recursive fibGen call (in the else statement), I've tried having i++ outside the function call, and I've tried what's in there right now, where I have i+=1 and then pass i through.
Also I didn't have the 'return fibSeq' down the bottom originally because it doesn't make sense to have it there, but I put it in because vscode wouldn't compile without it in there, saying that it could never reach the end of fibGen (which makes sense now, and when this problem's fixed I think it can be removed, but at the moment it's just there so that the program will compile)
std::vector<int> fibGen(std::vector<int> fibSeq, int i, int max){
if(fibSeq[i] >= max){
return fibSeq;
}else{
fibSeq.push_back(fibSeq[i] + fibSeq[i-1]);
i+=1;
fibGen(fibSeq, i, max);
}
return fibSeq;
}
The output should be a vector containing the Fibonacci sequence, and I'm getting a mem alloc error (described above)
Actually, your code kind of works. You are just handling the vector of results sub-optimally. With your declaration:
std::vector<int> fibGen(std::vector<int> fibSeq, int i, int max)
you will always pass copies of the vector around (and you are never using the returned value). Instead, what you probably want to do is to work on the same data. To do this, use a reference to a vector (denoted by &). Then, you do not need to return anything:
void fibGen(std::vector<int>& fibSeq, int i, int max) {
if (fibSeq[i] >= max) {
return;
}
else {
fibSeq.push_back(fibSeq[i] + fibSeq[i - 1]);
i += 1;
fibGen(fibSeq, i, max);
}
}
void main(void) {
std::vector<int> fib = { 1, 1 };
fibGen(fib, 1, 34);
for (auto i : fib)
std::cout << i << std::endl;
}
So, I could not reproduce the error, until I realized that in your actual code, you were doing this instead of the code you posted:
std::vector<int> fibGen(std::vector<int> fibSeq, int i, int max){
if(fibSeq[i] >= max){
return fibSeq;
}else{
fibSeq.push_back(fibSeq[i] + fibSeq[i-1]);
i+=1;
fibGen(fibSeq, i, max);
}
}
In Visual Studio 2010, at least, it compiled fine, but threw an error at runtime, which I believe is what you described. So I'm going to assume I reproduced it.
The reason this is throwing an error is because you are invoking C++'s infamous undefined behavior. Undefined behavior in C++ permits anything to happen, like not failing to compile, but throwing a runtime error.
The fix is simple, really. You just need to return a value in all execution paths. Or, simply put, just do this:
std::vector<int> fibGen(std::vector<int> fibSeq, int i, int max){
if(fibSeq[i] >= max){
return fibSeq;
}else{
fibSeq.push_back(fibSeq[i] + fibSeq[i-1]);
i+=1;
return fibGen(fibSeq, i, max);
// Notice we are returning the value of the recursive call to fibGen().
// We can do this because we have already modified the vector the way we need to,
// so just simply returning the value is fine
}
}
Of course, you can take Nico Schertler's suggestion instead too:
void fibGen(std::vector<int>& fibSeq, int i, int max) {
if (fibSeq[i] >= max) {
return;
}
else {
fibSeq.push_back(fibSeq[i] + fibSeq[i - 1]);
i += 1;
fibGen(fibSeq, i, max);
}
}
It should be noted that not returning a value from a void function is not undefined behavior (that I'm aware), but actually how void's intended to work, so this function is fine not returning a value.
Related
While I was solving a problem in LeetCode, I found something very strange.
I have this line which I assume gives me a time limit exceeded error:
s.erase(i-k, k);
when I comment(//) this line, it doesn't show me time exceed error, but the strange part was, it has never executed even when i didn't comment it.
below is the entire code.
and Here is the problem link.
class Solution {
public:
string removeDuplicates(string s, int k) {
char prev = s[0];
int cnt = 1;
cnt = 1;
for(int i = 1; i < s.size() + 1; i++){
if(s[i] == prev){
cnt++;
} else {
if(cnt == k){
// when input is "abcd" it never comes to this scope
// which is impossible to run erase function.
s.erase(i-k, k);
i = 0;
}
if(i >= s.size()) break;
cnt = 1;
prev = s[i];
}
}
return s;
}
};
When Input is "abcd", it never even go to the if scope where 'erase' function is in.
Although 'erase' function never run, it still affect on the time complexity, and I can't get the reason.
Does anyone can explain this? or is this just problem of LeetCode?
Many online contest servers report Time Exceeding when program encounters critical error (coding bug) and/or crashes.
For example error of reading out of bounds of array. Or dereferencing bad (junk) pointers.
Why Time Exceeded. Because with critical error program can hang up and/or crash. Meaning it also doesn't deliver result in time.
So I think you have to debug your program to find all coding errors, not spending your time optimizing algorithm.
Regarding this line s.erase(i-k, k); - it may crash/hang-up when i < k, then you have negative value, which is not allowed by .erase() method. When you get for example i - k equal to -1 then size_t type (type of first argument of erase) will overflow (wrap around) to value 18446744073709551615 which is defnitely out of bounds, and out of memory border, hence your program may crash and/or hang. Also erase crashes when there is too many chars deleted, i.e. for erase s.erase(a, b) you have to watch that a + b <= s.size(), it is not controlled by erase function.
See documentation of erase method, and don't put negative values as arguments to this method. Check that your algorithm never has negative value i.e. never i < k when calling s.erase(i-k, k);, also never i-k + k > s.size(). To make sure there is no program crash you may do following:
int start = std::min(std::max(0, i-k), int(s.size()));
int num = std::min(k, std::max(0, int(s.size()) - start));
s.erase(start, num);
So I wrote this function in C++ which basically counts the maximum number in an array and then prints out the number of maximum numbers in the array. Here's the code of the function:
int Number_of_maxNum(vector<int> ar) {
int max=0;
int Number_of_Maxnum=0;
int d = ar.size();
for(int i=0;i<=d;i++){
if(ar[i]>max){
max=ar[i];
}
}
for(int j=0;j<=d;j++){
if(ar[j]==max){
Number_of_Maxnum++;
}
}
return Number_of_Maxnum;
}
Now this code however doesn't work for the following array as input:
{44, 53, 31, 27, 77, 60, 66, 77, 26, 36}
It should print out 2, but print out 1
If someone could please explain what's actually going on with that input that's giving 1 as an input, It would
You have Undefined Behaviour. Arrays/vectors are indexed from 0 to Size-1. So change i<=d to i<d. This is most likely the reason for this strange result. Because you read your vector outside of its boundary, resulting in (effectively) random last value (note that this is UB, it can even crash your entire program).
Another thing is that you should initialize int max = std::numeric_limits<int>::min(); unless you guarantee that all elements of ar are nonnegative.
Finally you can do entire processing in a single loop. Try this:
int Number_of_maxNum(const vector<int>& ar) // <--- do this to avoid vector copy
{
int currentMax = std::numeric_limits<int>::min();
int counter = 0;
for (int value : ar) // <--- do this to avoid error prone manual indexing
{
if (value == currentMax)
{
counter++;
}
else if (value > currentMax)
{
currentMax = value;
counter = 1;
}
}
return counter;
}
The accepted answer is certainly correct, as well as explaining why your code is wrong.
However, you should also consider using the STL to do what you need, like this
int Number_of_maxNum(const std::vector<int>& ar)
{
if (ar.size() == 0)
return 0;
auto max = *std::max_element(ar.cbegin(), ar.cend());
return std::count(ar.cbegin(), ar.cend(), max);
}
Some of the advantages are:
It's easier to read (and write, once you're used to it).
There's no issues with off-by-one errors (as you had in your solution).
No worrying about initializing the maximum number to be the smallest possible number.
One disadvantage of this solution is that it loops over the vector twice. This can still be avoided by using the appropriate algorithm, e.g.
int Number_of_maxNum(const std::vector<int>& ar)
{
return std::accumulate(ar.cbegin(), ar.cend(), 0,
[max = std::numeric_limits<int>::min()]
(int count, int num) mutable {
return num > max ? max = num, 1 : count + (num == max);
});
}
This is effectively the conventional for-loop, so I'm not sure there's much to be gained by writing it this way. Also, mutable lambdas could be considered a code smell. You should use your judgement to decide which technique to use, once you are aware of the options.
I got a weird compile error in the following code:
class Solution {
public:
int function(vector<int>& nums) {
//Did something
int len = nums.size();
int mid = len / 2;
if (nums[mid] < nums[0]) {
vector<int> newVec(nums.begin(), nums.begin() + mid);
return function(newVec);
}
else
return function(vector<int>(nums.begin() + mid + 1, nums.end()));
}
};
The error occured in:
return function(vector<int>(nums.begin() + mid + 1, nums.end()));
It seems to me that it works perfectly fine if I construct the vector first, then pass it to the function. Like what I did in the block under if:
vector<int> newVec(nums.begin(), nums.begin() + mid);
return function(newVec);
But if I combine these two steps, the error occurs. Could anyone please explain that for me? Many thanks~
=========================================================================
Edit:
The compile error was
no matching function for call to ‘Solution::function(std::vector<int>)’
vector<int>& nums is an lvalue reference. You must pass an lvalue. To allow both of these uses, change to vector<int> const &nums , which you should be doing anyway.
Consider redesigning function to accept an iterator range in the first place. Then you can run your whole algorithm just looking at a single buffer, instead of making heaps of copies of parts of it.
– M.M
I wanted to make a recursive function for the multiplication of the elements from an array
If my array has 1 element and v[1] is 1 ,the program wil show me 4703488
My question is why?
#include<iostream>
using namespace std;
int prod(int n,int v[100])
{
if(n)
{
return prod(--n,v)*v[n];
}
return 1;
}
int main()
{
int v[100],n,i=1;
cout<<"n=";
cin>>n;
for(i=1;i<=n;i++)
cin>>v[i];
cout<<prod(n,v);
return 0;
}
The culprit is the line return prod(--n,v)*v[n];. When you call --n as the function parameter, you don't know which value of n will be used in the v[n] part. This causes undefined behaviour. Since the value at 0 in your array is a garbage value, it might be using that value instead of using v[1] as you planned.
The correct way to write it would be return prod(n-1, v)*v[n]. To address the OP's query, a detailed explanation is shown below:
int prod(int n,int v[100]) // n has value 1 right now, when called
{
if(n) // since n has value 1, boolean condition is satisfied and control //flow goes inside the loop
{ // inside the loop part is being executed now
return prod(--n,v)*v[n]; // the value of n is decremented with --n. So n is now 0 (or could be 1). The value in v[n] is undefined, and it may be or 1. Garbage value at 0. Hence, output has garbage value
}
return 1;
}
It does not work properly because
return prod(--n,v)*v[n];
is undefined behaviour. What value of n is used for v[n]? The one received on the function call or the value of --n?
It seems that in your case v[n] uses the value of n after the decrementation (and it uses v[0] that is not initialized). But it could be the other way around (get v[n] before --n).
You can fix it this way:
return prod(n-1,v)*v[n];
this is not well defined:
return prod(--n,v)*v[n];
the reason is, the side-effect in --n is unsequenced with respect to the read of n in v[n]
I would write the function the following way
long long int prod( const int a[], size_t n )
{
if ( n == 0 ) return 0;
else return a[n-1] * ( n > 1 ? prod( a, n - 1 ) : 1 );
}
As for your code then this statement
return prod(--n,v)*v[n];
has unspecified order of evaluation of operands of operator *.
as the title explains this is a program to find lcm of numbers between 1 to 20. i found an algorithm to do this, here's the link
http://www.cut-the-knot.org/Curriculum/Arithmetic/LCM.shtml
there is a java applet on the webpage that might explain the algorithm better
Problem: i wrote the code compiler shows no error but when i run the code the program goes berserk, i guess may be some infinite loopig but i can't figure it out for the life of me. i use turbo c++ 4.5 so basically if anyone can look at the code and help me out it would be great . thanks in advance
Algorithm:
say we need to find lcm of 2,6,8
first we find the least of the series and add to it the number above it, i.e the series become
4,6,8
now we find the least value again and add to it the intitial value in the column i.e 2
6,6,8
so the next iteration becomes
8,6,8
8,12,8
10,12,8
10,12,16
12,12,16
14,12,16
14,18,16
16,18,16
18,18,16
18,18,24
20,18,24
20,24,24
22,24,24
24,24,24
as you can see at one point all numbers become equal which is our lcm
#include<iostream.h>
/*function to check if all the elements of an array are equal*/
int equl(int a[20], int n)
{
int i=0;
while(n==1&&i<20)
{
if (a[i]==a[i+1])
n=1;
else
n=0;
i++;
}
return n;
}
/*function to calculate lcm and return that value to main function*/
int lcm()
{
int i,k,j,check=1,a[20],b[20];
/*loading both arrays with numbers from 1 to 20*/
for(i=0;i<20;i++)
{
a[i]=i+1;
b[i]=i+1;
}
check= equl(a,1);
/*actual implementation of the algorith*/
while(check==0)
{
k=a[0]; /*looks for the least value in the array*/
for(i=0;i<20;i++)
{
if(a[i+1]<k)
{
k=a[i+1]; /*find the least value*/
j=i+1; /*mark the position in array */
}
else
continue;
}
a[j]=k+b[j]; /*adding the least value with its corresponding number*/
check= equl(a,1);
}
return (a[0]);
/*at this point all numbers in the array must be same thus any value gives us the lcm*/
}
void main()
{
int l;
l=lcm();
cout<<l;
}
In this line:
a[j]=k+b[j];
You use j but it is unitialized so it's some huge value and you are outside of the array bounds and thus you get a segmentation fault.
You also have some weird things going on in your code. void main() and you use cout without either saying std::cout or using namespace std; or something similar. An odd practice.
Also don't you think you should pass the arrays as arguments if you're going to make lcm() a function? That is int lcm(int a[], int b[]);.
You might look into using a debugger also and improving your coding practices. I found this error within 30 seconds of pasting your code into the compiler with the help of the debugger.
Your loop condition is:
while(n==1&&i<20)
So your equl function will never return 1 because if n happens to be 1 then the loop will just keep going and never return a 1.
However, your program still does not appear to return the correct result. You can split the piece of your code that finds the minimum element and replace it with this for cleanliness:
int least(int a[], int size){
int minPos = 0;
for(int i=0; i<size ;i++){
if (a[i] < a[minPos] ){
minPos = i;
}
}
return minPos;
}
Then you can call it by saying j = least(a, 20);. I will leave further work on your program to you. Consider calling your variables something meaningful instead of i,j,k,a,b.
Your equl function is using array indices from 0-20, but the arrays only have 1-19
j in lcm() is uninitialized if the first element is the smallest. It should be set to 0 at the top of the while loop
In the following code, when i=19, you are accessing a[20], which is out of the bounds of the array. Should be for(i=0;i<19;i++)
for(i=0;i<20;i++) {
if(a[i+1]<k)
You are not actually using the std namespace for the cout. this should be std::cout<<l
Your are including iostream.h. The standard is iostream without the .h, this may not work on such an old compiler tho
instead of hard-coding 20 everywhere, you should use a #define. This is not an error, just a style thing.
The following code does nothing. This is the default behavior
else
continue;