Recursion Part explanation - c++

I am stuck with merge sort recursion part.
void divide(int arr[], int low, int high) {
int mid;
if(low < high) {
mid = (low + high)/2;
divide (arr, low, mid);
divide (arr, mid+1, high);
numbersSort (arr, low, mid, high);
}
}
Assume array size is four. first time it will be called by divide(arr,0,4) and then divide(arr,0,2), divide(arr,0,1), divide(arr,0,0) respectively.
But one word to say when it comes to divide(arr,0,0) it should be stop in low < high condition. Then how is it work for divide and numberSort() function?
I have an another query to ask, when does numberSort() work ?
if you can give my line by line by simulation of above code, I will be grateful to you . I am in serious panic about it.
Advance thanks.

Then how is it work for divide and numberSort() function?
Execution in a given function doesn't stop when you call another function, it just pauses until that function returns. So imagine you're currently executing divide(arr,0,1). low is still less than high, so you enter the condition and call divide(arr,0,0), which does whatever it needs to do (hint: try not to worry about what it does just now), and then you call divide(arr,1,1) which again does it's thing and returns. Next, you call numbersSort(arr,0,0,1), which recombines the two sections of the array, and the result is that the array is sorted from index 0 to index 1.
Good so far? Okay, well, next you just return. And it happens that the divide(arr,0,1) call we just talked about was invoked by a divide(arr,0,2) call, so when divide(arr,0,1) returns, execution of divide(arr,0,2) continues from the point just after the divide(arr,0,1). So the next thing to happen will be a divide(arr,2,2) call, right? 2 is not less than 2, so that just returns right away as well, and then you hit the numbersSort(arr,0,1,2), which combines the two sections of the array (i.e. 0 through 1, and 2 through 2) into a properly sorted array from 0 to 2. Now the array is sorted from index 0 through index 2.
But, of course, that divide(arr,0,2) was called in the context of a divide(arr,0,4) call, so when the divide(arr,0,2) returns the next thing that happens is divide(arr,3,4). Let's assume that that does the right thing and sorts the array from index 3 to index 4. And then you get to the numbersSort(arr,0,2,4), which combines the two parts of the array and returns to whatever function called divide(arr,0,4).
It can definitely be tough to get your head around recursion at first. Keep at it -- it'll click eventually. If you can step through the code for a small-ish example in a debugger, that might help you see what's going on. Also, working through the code on paper can help. Try not to get bogged down with understanding how it works at every level all at once, but instead look for what happens at a single level and trust that calls to any functions (even recursive calls) just do the right thing.

The example top down merge sort divide() function just keeps calling itself until the sub-array size is reduced to a size of 1, in which case a sub-array of size 1 can be considered sorted. Only then does any actual merging begin, starting just after divide(arr,0,0) and divide(arr,1,1) return after doing nothing. numbersSort() then merges arr[0] and arr[1], and it returns. The next merge occurs just after divide(arr,2,2) and divide(arr,3,3), merging arr[2] and arr[3]. Then after that return, arr[0 1] and arr[2 3] are merged, resulting in a sorted array of 4 integers. Note that all divide does is generate pairs of indexes (low, high), numbersSort() is where the actual merging of data is done.
In general, top down merge sort is a depth first, left first sort. The non-iterative bottom up merge sort skips all the recursion used to generate indexes and just starts off by merging by even and odd indexes, merging [0] with [1], [2] with [3], [4] with [5], ... . Then on the next pass it merges runs of size 2, [0 1] with [2 3], [4 5] with [6 7], ... and so on until the array is merged.
Passing a temp array of the same size as the array to be sorted can be used to eliminate have to create, copy, and delete working arrays during a merge sort.
Example showing top down merge sort order of operation:
7 4 2 5 3 0 6 1
7 4 2 5|3 0 6 1
7 4|2 5
7|4
4 7
2|5
2 5
2 4 5 7
3 0|6 1
3|0
0 3
6|1
1 6
0 1 3 6
0 1 2 3 4 5 6 7
Example showing bottom up merge sort order of operation:
7 4 2 5 3 0 6 1
7|4|2|5|3|0|6|1 run size = 0
4 7|2 5|0 3|1 6 run size = 1
2 4 5 7|0 1 3 6 run size = 4
0 1 2 3 4 5 6 7 done

Related

finding whats wrong with my code,solving a easy competitive problem

