Trouble Understanding C++ Sequential Search - c++

I am new to C++ and am having difficulty understanding this function. Could someone walk me through it?
int seqSearch(int [ ] list, int target)
{
//precondition: The list is in non-decreasing order
//postcondition: The method returns -1 if the target is not in the list. If the target
//is in the list, the method returns the index of the first occurrence of the target.
int result = -1;
boolean foundBigger = false;
int i = 0;
while (result == -1 && !foundBigger && i < list.length)
{
if (target == list[i])
result = i;
else if (list[i] > target)
foundBigger = true;
//endif
i++;
} //endwhile
return result;
}

It is trying to find if a target number is present in the list, where the number in list are stored in descending order.
The loop continues,
Till the target is not found. (Condition:result == -1)
( If target found then result != -1 and the loop breaks, returning the index of the element.
or Till the element in the list is bigger than the target. ( Condition:!foundBigger )
( As the list is in descending order, if it finds a number which is less than the target, so their would be no chance of finding the number in the remaining list. So this means it is not present in the list and the loop should break.)
or Till the whole list is rendered and its not found. (Condition: i < list.length)
Hope its clear now.

Hmm, "non-decreasing order". A better word for it is ascending order :-)
The function assumes the list is in ascending order. Starting with the first item in the list (list[0]) , compare with the item you are looking for (ie, "target"). If equal, set result to index "i". If not, increment i and continue loop. Go through each item one by one until:
(a) you find "target", OR
(b) the current item is bigger than your "target" (quit at this point since no point goind on since your list is ordered)
Return value is the index in the list where you found "target" or -1 if not found.

when result is == -1 and
foundBigger is true and
then the size of the array that you pass to the function is more than 0
then it goes inside the while loop
if even of the one of the above criteria is not full filled then it would not go inside the loop it would just return the value of the return
then if the value that you pass to the function using target parameter equals to i value of array list then you assign result to he value of i
if the target value is less than to i value of array list then the foundBigger is assigned true so again when you come into the while loop you cannot fulfill the above criteria
if none of the above works then i is incremented by 1 and it comes out of the while loop
it goes until you find the in which position the target value is saved if target value is not in the array then it would return result -1
or else it would return the location

// precondition: The list is in non-decreasing order
// postcondition: The method returns -1 if the target is not in the list. If the target
// is in the list, the method returns the index of the first occurrence of the target.
int seqSearch(int [ ] list, int target)
{
int result = -1; // Set result to 'not-found' value
// Also we want to stop search if smth bigger than `target' will be found
// Remember the original list is assumed to be sorted, so first value
// bigger than `target' means: no need to continue, it is guarantied that `target'
// is nto here!
boolean foundBigger = false;
int i = 0; // Initial index to start search
// Repeat 'till `target' not found AND not found smth bigger that requested target
// and current index less than the list size...
while (result == -1 && !foundBigger && i < list.length)
{
if (target == list[i]) // Is current item equal to the requested?
result = i; // Remember result index (this will break the loop)
else if (list[i] > target) // Is current item bigger than the requsted?
foundBigger = true; // Yep, will break the loop w/ no result to return
//endif
i++; // move to next item in the list
} //endwhile
return result; // Return the result, whatever it is
}

