recursive binary search in c++ using a bool function - c++

I have an school assignement that requires me to create a recursive Binary search function. I'm not allowed to change the function signature.
My experience with pointer isn't the best and i think my problem lies there.
I get an Stackoveflow but i dont really understand way
bool contains(const int* pBegin, const int* pEnd, int x)
{
int length = pEnd - pBegin;//gives me the length of the array
const int* pMid = pBegin + (length / 2);
if(length == 1)
{
if(*pMid != x)
return false;
return true;
}
else if(x < *pMid)
return contains(pBegin, pMid-1, x);
else
return contains(pMid, pEnd, x);
}
void main(){
setlocale(LC_ALL, "swedish");
int arr[10];
for(int i = 0; i < 10; ++i)
arr[i] = i;
bool find = contains(&arr[0], &arr[10], 3);//arr[10] points to the index after the array!
cout <<"found = "<< find << endl;
system("pause");
}
Can somebody please explain to me what I'm doing wrong, and how i could do it in a better way?

Stack overflow is due to too deep recursion.
Its unlikely your array is large enough to really be a problem, so what you have is unbounded recursion ... contains() keeps calling itself and fails to detect this.
Look at how this is possible, and add assertions.
Your code assumes
pEnd > pBegin
Your code doesn't handle this possibility.
#include <assert.h>
bool contains( ... )
{
assert(pBegin > pEnd);
...
Now, it will abort if this assumption is incorrect.
There are two possibities for (pEnd > pBegin) being false, namely "<" or "==".
What does your code do in these two cases?
Spoiler below..
Length can be zero and isn't handled.

Related

Error: Char 34: runtime error: addition of unsigned offset to 0x603000000070 overflowed to 0x60300000006c (stl_vector.h) (C++)

I have been trying to solve the sorted Squares leetcode problem (https://leetcode.com/explore/learn/card/fun-with-arrays/521/introduction/3240/), and I am mostly through it. However, I get the above error. Following is my code
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int start = 0;
int end = nums.size()-1;
vector<int> final(nums.size());
int finalIdx = final.size()-1;
int sqr = 0;
while(start<=end){
if (abs(nums[start])<abs(nums[end])){
sqr = nums[end]*nums[end];
final[finalIdx] = sqr;
finalIdx--;
end--;
}
if (abs(nums[start])>abs(nums[end])){
sqr = nums[start]*nums[start];
final[finalIdx] = sqr;
finalIdx--;
start++;
}
else if(abs(nums[start])==abs(nums[end])){
sqr = nums[end]*nums[end];
final[finalIdx] = sqr;
finalIdx--;
final[finalIdx] = sqr;
finalIdx--;
start++;
end--;
}
return final;
}
}
};
The issue lies in my loop condition I believe. When I change the condition to start<end, I have no compile error, but the first element of the output array (final) is always 0, which I assume is by default. However, when I try to do start<=end in order to add a condition that handles the start==end case, I get the above error. I would like to understand why this is happening so I can rectify the issue. Thanks!
First, that's not a "compile error" ; it's a runtime error (and the error message reported says as much.
That said, the issue stems from the condition of start <= end landing on the = part of that condition. Eventually that is guaranteed to happen, save for one very specific set of circumstances:
start = (end-1)
abs(num[start]) == abs(num[end])
When that happens, your code will dump two values to the output vector, and both increment start and decrement end. The start and end indexes effectively swap values, the while condition is no longer true, and the loop will now cleanly exit.
In all other circumstances start and end will eventually land on the same index. When that happens your dual-push logic will dump the same value twice into the target vector, and that is where the issue manifests. There is only one value left to push (and start and end both reference it by index). Therefore you're going to push one more value into your target vector than you have space for, and the runtime exception ensues.
The fix is simple. Stop trying to be smart about short circuiting in three different conditions when in reality you only need one and a master-else. The computational requirements are the same no matter what, and in the end all you need is this:
class Solution
{
public:
std::vector<int> sortedSquares(std::vector<int> const &nums)
{
std::vector<int> final(nums.size());
int start = 0;
int end = nums.size()-1;
int finalIdx = final.size()-1;
while(start<=end)
{
if (abs(nums[end]) < abs(nums[start]))
{
final[finalIdx--] = nums[start]*nums[start];
++start;
}
else
{
final[finalIdx--] = nums[end]*nums[end];
--end;
}
}
return final;
}
};
If you really want all three conditions in your code, it is possible, but not warranted, and the special case circumstances don't justify doing it. Regardless, see below:
class Solution
{
public:
std::vector<int> sortedSquares(std::vector<int> const &nums)
{
std::vector<int> final(nums.size());
int start = 0;
int end = nums.size() - 1;
int finalIdx = final.size() - 1;
while (start <= end)
{
if (abs(nums[start]) < abs(nums[end]))
{
final[finalIdx--] = nums[end] * nums[end];
end--;
}
else if (abs(nums[end]) < abs(nums[start]))
{
final[finalIdx--] = nums[start] * nums[start];
start++;
}
else // !(a<b || b<0) implies (a == b)
{
int sqr = final[finalIdx--] = nums[end] * nums[end];
if (end != start)
{
final[finalIdx--] = sqr;
}
--end;
++start;
}
}
return final;
}
};

C++ There is a bool return type function returning (24) here

First of all sorry for too much code
Here there is a vector (teamNum) with type class, the class contain a vector (player) with type struct, it is a little complicated, but here in this function I need to check if there is a player in teamNum which contain tName equal to _tname (function parameter) contain (the player) pID equal to _pID (function parameter)
bool thereIsSimilarID(string _tname, int _pID)
{
for (int i = 0; i < teamNum.size(); i++)
{
if (teamNum[i].tName == _tname)
{
for (int j = 0; j < teamNum[i].player.size(); j++)
{
if (teamNum[i].player[j].pID == _pID)
return true;
}
}
else if (i == (teamNum.size() - 1))
{
return false;
}
}
}
And in the main
int main()
{
cout << "\n" << thereIsSimilarID("Leverpool", 1) << endl;
}
The output is 24 !!!!!
(good note that this happen just when the team (Leverpool) is the last team in the vector teamNum)
Again sorry for too much code but I need to know the bug not only fix the problem I need to learn from you
You encountered undefined behaviour.
If you take the if (teamNum[i].tName == _tname)-branch on the last element, but find no player with the correct pID, you don't return anything. Which means, that the return value is whatever random value is currently in the memory location that should hold the return value. In your case it happens to 24. But theoretically, everything could happen.
The same problem occurs when teamNum is empty.
The solution is to make sure to always return a value from a function (except if it has return type void of course):
bool thereIsSimilarID(string _tname, int _pID)
{
for (int i = 0; i < teamNum.size(); i++)
{
// In this loop return true if you find a matching element
}
// If no matching element was found we reach this point and make sure to return a value
return false;
}
You should take a look at your compiler settings and enable all the warnings. And often it's good to let it treat certain warnings as errors.

Function that checks if an array is sorted

So I'm just a beignner programmer when it comes to C++, and I have to write a function that checks if an int array is sorted using pointers (no index notations allowed), and here's what I have so far:
bool isSorted(const int *ar, int size) {
bool sorted = true;
const int *ptr1, *ptr2, *ptr3;
ptr1 = ar;
ptr2 = ar+1;
ptr3 = ar+size;
for (ptr1; ptr1 < ptr3; ptr1++) {
for (ptr2; ptr2 < ptr3; ptr2++) {
if (*ptr1 > *ptr2) {
sorted = false;
}
}
}
return sorted;
}
However, I can't seem to get it to work as it always returns true regardless of whether the array is sorted or not. Any help is appreciated, thanks.
"The more you overthink the plumbing, the easier it is to stop up the
drain" -- Scotty, Star Trek III.
You are making this much more complicated than it has to be.
Ask yourself a basic question: what is a sorted array?
Answer: an array in which each successive element is not less than its preceding element.
Therefore: to check if the array is sorted, just look for an element that's less than its previous element. If you found one, the array is not sorted. If you couldn't find one, the array must be sorted.
bool isSorted(const int *ar, int size) {
if (size == 0)
return true; // Edge case
int previous_value= *ar;
while (size)
{
if (*ar < previous_value)
return false;
previous_value= *ar;
++ar;
--size;
}
return true;
}
No index notations, just a single pointer. No need to do any kind of a nested search, etc... If you want to use only pointers, you could do this:
bool isSorted(const int *ar, int size) {
const int *previous_value=ar;
while (size)
{
if (*ar < *previous_value)
return false;
previous_value= ar;
++ar;
--size;
}
return true;
}
Actually, I like this version even better.
You should keep ptr2 always be ptr+1,so you need to initialize ptr2 in second for() .
And I think only one loop is better.
for(; ptr2 < ptr3; ++ptr1, ++ptr2) {
if (*ptr1 > *ptr2) {
sorted = false;
}
}
return sorted;

overflow with binary search recursively c++

I am trying to implement binarySerach recursively, but I got stack overflow.
First I have find function that takes 3 parameters. Then I call this function in main and pass adresess from the array. Nut I have got stack overflow!
bool find( const int x, const int* pBegin, const int* pEnd)
{
int medel =((*pBegin) + (*pEnd -1))/2 ;
if(x == medel)
return true ;
else if( x<medel)
{
int last = medel -1 ;
return find(x, pBegin, &last);
}
else if( x > medel)
{
int begin = medel +1;
return find(x, &begin, pEnd);
}
}// find
void main()
{
int arr[10];
for (int i=0;i<10;++i)
arr[i] = i;
bool found = find(3, &arr[0], &arr[10]);
cout << "hittat = " << found << endl;
system("pause");
}
There are several very fundamental issues around the use of pointers in your code. Without fixing the code for you, I'll give you a hint:
Try turning medel into a pointer to the middle element. This might help resolve some of the confusion.

Learning recursion: How can I locate a substring index within a string without using find?

I have a recursive function to find the starting index of a substring within a string. I am learning to use recursion, so the find function is not allowed. I believe I have met most of the conditions. This function is supposed to find the correct index in the string. If it is blank it returns -1.
Here is the real problem. If I enter a string "nothing" and search for "jax" it doesn't return -1. I don't understand why. Any help please? Here is the code:
The user would enter string s and t passed into below:
int index_of(string s, string t)
{
int start = 0;
int len2 = t.length();
int index = 0;
if (s == "")
{
return -1;
}
else if (s.substr(1).length() <= t.length())
{
return -1;
}
else if ( s.substr(start, len2) == t)
{
return index;
}
else
{
index ++;
return index + index_of(s.substr(1), t);
}
return -1;
}
There are several problems -- some minor ones, and some quite important ones.
You have two variables, start and index, to indicate "the current position", but one would be enough.
index can only be 0 or 1. Therefore, the way it is currently written, you could easily get rid of index and start altogether.
Important: When, during the final recursion, the end of the string is reached, you return -1 to the previous recursive call. Then, because of the way the recursive calls are done, you add 1 and return that to the previous call, and so forth. The value finally returned is the -1 plus the length of the string. That is why you get strange results.
This comparison
if (s.substr(1).length() <= t.length())
does not make much sense.
Taking all of this into account, here is an improved version:
#include <iostream>
#include <string>
int index_of(
const std::string &s,
const std::string &t,
const size_t index)
{
int len2 = t.length();
if ((s.length() - index) < t.length())
return -1;
else if (s.substr(index,len2) == t)
return index;
else
return index_of(s,t,index + 1);
return -1;
}
/** Overloading, so you can call index_of with just
two arguments */
int index_of(const std::string &s, const std::string &t)
{
return index_of(s,t,0);
}
/** Some test cases. */
int main()
{
std::cout << index_of("hello","ello") << std::endl;
std::cout << index_of("nothing","jax") << std::endl;
std::cout << index_of("hello","llo") << std::endl;
std::cout << index_of("hello","lo") << std::endl;
std::cout << index_of("hello","o") << std::endl;
std::cout << index_of("hello","hel") << std::endl;
}
The best way to learn how to debug problems like this is to work them out on paper. Your example is small enough that it shouldn't take too long. It's pretty clear that you're going to fall into your else case in the first few steps because the strings don't match. So we have:
index_of("nothing", "jax"):
index++; // index is now 1
return 1 + index_of("othing", "jax");
index_of("othing", "jax"):
index++; // index is now 1
return 1 + index_of("thing", "jax");
etc.
Does that help?