QN;Here is the question.i dont know where my algorithm is wrong.help me find pls
Given an array A of N length. We need to calculate the next greater element for each element in given array. If next greater element is not available in given array then we need to fill ‘_’ at that index place.
Input:
The first line contains an integer T, the number of test cases. For each test case, the first line contains an integer n, the size of the array. Next line contains n space separated integers denoting the elements of the array.
Output:
For each test case, the output is an array that displays next greater element to element at that index.
Constraints:
1 <= T <= 100
1 <= N <= 100
-106 <= Ai <= 106
Example:
Input
2
9
6 3 9 8 10 2 1 15 7
4
13 6 7 12
Output:
7 6 10 9 15 3 2 _ 8
_ 7 12 13
Explanation:
Testcase 1: Here every element of the array has next greater element but at index 7, 15 is the greatest element of given array and no other element is greater from 15 so at the index of 15 we fill with ''.
Testcase 2: Here, at index 0, 13 is the greatest value in given array and no other array element is greater from 13 so at index 0 we fill ''.
My solution:
//NOT SOLVED YET
#include<iostream>
using namespace std;
int main()
{
int a[10]={6 ,3 ,9, 8 ,10, 2 ,1, 15, 7};
int b[10],flag=0,big=-1,i,j;
for(i=0;i<10;i++)
{
for(j=0;j<10;j++)
{
if(i==j)continue;
if((a[j]>a[i]) && (flag==0))
{
big=a[j];
flag=1;
}
else if(a[j]<big && big>a[i] && flag==1)
big=a[j];
}
if(big==-1)cout<<'_';
else cout<<big<<' ';
big=-1;
flag=0;
}
}
the output i get is:
2 2 2 2 7 1 0 _ 2 1
The condition should be:
else if(a[j] < big && a[j] > a[i] && flag == 1)
Indeed, if you use big > a[i], then that means you just check if the thus far next greater element was larger than a[i], but this thus makes it possible to select a value later in the process that is smaller than big, but smaller than a[i] as well. Here we thus want to check if a[j] is between a[i] and big.
That being said, the above approach is not very efficient. Indeed, for each element, you calculate the next element in linear time, making this a quadratic time algorithm. You might want to look at solutions where the list is sorted first. You can for example use min-heap here to move over the list in two passes.
To expand on what others have mentioned - that you currently have an O(N^2) algorithm, and this can be done more efficiently.
I don't think you can get O(N) here, but here is a plan for an O(N log N) algorithm:
For each test case:
Load the Ai values into two arrays, let's call them X and Y
Sort the Y array
Iterate over X and for each element of X do a binary search into Y to find the next larger value of Ai: use that as the output, or use _ if you did not find one
I recommend, for practice purposes, implementing this both using the C++ standard library, using https://en.cppreference.com/w/cpp/algorithm/sort and https://en.cppreference.com/w/cpp/algorithm/upper_bound , and implementing the above two functions yourself, see: https://en.wikipedia.org/wiki/Quicksort

Decreasing value in vectors with SFML

I created 5 numbers using vector with SFML, but I want the second one to fall one by one at intervals of 1 second. But, they first three falling as one by one. I don't understand why something like this is happening. Can you help me?
if (second == 1)
{
random.at(2)-=1;
cout << random[2] << endl;
text.setString(to_string(random[2]));
text.setPosition(numbers[2].getPosition().x, numbers[2].getPosition().y);
numbers.push_back(text);
numbers.erase(numbers.begin() + 2);
clock.restart();
}
The program gif
Full code
I'll give you a hand.
Here's what's happening:
You create 5 numbers in the random array. You may not have noticed it, but they are numbered 0 to 4 (SFML is sitting on C++, and then it means that arrays starts at zero here).
Every second, you update the number stocked in the 3rd place of your random array.
Then it goes wrong: instead of updating the corresponding number in the numbers array, you cycle it with push_back and erase.
Understand me here: push_back create a new element at the end of the vector, while erase removes an element from the vector and then "sort out things" so there's not number gap in the index of the vector.
Effectively, you're handling random right, but when you try to update number you cycle through it. Like this:
seconds: 1 2 3 4 5 6
array content: 0 0 0 0 0 0
(vertical) 1 1 1 1 1 1
2 3 4 5 6 7
3 4 5 6 7 8
4 5 6 7 8 9
I'm not sure how clear I'm making this, but if you look at the array content, you'll see that by erasing and creating a new value at the end, you're cycling through the positions [2-4] of the array. That's why in your gif not all numbers are updated wrong, only 3 of them.
The obvious solutions would be to stop erasing and pushing back in the numbers array. You can update it the same way you updated the random array. It'll be fine.
Like this:
if (second == 1)
{
random.at(2)-=1;
cout << random[2] << endl;
numbers[2].setString(to_string(random[2]));
clock.restart();
}
Have fun.

cant find error in my applied logic