If this is working code then its DEFINETELY not c++. The boolean operations in the while loop would have to be enclosed in separate parenthesis for order of operations and c++ doesn't have a .length property for arrays (java allows for both of these which makes me thing it's written in java).The logic behind it still remains the same though.
You first initialize your result int(the one that's to be returned) and a boolean that checks if you've passed the element that you want. As long as you haven't found what your looking for and you haven't 'passed' the target item you keep going.
If you've found your target then your result int is changed to the correct index and the next time the loop checks its conditions the index will be over -1 and represent a real number so the method will end and return an index.
The second statement checks to see if you've passed the int that you're looking for. You know the list is sequential so if the value you're currently on is higher than the value you're looking for and you didn't find the item then you change the foundBigger boolean which will end the loop next time the conditions are checked.
If none of these conditions are met then you will eventually go past the end of the list searching so once you've reached the end of your list you know the item wasn't in the list so you still return -1.

Related

C++ map showing values as 0 for all keys

I am inserting number from a vector in map with key as the number and value as it's (index + 1).
But when I print the contents of the map, value being shown is 0 though I pass interger i.
// taking input of n integers in vector s;
vector<int> s;
for(int i=0;i<n;i++){
int tmp;cin>>tmp;
s.push_back(tmp);
}
//creating map int to int
map<int,int> m;
bool done = false;
for(int i=1;i<=s.size();i++){
//check if number already in map
if (m[s[i-1]]!=0){
if (i-m[s[i-1]]>1){
done = true;
break;
}
}
// if number was not in map then insert the number and it's index + 1
else{
m.insert({s[i-1],i});
}
}
for(auto it=m.begin();it!=m.end();it++){
cout<<endl<<it->first<<": "<<it->second<<endl;
}
For input
n = 3
and numbers as
1 2 1 in vector s, I expect the output to be
1: 1
2: 2
but output is
1: 0
2: 0
Why 0? What's wrong?
Your code block following the comment:
// check if number already in map
is logically faulty, because operator[] will actually insert an element, using value initialisation(a), if it does not currently exist.
If you were to instead use:
if (m.find(s[i-1]) != m.end())
that would get rid of this problem.
(a) I believe(b) that value initialisation for classes involve one of the constructors; for arrays, value initialisation for each item in the array; and, for other types (this scenario), zero initialisation. That would mean using your method creates an entry for your key, with a zero value, and returns that zero value
It would then move to the else block (because the value is zero) and try to do the insert. However, this snippet from the standard (C++20, [map.modifiers] discussing insert) means that nothing happens:
If the map already contains an element whose key is equivalent to k, there is no effect.
(b) Though, as my kids will point out frequently, and without much prompting, I've been wrong before :-)
std::map::operator[] will create a default element if it doesn't exist. Because you do m[s[i-1]] in the if condition, m.insert({s[i-1],i}); in else branch will always fail.
To check if key is already present in map use either find(), count() or contains() (if your compiler supports C++20)
//either will work instead of `if (m[s[i-1]]!=0)`
if (m.find(s[i-1]) != m.end())
if (m.count(s[i-1]) == 1)
if (m.contains(s[i-1])) //C++20

How to find the number of iteration in this while loop - operation count

I'm confused about how to do the operation count for a while loop specifically the number of iterations.
I do understand how to find the number of iteration for a regular loop (from 0 to n) and also for binary search (log2n) but this piece of code utilizes the case of true and false. the number of iteration would depend on if "more" is true and "found" is false.
What would be the worst case scenario for this? the item is not found?
In the code below, the commented parts are the operation count for that line.
List is a linked list structure of N nodes:
void FindItem(Node *list, Item item, Node *&loc, bool &found){
bool more = true; // 1
loc = list; found = false; // 2
while (more && !found) { // (number of iterations)
if (item < loc->info) // 2 * (number of iteration)
more = false; // (0 or 1)*number of iterations
else if (item == loc->info) // 2 * (number of iteration)
found=true; // (0 or 1)*number of iterations
else {
loc = loc->next; // (0 or 2) * (number of iteration)
more = (loc != NULL); // (0 or 2)*number of iterations
}
}
}
This looks like a school exercise or a homework question.
The fact that you need to answer on paper, pretty much confirms that.
So what you are looking for is probably "Big O" complexity.
And in that case, you are looking at a simple 0 .. n loop, which you claim to know, since at most, the loop can run over the entire list.
The name of the condition variable more and the condition it self are a clear clue that the code is nothing more than a linier search on a sorted list.

Using a hash to find one duplicated and one missing number in an array

I had this question during an interview and am curious to see how it would be implemented.
Given an unsorted array of integers from 0 to x. One number is missing and one is duplicated. Find those numbers.
Here is what I came up with:
int counts[x+1];
for(int i =0;i<=x; i++){
counts[a[i]]++;
if(counts[a[i]] == 2)
cout<<”Duplicate element: “<<a[i]; //I realized I could find this here
}
for(int j=0; j<=x; j++){
if(counts[j] == 0)
cout<<”Missing element: “<<j;
//if(counts[j] == 2)
// cout<<”Duplicate element: “<<j; //No longer needed here.
}
My initial solution was to create another array of size x+1, loop through the given array and index into my array at the values of the given array and increment. If after the increment any value in my array is two, that is the duplicate. However, I then had to loop through my array again to find any value that was 0 for the missing number.
I pointed out that this might not be the most time efficient solution, but wasn't sure how to speed it up when I was asked. I realized I could move finding the duplicate into the first loop, but that didn't help with the missing number. After waffling for a bit, the interviewer finally gave me the idea that a hash would be a better/faster solution. I have not worked with hashes much, so I wasn't sure how to implement that. Can someone enlighten me? Also, feel free to point out any other glaring errors in my code... Thanks in advance!
If the range of values is the about the same or smaller than the number of values in an array, then using a hash table will not help. In this case, there are x+1 possible values in an array of size x+1 (one missing, one duplicate), so a hash table isn't needed, just a histogram which you've already coded.
If the assignment were changed to be looking for duplicate 32 bit values in an array of size 1 million, then the second array (a histogram) could need to be 2^32 = 4 billion counts long. This is when a hash table would help, since the hash table size is a function of the array size, not the range of values. A hash table of size 1.5 to 2 million would be large enough. In this case, you would have 2^32 - 2^20 = 4293918720 "missing" values, so that part of the assignment would go away.
Wiki article on hash tables:
Hash Table
If x were small enough (such that the sum of 0..x can be represented), you could compute the sum of the unique values in a, and subtract that from the sum of 0..x, to get the missing value, without needing the second loop.
Here is a stab at a solution that uses an index (a true key-value hash doesn't make sense when the array is guaranteed to include only integers). Sorry OP, it's in Ruby:
values = mystery_array.sort.map.with_index { |n,i| n if n != i }.compact
missing_value,duplicate_value = mystery_array.include?(values[0] - 1) ? \
[values[-1] + 1, values[0]] : [values[0] - 1, values[-1]]
The functions used likely employ a non-trivial amount of looping behind the scenes, and this will create a (possibly very large) variable values which contains a range between the missing and/or duplicate value, as well as a second lookup loop, but it works.
Perhaps the interviewer meant to say Set instead of hash?
Sorting allowed?
auto first = std::begin(a);
auto last = std::end(a);
// sort it
std::sort( first, last );
// find duplicates
auto first_duplicate = *std::adjacent_find( first, last );
// find missing value
auto missing = std::adjacent_find(first, last, [](int x, int y) {return x+2 == y;});
int missing_number = 0;
if (missing != last)
{
missing_number = 1+ *missing;
}
else
{
if (counts[0] != 0)
{
missing_number = 0;
}
else
{
missing_number = 9;
}
}
Both could be done in a single hand-written loop, but I wanted to use only stl algorithms. Any better idea for handling the corner cases?
for (i=0 to length) { // first loop
for( j=0 to length ){ // second loop
if (t[i]==j+1) {
if (counter==0){//make sure duplicated number has not been found already
for( k=i+1 to length ) { //search for duplicated number
if(t[k]==j+1){
j+1 is the duplicated number ;
if(missingIsFound)
exit // exit program, missing and dup are found
counter=1 ;
}//end if t[k]..
}//end loop for duplicated number
} // end condition to search
continue ; // continue to first loop
}
else{
j+1 is the missing number ;
if(duplicatedIsFound)
exit // exit program, missing and dup are found
continue ; //continue to first loop
}//end second loop
} //end first loop

simple hash map with vectors in C++

I'm in my first semester of studies and as a part of my comp. science assignment I have to implement a simple hash map using vectors, but I have some problems understanding the concept.
First of all I have to implement a hash function. To avoid collisions I thought it would be better to use double hashing, as follows:
do {
h = (k % m + j*(1+(k % (m-2)));
j++;
} while ( j % m != 0 );
where h is the hash to be returned, k is the key and m is the size of hash_map (and a prime number; they are all of type int).
This was easy, but then I need to be able to insert or remove a pair of key and the corresponding value in the map.
The signature of the two functions should be bool, so I have to return either true or flase, and I'm guessing that I should return true when there is no element at position h in the vector. (But I have no idea why remove should be bool as well).
My problem is what to do when the insert function returns false (i.e. when there is already a key-value pair saved on position h - I implemented this as a function named find). I could obviously move it to the next free place by simply increasing j, but then the hash calculated by my hash function wouldn't tell us anymore at which place a certain key is saved, causing wrong behaviour of remove function.
Is there any good example online, that doesn't use the pre defined STD methods? (My Google behaves wierdly in the past few days and only reutrns me unuseful hits in the local language)
I've been told to move my comment to an answer so here it is. I am presuming your get method takes the value you are looking for an argument.
so what we are going to do is a process called linear probing.
when we insert the value we hash it as normal lets say our hash value is 4
[x,x,x,,,x,x]
as we can see we can simply insert it in:
[x,x,x,x,,x,x]
however if 4 is taken when we insert it we will simply move to the next slot that is empty
[x,x,x,**x**,x,,x,x]
In linear probing if we reach the end we loop back round to the beginning until we find a slot. You shouldn't run out of space as you are using a vector which can allocate extra space when it starts getting near full capacity
this will cause problems when you are searching because the value at 4 may not be at 4 anymore (in this case its at 5). To solve this we do a little bit of a hack. Note that we still get O(1) run time complexity for inserting and retrieval as long as the load balance is below 1.
in our get method instead of returning the value in the array at 4 we are instead going to start looking for our value at 4 if its there we can return it. If not we look at the value at 5 and so on till we find the value.
in psudo code the new stuff looks like this
bool insert(value){
h = hash(value);
while(node[h] != null){
h++;
if( h = node.length){
h = 0;
}
}
node[h] = value;
return true;
}
get
get(value){
h = hash(value);
roundTrip = 0; //used to see if we keep going round the hashmap
while(true){
if(node[h] == value)
return node[h];
h++;
if( h = node.length){
h = 0;
roundTrip++;
}
if(roundTrip > 1){ //we can't find it after going round list once
return -1;
}
}
}

How do I find the mode of a sorted array?

I need to write a function to find the mode of a array. I'm not good at coming up with algorithms however and I'm hoping someone else knows how to do this.
I know the size of the array and the values in each element, and I have the array sorted from least to greatest.
array would be passed to the mode function like
mode = findMode(arrayPointer, sizePointer);
UPDATE:
After reading the comments I've tried this
int findMode(int *arrPTR, const int *sizePTR)
{
int most_found_element = arrPTR[0];
int most_found_element_count = 0;
int current_element = arrPTR[0];
int current_element_count = 0;
int count;
for (count = 0; count < *sizePTR; count++)
{
if(count == arrPTR[count])
current_element_count++;
else if(current_element_count > most_found_element)
{
most_found_element = current_element;
most_found_element_count = current_element_count;
}
current_element = count;
current_element_count=1;
}
return most_found_element;
}
I'm still having problems grasping this algorithm though if anyone can sort me out.
I've never used vectors so don't really understand the other examples.
You have almost everything.
You can take advantage of the fact that the array is sorted.
Just go through the array keeping track of both the current equal consecutive numbers, and the greatest number of equal consecutive numbers you have found until that point (and which number produced it). In the end you will have the greatest number of equal consecutive numbers and which number produced it. That will be the mode.
Note: For a solution which does not require the array to be sorted, see for example one based in the histogram approach in a related question.
set most_found_element to the first element in the array
set most_found_element_count to zero
set current_element to the first element of the array
set current_element_count to zero
for each element e in the array
if e is the same as the current_element
increase current_element_count by one
else
if current_element_count is greater than most_found_element_count
set most_found_element to the current_element
set most_found_element_count to current_element_count
set current_element to e
set current_element_count to one
if current_element_count is greater than most_found_element_count
set most_found_element to the current_element
set most_found_element_count to current_element_count
print most_found_element and most_found_element_count
I thought the names would explain it, but here we go:
When we start, no element has been found the most times
so the "high-score" count is zero.
Also, the "current" value is the first, but we haven't looked at it yet
so we've seen it zero times so far
Then we go through each element one by one
if it's the same as "current" value,
then add this to the number of times we've seen the current value.
if we've reached the next value, we've counted all of the "current" value.
if there was more of the current value than the "high-score"
then the "high-score" is now the current value
and since we reached a new value
the new current value is the value we just reached
Now that we've seen all of the elements, we have to check the last one
if there was more of the current value than the "high-score"
then the "high-score" is now the current value
Now the "high-score" holds the one that was in the array the most times!
Also note: my original algorithm/code had a bug, we have to do an extra check of "current" after the loop ends, as it never finds "the one after the last".
Hints:
Q: How do you define the mode?
A: The number whose count is greatest within the array.
Q: How do you count numbers in an ordered array?
A: Iterate through the array, and while the next item is equal to the previous, increment the count for that value.
Q: If the count of the previous value is less than the count of the current value, then can the previous value be the mode?
A: No
If the input array is sorted, here is the same approach as described in other answers but implemented in a different way, a better and easy to understand way.
Run a loop over the input array.
Keep global mode value and mode count.
Run a sliding window till you find equal elements.
If local equal element count is greater than global mode count, then update global mode and mode count.
Here is working and tested code in C++.
int mode(vector<int> a, int N)
{
int mode = a[0];
int mode_count = 1;
int i = 0;
while (i < N - 1) {
int cur = a[i];
int cur_count = 1;
while (a[i] == a[i + 1]) {
i++;
cur_count++;
}
if (cur_count > mode_count) {
mode_count = cur_count;
mode = a[i];
}
i++;
}
return mode;
}