Divide function returns wrong value - c++

I have a function which will supposedly check if there's an indices i such that it is equal to v[i]. V is a strictly ascending ordered vector. It needs to be done in O(logn) and I thought about divide. I was never really familiar with recursion. I wrote this code and I don't really know why it won't work. Something's missing. If I put cout << mid instead of return it will show the right value, but I guess that's not the proper way to do it, frankly. In this stage the mid value returned is 7, and I don't know why.
Here's the code.
int customDivide(vector <int>& v, int left, int right)
{
if(left <= right)
{
int mid = (left+right)/2;
if(mid == v[mid]){
//cout<<mid<<" ";
return mid;
}
customDivide(v,left,mid-1);
customDivide(v,mid+1,right);
}
}

Two problems exist here, and I will attempt to explain them with an analogy of finding a lost dog in your neighborhood.
You are not returning a value from the function, unless you found the correct element immediately. You promise to return a value (an int) but you don't always do it.
This is like promising to send the dog owner a letter to indicate where their lost dog can be found. You check your garden and if you find the dog, you send a letter - that works. If you didn't find the dog, you go to your neighbors and have them promise to send you a letter if they find the dog, using the same method as you did (recursion). The problem is that in this case you are not reading or forwarding their letters (the return values from your two recursive function calls at the end) - you are just throwing these letters away. Worse, you are not actually sending back the letter to the guy looking for his dog if you didn't find it yourself (no return after the calls). Your code seems to assume that the neighbors will automatically send the letter to the dog owner - that is not how return works, it just sends the letter to the previous person in the chain (in code terms, the call stack), so if that person throws it into the trash right away, the system won't work.
You cannot get O(log(n)) performance if you unconditionally recurse to both sides.
If you always ask all your neighbors (and they ask all of theirs), you will have literally every person in the neighborhood looking for the dog. That's O(n). You must identify which of your two neighbors should look for the dog (e.g. by looking at the trail the dog left) and only ask that one. This way you halve the number of people that might have to search for the dog at each step, giving you O(log(n)) performance.
This "trail" is something you need to know beforehand. In your case, it is not clear what that could be - the dog could be anywhere (all elements could have random values) and you have no idea where to go looking. You need to figure out this detail of the task to get to your O(log(n)) time. It could be that vector elements are strictly increasing (see #Jarod42's comment), i.e. there are no duplicate elements and each one is larger than the previous one. In that case you can decide that only one of the two remaining halves can possibly contain what you are looking for, thus recursing there.
(Yes I know, the analogy breaks down unless your neighborhood is shaped like a binary tree with you at the top and a non-reciprocal definition of "neighbors".)

As a result of all the help involved here, I finally understood what the problem was.
1st of all - It didn't take advantage of the fact that the vector was strictly sorted.
2nd - Every function in the stack returns something now.
int customDivide(vector <int>& v, int left, int right)
{
if(left <= right)
{
int mid = (left+right)/2;
if(mid == v[mid])
return mid;
else if(v[mid] < mid)
return customDivide(v,mid+1,right);
else
return customDivide(v,left, mid-1);
}
return -1;
}
Thanks a lot for all your help!

Related

How is binary search applicable here (since the values are not monotonic)?

I am solving a LeetCode problem Search in Rotated Sorted Array, in order to learn Binary Search better. The problem statement is:
There is an integer array nums sorted in ascending order (with distinct values). Prior to being passed to your function, nums is possibly rotated at an unknown pivot index. For example, [0,1,2,4,5,6,7] might be rotated at pivot index 3 and become [4,5,6,7,0,1,2]. Given the array nums after the possible rotation and an integer target, return the index of target if it is in nums, or -1 if it is not in nums.
With some online help, I came up with the solution below, which I mostly understand:
class Solution {
public:
int search(vector<int>& nums, int target) {
int l=0, r=nums.size()-1;
while(l<r) { // 1st loop; how is BS applicable here, since array is NOT sorted?
int m=l+(r-l)/2;
if(nums[m]>nums[r]) l=m+1;
else r=m;
}
// cout<<"Lowest at: "<<r<<"\n";
if(nums[r]==target) return r; //target==lowest number
int start, end;
if(target<=nums[nums.size()-1]) {
start=r;
end=nums.size()-1;
} else {
start=0;
end=r;
}
l=start, r=end;
while(l<r) {
int m=l+(r-l)/2;
if(nums[m]==target) return m;
if(nums[m]>target) r=m;
else l=m+1;
}
return nums[l]==target ? l : -1;
}
};
My question: Are we searching over a parabola in the first while loop, trying to find the lowest point of a parabola, unlike a linear array in traditional binary search? Are we finding the minimum of a convex function? I understand how the values of l, m and r change leading to the right answer - but I do not fully follow how we can be guaranteed that if(nums[m]>nums[r]), our lowest value would be on the right.
You actually skipped something important by “getting help”.
Once, when I was struggling to integrate something tricky for Calculus Ⅰ, I went for help and the advisor said, “Oh, I know how to do this” and solved it. I learned nothing from him. It took me another week of going over it (and other problems) myself to understand it sufficient that I could do it myself.
The purpose of these assignments is to solve the problem yourself. Even if your solution is faulty, you have learned more than simply reading and understanding the basics of one example problem someone else has solved.
In this particular case...
Since you already have a solution, let’s take a look at it: Notice that it contains two binary search loops. Why?
As you observed at the beginning, the offset shift makes the array discontinuous (not convex). However, the subarrays either side of the discontinuity remain monotonic.
Take a moment to convince yourself that this is true.
Knowing this, what would be a good way to find and determine which of the two subarrays to search?
Hints:
A binary search as  ( n ⟶ ∞ )   is   O(log n)
O(log n) ≡ O(2 log n)
I should also observe to you that the prompt gives as example an arithmetic progression with a common difference of 1, but the prompt itself imposes no such restriction. All it says is that you start with a strictly increasing sequence (no duplicate values). You could have as input [19 74 512 513 3 7 12].
Does the supplied solution handle this possibility?
Why or why not?

How do I calculate the time complexity of the following function?

Here is a recursive function. Which traverses a map of strings(multimap<string, string> graph). Checks the itr -> second (s_tmp) if the s_tmp is equal to the desired string(Exp), prints it (itr -> first) and the function is executed for that itr -> first again.
string findOriginalExp(string Exp){
cout<<"*****findOriginalExp Function*****"<<endl;
string str;
if(graph.empty()){
str ="map is empty";
}else{
for(auto itr=graph.begin();itr!=graph.end();itr++){
string s_tmp = itr->second;
string f_tmp = itr->first;
string nll = "null";
//s_tmp.compare(Exp) == 0
if(s_tmp == Exp){
if(f_tmp.compare(nll) == 0){
cout<< Exp <<" :is original experience.";
return Exp;
}else{
return findOriginalExp(itr->first);
}
}else{
str="No element is equal to Exp.";
}
}
}
return str;
}
There are no rules for stopping and it seems to be completely random. How is the time complexity of this function calculated?
I am not going to analyse your function but instead try to answer in a more general way. It seems like you are looking for an simple expression such as O(n) or O(n^2) for the complexity for your function. However, not always complexity is that simple to estimate.
In your case it strongly depends on what are the contents of graph and what the user passes as parameter.
As an analogy consider this function:
int foo(int x){
if (x == 0) return x;
if (x == 42) return foo(42);
if (x > 0) return foo(x-1);
return foo(x/2);
}
In the worst case it never returns to the caller. If we ignore x >= 42 then worst case complexity is O(n). This alone isn't that useful as information for the user. What I really need to know as user is:
Don't ever call it with x >= 42.
O(1) if x==0
O(x) if x>0
O(ln(x)) if x < 0
Now try to make similar considerations for your function. The easy case is when Exp is not in graph, in that case there is no recursion. I am almost sure that for the "right" input your function can be made to never return. Find out what cases those are and document them. In between you have cases that return after a finite number of steps. If you have no clue at all how to get your hands on them analytically you can always setup a benchmark and measure. Measuring the runtime for input sizes 10,50, 100,1000.. should be sufficient to distinguish between linear, quadratic and logarithmic dependence.
PS: Just a tip: Don't forget what the code is actually supposed to do and what time complexity is needed to solve that problem (often it is easier to discuss that in an abstract way rather than diving too deep into code). In the silly example above the whole function can be replaced by its equivalent int foo(int){ return 0; } which obviously has constant complexity and does not need to be any more complex than that.
This function takes a directed graph and a vertex in that graph and chases edges going into it backwards to find a vertex with no edge pointing into it. The operation of finding the vertex "behind" any given vertex takes O(n) string comparisons in n the number of k/v pairs in the graph (this is the for loop). It does this m times, where m is the length of the path it must follow (which it does through the recursion). Therefore, it has time complexity O(m * n) string comparisons in n the number of k/v pairs and m the length of the path.
Note that there's generally no such thing as "the" time complexity for just some function you see written in code. You have to define what variables you want to describe the time in terms of, and also the operations with which you want to measure the time. E.g. if we want to write this purely in terms of n the number of k/v pairs, you run into a problem, because if the graph contains a suitably placed cycle, the function doesn't terminate! If you further constrain the graph to be acyclic, then the maximum length of any path is constrained by m < n, and then you can also get that this function does O(n^2) string comparisons for an acyclic graph with n edges.
You should approximate the control flow of the recursive calling by using a recurrence relation. It's been like 30 years since I took college classes in Discrete Math, but generally you do like pseuocode, just enough to see how many calls there are. In some cases just counting how many are on the longest condition on the right hand side is useful, but you generally need to plug one expansion back in and from that derive a polynomial or power relationship.

Heap Buffer Overflow occurs randomly....... for a simple code?(I'm new to C++)

ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000114 at pc 0x000000406d27 bp 0x7ffc88f07560 sp 0x7ffc88f07558
READ of size 4 at 0x602000000114 thread T0
LeetCode No.1
I get this when I give this code
The code below works for some other inputs, but for [3,2,4]\n6, it shows the above error.
vector<int> twoSum(vector<int>& nums, int target) {
int first = 0,last = nums.size() - 1;
vector<int> ref = nums;
while(first < last){
if(ref[first]+ref[last] > target) last--;
else if(ref[first]+ref[last] < target) first++;
else break;
}
vector<int> result;
for(int i=0;i<nums.size();i++){
if(ref[first]==nums[i]) result.push_back(i);
else if(ref[last]==nums[i]) result.push_back(i);
}
if(result[0] > result[1])
swap(result[0],result[1]);
return result;
}
The expected output is [1,2], indexes of values in the array adding up to the value 6.
Consider this while loop.
while(first < last){
if(ref[first]+ref[last] > target) last--;
else if(ref[first]+ref[last] < target) first++;
else break;
}
It seems that the intent was to break and exit when the sum is exactly equal to the target number. However, it is not guaranteed that this will become true. You can also exit the loop when the while condition fails, which happens whenever you reach first == last without yet finding any exact match. That actually happens in the particular case you mention. Follow the logic through and you will find this yourself. The search process misses the desired answer. The logic will not find [1,2]. It will first consider [0,2] and when that fails as too big, it will permanently decrement last and never again consider any combination that involves position 2.
(Likewise, if it fails for being too small it would increment the first position and never again consider combinations with the first value. So there are other failure cases that would happen similarly with that scenario.)
Since you exit without finding the matching combination and first == last, only one number will be pushed into the results. Therefore, when you just assume there are two numbers (false), things blow up as you try to reference the second result number.
General Observation:
You need to plan for the case where no exact match is found and code with that possibility in mind. In that case, what would a correct return result look like to signify no solution was found?
Plus, you could think about how the algorithm could be better at not missing a solution when it is actually present. However, that doesn't change the first requirement. If the target cannot be matched by any sum, you need to be ready for that possibility.
Side Notes:
Rather than repeat the sum of two in if statements, when the sum isn't changing I would suggest that you could create and use an auto local variable once that is
auto sum(ref[first]+ref[last]);
If you want to ensure that argument vector nums is not changed, and communicate that clearly to anyone looking at the declaration of the function, a better choice would be the pass it as a const reference, e.g.
(const vector<int>& nums, ...)
Why does the code create a local copy called ref of the argument vector nums? What is the point of making the effort to make the copy?
Regarding...
last = nums.size() - 1
...notice that if the vector passed in is empty, the value of last goes negative. That might not cause a problem for some code, but it has a dangerous smell in that it looks like code that is just assuming that the vector passed in would never be empty. Practice defensive coding that can be seen to guard against the possibility of unusual input values.
p.s. Part of what saves that last initialization from being broken is the use of int. Since size() returns size_t (unsigned), a common problem is to handle it as unsigned size_t. Then instead of going negative, the result wraps around to the maximum value and the looping may try to work with that as if that was a valid position in the vector. It's hazardous to get into habits that invite those kinds of bugs.

Generalised suffix tree traversal to find longest common substring

I'm working with suffix trees. As far as I can tell, I have Ukkonen's algorithm running correctly to build a generalised suffix tree from an arbitrary number of strings. I'm now trying to implement a find_longest_common_substring() method to do exactly that. For this to work, I understand that I need to find the deepest shared edge (with depth in terms of characters, rather than edges) between all strings in the tree, and I've been struggling for a few days to get the traversal right.
Right now I have the following in C++. I'll spare you all my code, but for context, I'm keeping the edges of each node in an unordered_map called outgoing_edges, and each edge has a vector of ints recorded_strings containing integers identifying the added strings. The child field of an edge is the node it is going to, and l and r identify its left and rightmost indices, respectively. Finally, current_string_number is the current number of strings in the tree.
SuffixTree::Edge * SuffixTree::find_deepest_shared_edge(SuffixTree::Node * start, int current_length, int &longest) {
Edge * deepest_shared_edge = new Edge;
auto it = start->outgoing_edges.begin();
while (it != start->outgoing_edges.end()) {
if (it->second->recorded_strings.size() == current_string_number + 1) {
int edge_length = it->second->r - it->second->l + 1;
int path_length = current_length + edge_length;
find_deepest_shared_edge(it->second->child, path_length, longest);
if (path_length > longest) {
longest = path_length;
deepest_shared_edge = it->second;
}
}
it++;
}
return deepest_shared_edge;
}
When trying to debug, as best I can tell, the traversal runs mostly fine, and correctly records the path length and sets longest. However, for reasons I don't quite understand, in the innermost conditional, deepest_shared_edge sometimes seems to get updated to a mistaken edge. I suspect I maybe don't quite understand how it->second is updated throughout the recursion. Yet I'm not quite sure how to go about fixing this.
I'm aware of this similar question, but the approach seems sufficiently different that I'm not quite sure how it applies here.
I'm mainly during this for fun and learning, so I don't necessarily need working code to replace the above - pseudocode or just any explanation of where I'm confused would be just as well.
Your handling of deepest_shared_edge is wrong. First, the allocation you do at the start of the function is a memory leak, since you never free the memory. Secondly, the result of the recursive call is ignored, so whatever deepest edge it finds is lost (although you update the depth, you don't keep track of the deepest edge).
To fix this, you should either pass deepest_shared_edge as a reference parameter (like you do for longest), or you can initialize it to nullptr, then check the return from your recursive call for nullptr and update it appropriately.

Recursive Backtracking Sudoku Solver Problems, c++

It's my first time dealing with recursion as an assignment in a low level course. I've looked around the internet and I can't seem to find anybody using a method similar to the one I've come up with (which probably says something about why this isn't working). The error is a segmentation fault in std::__copy_move... which I'm assuming is something in the c++ STL.
Anywho, my code is as follows:
bool sudoku::valid(int x, int y, int value)
{
if (x < 0) {cerr << "No valid values exist./n";}
if (binary_search(row(x).begin(), row(x).end(), value))
{return false;} //if found in row x, exit, otherwise:
else if (binary_search(col(y).begin(), col(y).end(), value))
{return false;} //if found in col y, exit, otherwise:
else if (binary_search(box((x/3), (y/3)).begin(), box((x/3), (y/3)).end(), value))
{return false;} //if found in box x,y, exit, otherwise:
else
{return true;} //the value is valid at this index
}
int sudoku::setval(int x, int y, int val)
{
if (y < 0 && x > 0) {x--; y = 9;} //if y gets decremented past 0 go to previous row.
if (y > 8) {y %= 9; x++;} //if y get incremented past 8 go to next row.
if (x == 9) {return 0;} //base case, puzzle done.
else {
if (valid(x,y,val)){ //if the input is valid
matrix[x][y] = val; //set the element equal to val
setval(x,y++,val); //go to next element
}
else {
setval(x,y,val++); //otherwise increment val
if(val > 9) {val = value(x,y--); setval(x,y--,val++); }
} //if val gets above 9, set val to prev element,
} //and increment the last element until valid and start over
}
I've been trying to wrap my head around this thing for a while and I can't seem to figure out what's going wrong. Any suggestions are highly appreciated! :)
sudoku::setval is supposed to return an int but there are at least two paths where it returns nothing at all. You should figure out what it needs to return in those other paths because otherwise you'll be getting random undefined behavior.
Without more information, it's impossible to tell. Things like the data
structures involved, and what row and col return, for example.
Still, there are a number of obvious problems:
In sudoku::valid, you check for what is apparently an error
condition (x < 0), but you don't return; you still continue your
tests, using the negative value of x.
Also in sudoku:valid: do row and col really return references to
sorted values? If the values aren't sorted, then binary_search will
have undefined behavior (and if they are, the names are somewhat
misleading). And if they return values (copies of something), rather
than a reference to the same object, then the begin() and end()
functions will refer to different objects—again, undefined
behavior.
Finally, I don't see any backtracking in your algorithm, and I don't
see how it progresses to a solution.
FWIW: when I wrote something similar, I used a simple array of 81
elements for the board, then created static arrays which mapped the
index (0–80) to the appropriate row, column and box. And for each of
the nine rows, columns and boxes, I kept a set of used values (a
bitmap); this made checking for legality very trivial, and it meant that
I could increment to the next square to test just by incrementing the
index. The resulting code was extremely simple.
Independently of the data representation used, you'll need: some
"global" (probably a member of sudoku) means of knowing whether you've
found the solution or not; a loop somewhere trying each of the nine
possible values for a square (stopping when the solution has been
found), and the recursion. If you're not using a simple array for the
board, as I did, I'd suggest a class or a struct for the index, with a
function which takes care of the incrementation once and for all.
All of the following is for Unix not Windows.
std::__copy_move... is STL alright. But STL doesn't do anything by itself, some function call from your code would've invoked it with wrong arguments or in wrong state. You need to figure that out.
If you have a core dump from teh seg-fault then just do a pstack <core file name>, you will see the full call stack of the crash. Then just see which part of your code was involved in it and start debugging (add traces/couts/...) from there.
Usually you'll get this core file with nice readable names, but in case you don't you can use nm or c++filt etc to dismangle the names.
Finally, pstack is just a small cmd line utility, you can always load the binary (that produced the core) and the core file into a debugger like gdb, Sun Studio or debugger built into your IDE and see the same thing along with lots of other info and options.
HTH
It seems like your algorithm is a bit "brute forcy". This is generally not a good tactic with Constraint Satisfaction Problems (CSPs). I wrote a sudoku solver a while back (wish I still had the source code, it was before I discovered github) and the fastest algorithm that I could find was Simulated Annealing:
http://en.wikipedia.org/wiki/Simulated_annealing
It's probabilistic, but it was generally orders of magnitude faster than other methods for this problem IIRC.
HTH!
segmentation fault may (and will) happen if you enter a function recursively too many times.
I noted one scenario which lead to it. But I'm pretty sure there are more.
Tip: write in your words the purpose of any function - if it is too complicated to write - the function should probably be split...