question:
Given an array of elements of length N, ranging from 0 to N-1, your task is to write a program that rearranges the elements of the array. All elements may not be present in the array, if element is not present then there will be -1 present in the array. Rearrange the array such that A[i] = i and if i is not present, display -1 at that place.
my code:
#include <iostream>
using namespace std;
int main()
{
long int n;
cin>>n;
long int a[n];
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for (int i=1;i<=n;i++)
{
while(a[i]==i&&a[i]==-1)
{
int temp=a[i];
a[i]=a[temp];
a[temp]=temp;
}
}
for(int i=1;i<=n;i++)
cout<<a[i]<<" ";
return 1;
}
output:
6
-1 4 2 3 -1 5
-1 4 2 3 -1 5
can anyone please help me in finding out my error in the logic apllied?
Thanks in advance.
for(int i=1;i<=n;i++)
Wrong, elements go from 0 to N-1, not 1 to N
while(a[i]==i&&a[i]==-1)
This will never happen, you are asking for a[i] to be equal to both i and -1, which means asking i to be equal to -1, which won´t happen in your loop.
For a simple answer, you need to sort the list and then process that. For an efficient answer, you will want to make a boolean array of size N and then iterate the array and check which values are present. Then you iterate the boolean array to write the number when it is present or -1 when its not.
The easiest way to solve this kind of problem is to get a pack of playing cards and lay them out on your desk, and then solve the problem by hand. Write down every step you take, and then write code that performs those steps.
Because cards start at 1, rather than 0, I use the 10 as a 0. Use the joker to indicate an empty space (-1 in your problem description).
Take five cards and lay them out in six spaces
2 10 4 J 3 1
Starting with position 0. Pull the 2 out and replace it with -1, so your cards look like this:
J 10 4 J 3 1
And you're holding the 2 in your hand.
Then, go to position 2, pull out the 4 and put the 2 there. Now you have
J 10 2 J 3 1
And you're holding 4 in your hand. Go to position 4 (where the 3 is). Replace the 3 with 4, you have:
J 10 2 J 4 1
And 3 in the hand. Position 3 contains a joker. So you put the 3 in that position and put the joker aside. You now have:
J 10 2 3 4 1
So you move to the next position, 1. Pick up the 10 and put a joker in that spot. The 10 goes to position 0, so take the joker from position 0, place the 10 there, and you have:
10 J 2 3 4 1
You don't have anything in your hand now, so you move forward, checking positions 2, 3, and 4, which already have a[i] == i. But position 5 contains a 1. So you pick it up, place a joker in that position, and then replacing the joker in position 1 with the value 1 that you just pulled from position 5. Your array now looks like this:
10 1 2 3 4 J
And you're done.
Do that a few times with different arrangements of cards, writing down the steps you took. After a few practice runs, you should be able to write down the general algorithm for solving the problem. Then you write a program to implement that solution.
The idea of this kind of problem is to help you develop these problem solving steps. Over time, you'll be able to go straight to code with the simpler problems, but you'll find that building a physical model is very useful with more complex problems. If you step away from the computer, you're not tempted to start programming before you've solved the problem. You'll find that doing things way will save you a lot of frustration.

Every sum possibilities of elements

From a given array (call it numbers[]), i want another array (results[]) which contains all sum possibilities between elements of the first array.
For example, if I have numbers[] = {1,3,5}, results[] will be {1,3,5,4,8,6,9,0}.
there are 2^n possibilities.
It doesn't matter if a number appears two times because results[] will be a set
I did it for sum of pairs or triplet, and it's very easy. But I don't understand how it works when we sum 0, 1, 2 or n numbers.
This is what I did for pairs :
std::unordered_set<int> pairPossibilities(std::vector<int> &numbers) {
std::unordered_set<int> results;
for(int i=0;i<numbers.size()-1;i++) {
for(int j=i+1;j<numbers.size();j++) {
results.insert(numbers.at(i)+numbers.at(j));
}
}
return results;
}
Also, assuming that the numbers[] is sorted, is there any possibility to sort results[] while we fill it ?
Thanks!
This can be done with Dynamic Programming (DP) in O(n*W) where W = sum{numbers}.
This is basically the same solution of Subset Sum Problem, exploiting the fact that the problem has optimal substructure.
DP[i, 0] = true
DP[-1, w] = false w != 0
DP[i, w] = DP[i-1, w] OR DP[i-1, w - numbers[i]]
Start by following the above solution to find DP[n, sum{numbers}].
As a result, you will get:
DP[n , w] = true if and only if w can be constructed from numbers
Following on from the Dynamic Programming answer, You could go with a recursive solution, and then use memoization to cache the results, top-down approach in contrast to Amit's bottom-up.
vector<int> subsetSum(vector<int>& nums)
{
vector<int> ans;
generateSubsetSum(ans,0,nums,0);
return ans;
}
void generateSubsetSum(vector<int>& ans, int sum, vector<int>& nums, int i)
{
if(i == nums.size() )
{
ans.push_back(sum);
return;
}
generateSubsetSum(ans,sum + nums[i],nums,i + 1);
generateSubsetSum(ans,sum,nums,i + 1);
}
Result is : {9 4 6 1 8 3 5 0} for the set {1,3,5}
This simply picks the first number at the first index i adds it to the sum and recurses. Once it returns, the second branch follows, sum, without the nums[i] added. To memoize this you would have a cache to store sum at i.
I would do something like this (seems easier) [I wanted to put this in comment but can't write the shifting and removing an elem at a time - you might need a linked list]
1 3 5
3 5
-----
4 8
1 3 5
5
-----
6
1 3 5
3 5
5
------
9
Add 0 to the list in the end.
Another way to solve this is create a subset arrays of vector of elements then sum up each array's vector's data.
e.g
1 3 5 = {1, 3} + {1,5} + {3,5} + {1,3,5} after removing sets of single element.
Keep in mind that it is always easier said than done. A single tiny mistake along the implemented algorithm would take a lot of time in debug to find it out. =]]
There has to be a binary chop version, as well. This one is a bit heavy-handed and relies on that set of answers you mention to filter repeated results:
Split the list into 2,
and generate the list of sums for each half
by recursion:
the minimum state is either
2 entries, with 1 result,
or 3 entries with 3 results
alternatively, take it down to 1 entry with 0 results, if you insist
Then combine the 2 halves:
All the returned entries from both halves are legitimate results
There are 4 additional result sets to add to the output result by combining:
The first half inputs vs the second half inputs
The first half outputs vs the second half inputs
The first half inputs vs the second half outputs
The first half outputs vs the second half outputs
Note that the outputs of the two halves may have some elements in common, but they should be treated separately for these combines.
The inputs can be scrubbed from the returned outputs of each recursion if the inputs are legitimate final results. If they are they can either be added back in at the top-level stage or returned by the bottom level stage and not considered again in the combining.
You could use a bitfield instead of a set to filter out the duplicates. There are reasonably efficient ways of stepping through a bitfield to find all the set bits. The max size of the bitfield is the sum of all the inputs.
There is no intelligence here, but lots of opportunity for parallel processing within the recursion and combine steps.

Position of elements in vector

I have several elements in a vector type that are read from cin and then i perfrom some calculations on the vector and it's order of elements gets changed. The problem is that I need to print the positions of the vector elements after the calculations. I don't know how to explain this well that's why i'll give an example:
10 1 100 1000
and 10 is 1st element, 1 is 2nd, 100 is 3rd etc. After the calculations the vector changes in :
100 10 1 1000
so I should print
3 1 2 4
because 100 is the 3rd element of the input, 10 is the 1st etc. etc.
I tried with an array[1000] (because there aren't numbers larger than 1000 in the input), but it won't work because there can be multiple numbers with the same value, like:
10 10 10 100
and the output can be 1 2 3 4 or 2 3 1 4 or 3 1 2 4 etc. but here i need to output 1 2 3 4 because it's the 'smallest'.
I tried with array f[1001] and f[10] = 1, f[100] = 2, f[1] = 3 - if the numbers from the input are 10 100 1. But in case there are multiple numbers with the same value like 10 10 100, then my idea's not working. Please help me in any possible way.
Sounds like you need to store both the value and the initial position. You should be able to do this with an array of structs:
struct UserInput
{
unsigned int initialPosition;
int userInputValue;
};
int main()
{
userInput theUserInput[100];
// increment a counter, starting at 1, and place it in
// "initialPosition" in the struct as user input is read
}
I'll leave the rest up to you... as it is after all homework :) good luck.
Use an associative array if you know what it is.
Use linear search to determine the index if the number of input is limited.
Consider using log10 (or strlen) to transform the 1, 10, 100, 1000, etc. into 0, 1, 2, 3, etc.
From your description of such example:
10(3) 10(2) 10(1) 100(4)
What we have to output is 1 2 3 4, instead of 3 2 1 4.
So I don't think your requirement is just print the initial position directly. You've to make the position sequences as small as possible.
Following is my solution:
Use a direct-mapping hash table to store all the initial positions for specified element. All the initial positions for the same element is sorted. So if you want output the smallest position sequence, you only need to read the initial positions for this specified element from first to last.
The detailed implementation is left to you, since it's a homework.