Understanding a C++ Shell sort [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Hi I am trying to learn the shell sort .I understand the basic principles of splitting into segments and using the insertion method to sort.
However I only understand this example of code I found up to a point. If anyone could give me a clear explanation of what each of the for loops do etc. would be great.
int const size = 5;
int i, j, increment, temp;
int array[size]={4,5,2,3,6},i1=0;
//split the array into segments unil we reach beginning of array
for(increment = size/2;increment > 0; increment /= 2)
{
for(i = increment; i<size; i++)
{
temp = array[i];
for(j = i; j >= increment ;j-=increment)
{
//perform the insertion sort for this section
if(temp < array[j-increment])
{
array[j] = array[j-increment];
}
else
{
break;
}
}
array[j] = temp;
}
}

for(increment = size/2;increment > 0; increment /= 2)
This for loop initializes the gap between the elements in the array you are comparing against. So increment is set to 2 initially.
for(i = increment; i<size; i++)
{
temp = array[i];
This says, start at element 3 and go forwards until you reach element 5, we will see why soon.
for(j = i; j >= increment ;j-=increment)
{
//perform the insertion sort for this section
if(temp < array[j-increment])
{
array[j] = array[j-increment];
}
else
{
break;
}
}
array[j] = temp;
Says ok, we are starting at the element specified above (in this case, the 2nd index), and we are going to compare it against the element that is the "gap" length behind it. So it would take the 3rd element, and compare it against the 1st element. If the 3rd element is smaller than the 1st element, swap them, otherwise break out of the loop. We then decrement our index by the size of the gap (from 2 to 0) and keep going if our new index is at least as large as the size of the gap (so we don't have array out of bounds issues).
Now we go back to the middle for loop and increment the element position we start at; so we compare the
4th element against the 2nd element. Stop
5th element against the 3rd, then 3rd against the 1st. Stop
Once we have compared all elements within their "gap" length, we go back and change the gap length to half of what it was before, rinse and repeat, until it reaches 0.
Typically, you don't want to just divide the gap in half - there are pre-defined functions for gap length recommendation (usually primes). See wikipedia for more info.

Related

breaking permutation of 1 to n number in 2 set [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
problem link : https://codeforces.com/contest/1295/problem/E
this problem states that there is permutation of 1 to n number such that every number occur only once
eg. p = [ 1,2,3] or [2,1,3] for n = 3.
now for every permutation in p there is a cost ci for the ith element of permutation p. whenever I move the ith element form one set to another i have to pay ci.
So, the question asks me to break the permutation in two set at any position k such that 1 <= k < n. Basically no set should be empty. Now the condition is that each element of set1 = (1 to k) should be less from set2 = (k+1, n). so to do so i have two operation , either i can move an element from set1 to set2 or vice versa. performin this operation on ith element wold cost me the ci amount. If either set1 or set2 is empty the condition is met.
eg
p = [3,1,2] c = [7,1,4].
set1 = [3,1] & set2 = [2].
so now we can send 2 from set2 to set1 with minimum cost of 4.
for more example please refer to problem. Link is above.
my approach :
for any k we need to have 1 to k element in set1 and rest in set2.
So lets start from i = 1 and keep on moving till i = n-1 && at every position I maintain the pfx ans.
To calculate the pfx array at every pos = i if the p[i] > i then we need to add the cost because we have to transfer the element to set2 and if it is less than i then we need to substract because we wanted it before so we had it in our total cost. but now we don't want it to be in our cost since we have the value. similarly I have also calculated for every position if I had the cur value or not.
here is my code. It passes many test cases but keeps on failing at 10th. cant understand the reason.
help please.
#include <bits/stdc++.h>
#define ll unsigned long long
#define pii pair<int,int>
using namespace std;
int main(void)
{
ll n , ans, prc3=0;
cin>>n;
vector<ll> p(n+1),a(n+1);
for(ll i=1; i<=n; i++) cin>>p[i];
for(ll i=1; i<=n; i++) cin>>a[p[i]], prc3 += a[p[i]];
ll prc1=0, prc2=0;
ll ans1=INT_MAX, ans2=INT_MAX, ans3=INT_MAX;
vector<bool> vst(n+1,false);
for(ll i=1; i<n; i++)
{
if(p[i]>i)
{
prc1 += a[p[i]];
}
else if(p[i]<i)
{
prc1 -= a[p[i]];
}
if(vst[i])
{
prc1 -= a[i];
}
vst[p[i]] = true;
if(!vst[i])
{
prc1 += a[i];
}
ans1 = min(ans1,prc1);
prc2 += a[p[i]];
ans2 = min(ans2,prc2);
prc3 -= a[p[i]];
ans3 = min(ans3,prc3);
}
ans = min(ans1,ans2);
ans = min(ans,ans3);
cout << ans << endl;
return 0;
}
I'm not sure what your code is attempting to do exactly, but from struggling with this question myself and finally reading the editorial, it seems to me that achieving a solution within the constraints requires a tree data structure.
As I understand, we keep a variable, k, that represents the highest number in the left side. We start k at 1 and we iterate up to n. At the same time, we keep a tree, where each key, i, points to the cost of creating the current k partition starting at position i.
When we increment k, all the is that are the partition starting-positions greater than or equal to the position of k in the starting list will not need that element moved so we update all those is, subtracting A[p[k]] from each one in O(log n) time using the tree; and update all the is that point to partition starting-positions less than k, adding the cost of that move to each one. We take the minimum cost on each iteration.
As far as I know, updates on a segment in O(log n) time would require a tree data structure.

Why does the longest prefix which is also suffix calculation part in the KMP have a time complexity of O(n) and not O(n^2)?

I was going through the code of KMP when I noticed the Longest Prefix which is also suffix calculation part of KMP. Here is how it goes,
void computeLPSArray(char* pat, int M, int* lps)
{
int len = 0;
lps[0] = 0;
int i = 1;
while (i < M) {
if (pat[i] == pat[len]) {
len++;
lps[i] = len;
i++;
}
else
{
if (len != 0) {
len = lps[len - 1]; //<----I am referring to this part
}
else
{
lps[i] = 0;
i++;
}
}
}
}
Now the part where I got confused was the one which I have shown in comments in the above code. Now we do know that when a code contains a loop like the following
int a[m];
memset(a, 0, sizeof(a));
for(int i = 0; i<m; i++){
for(int j = i; j>=0; j--){
a[j] = a[j]*2;//This inner loop is causing the same cells in the 1
//dimensional array to be visited more than once.
}
}
The complexity comes out to be O(m*m).
Similarly if we write the above LPS computation in the following format
while(i<M){
if{....}
else{
if(len != 0){
//doesn't this part cause the code to again go back a few elements
//in the LPS array the same way as the inner loop in my above
//written nested for loop does? Shouldn't that mean the same cell
//in the array is getting visited more than once and hence the
//complexity should increase to O(M^2)?
}
}
}
It might be that the way I think complexities are calculated is wrong. So please clarify.
If expressions do not take time that grows with len.
Len is an integer. Reading it takes O(1) time.
Array indexing is O(1).
Visiting something more than once does not mean you are higher O notation wise. Only if the visit count grows faster than kn for some k.
If you carefully analyze the algorithm of creating prefix table, you may notice that the total number of rollbacked positions could be m at most, so the upper bound for total number of iterations is 2*m which yields O(m)
Value of len grows alongside the main iterator i and whenever there is a mismatch, len drops back to zero value but this "drop" cannot exceed the interval passed by the main iterator i since the start of match.
For example, let's say, the main iterator i started matching with len at position 5 and mismatched at position 20.
So,
LPS[5]=1
LPS[6]=2
...
LPS[19]=15
At the moment of mismatch, len has a value of 15. Hence it may rollback at most 15 positions down to zero, which is equivalent to the interval passed by i while matching. In other words, on every mismatch, len travels back no more than i has traveled forward since the start of match

Intuition behind incrementing the iteration variable?

I am solving a question on LeetCode.com:
Given an array with n objects colored red, white or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white and blue. Here, they use the integers 0, 1, and 2 to represent the color red, white, and blue respectively. [The trivial counting sort cannot be used].
For the input: [2,0,2,1,1,0]; the output expected is: [0,0,1,1,2,2].
One of the highly upvoted solutions goes like this:
public void sortColors(vector<int>& A) {
if(A.empty() || A.size()<2) return;
int low = 0;
int high = A.size()-1;
for(int i = low; i<=high;) {
if(A[i]==0) {
// swap A[i] and A[low] and i,low both ++
int temp = A[i];
A[i] = A[low];
A[low]=temp;
i++;low++;
}else if(A[i]==2) {
//swap A[i] and A[high] and high--;
int temp = A[i];
A[i] = A[high];
A[high]=temp;
high--;
}else {
i++;
}
}
}
My question is, why is i incremented when A[i]==0 and A[i]==1 and not when A[i]==2? Using pen and paper, the algorithm just works to give me the answer; but could you please provide some intuition?
Thanks!
This steps through the array and maintains the constraint that the elements 0..i are sorted, and all either 0 or 1. (The 2's that were there get swapped to the end of the array.)
When A[i]==0, you're swapping the element at i (which we just said was 0) with the element at low, which is the first 1-element (if any) in the range 0..i. Hence, after the swap, A[i]==1 which is OK (the constraint is still valid). We can safely move forward in the array now. The same is true if A[i]==1 originally, in which case no swap is performed.
When A[i]==2, you're essentially moving element i (which we just said was 2) to the end of the array. But you're also moving something from the end of the array into element i's place, and we don't know what that element is (because we haven't processed it before, unlike the A[i]==0 case). Hence, we cannot safely move i forward, because the new element at A[i] might not be in the right place yet. We need another iteration to process the new A[i].
That is, because for 0s and 1s, only items left of the current item are handled and those have already been reviewed / sorted. Only for 2s items from the right end of the array are handled, which haven't been looked at yet.
To be more specific: In this specific example only three different states are handled:
the current item being reviewed equals 0: in this case this sorting algorithm just puts this item at the end of all zeros, which have already been sorted (aka A[low]). Also the item which was at A[low] before can only be a 0 or 1 (since they have already sorted) which means you can just swap with the current item and not break the sequence. Now the interesting part: up until now, every item from A[0] over A[low] to A[i] has been already sorted, so the next item which has to be reviewed will be A[i + 1], hence the i++
the current item equals 1: in this case, no swapping has to be done, since all 0s and 1s has already been put in A[0] to A[i - 1] and all 2s have already been put at the end of the array. That means, the next item to be reviewed is A[i + 1], hence the i++
the current item equals 2: in this case, the current item will be put at the end of the array, next to (i.e., to the left of) all the other already sorted 2s (A[high]). The item, which will be swapped from A[high] to A[i] has not been sorted yet and therefor has to be reviewed in the next step, hence th i = i;

Arrays not filling in as expected in C++ [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I just started trying to learn C++ yesterday, and one of my goals for the near future is to make a matrix multiplication function.
Before trying that, I wanted to get a feel of how arrays work, so I made a simple program that is supposed to make two arrays that represent (mathematical) vectors in 3D space and take their dot product. Below is the code that I wrote.
/*Initializing two vectors, v1 and v2*/
int v1[3] = { 0 };
int v2[3] = { 0 };
int sum = 0; //This will become the sum for the dot product
int i=0; //counter for the following loop
for(; i<3; ++i)
v1[i] = v2[i] = i+1; //This should make both vectors equal {1,2,3} at the end of the loop
sum += v1[i]*v2[i]; //Component-wise, performing the dot product operation
std::cout<< sum <<std::endl;
return 0;
When the code is done running, the output is supposed to come out to be 1*1 +2*2 +3*3 = 14
However, the output is actually coming out as 647194768, which doesn't seem to make any sense. I heard from some friends that in C++, if you aren't careful about initializing the arrays, then some crazy stuff happens, but I'm completely dumbfounded how something this simple could mess up so badly.
Could you provide some deeper insight into why this is happening, and what about C++'s logic causes this?
You are accidentally putting the sum += line outside the for loop. This is because you have no braces on the loop. So only the first line v1[i]... is included in the for loop. Change it like this:
/*Initializing two vectors, v1 and v2*/
int v1[3] = { 0 };
int v2[3] = { 0 };
int sum = 0; //This will become the sum for the dot product
for(int i=0; i<3; ++i)
{
v1[i] = v2[i] = i+1; //This should make both vectors equal {1,2,3} at the end of the loop
sum += v1[i]*v2[i]; //Component-wise, performing the dot product operation
}
std::cout<< sum <<std::endl;
return 0;
Note the use of braces { .. } around the for loop statements. Now this gives the correct answer: 14.
As you ask deeper insight here i am writing some explanation of your code
int v1[3] = { 0 };
int v2[3] = { 0 };
Initializing v1 and v2 with 0,
int sum = 0; //This will become the sum for the dot product
Here you Initializing sum with 0 (GOOD)
int i=0; //counter for the following loop
for(; i<3; ++i)
v1[i] = v2[i] = i+1; //This should make both vectors equal {1,2,3} at the end of the loop
sum += v1[i]*v2[i]; //Component-wise, performing the dot product operation
Here you make mistake as you did not provide {..} compiler will consider first list in loop statement. like below
v1[0] = v2[0] = 0+1
v1[1] = v2[1] = 1+1
v1[2] = v2[2] = 2+1
Now second line will come in picture,
Note that now i is become 3.
sum += v1[i]*v2[i];
Here, you try to access invalid location of an array (4th one)
that's the reason why you got 647194768
You got junk value nothing else
Correct code is already given by metacubed, so I am not writing here,
best of luck for you further study.

Array balancing point

What is the best way to solve this?
A balancing point of an N-element array A is an index i such that all elements on lower indexes have values <= A[i] and all elements on higher indexes have values higher or equal A[i].
For example, given:
A[0]=4 A[1]=2 A[2]=7 A[3]=11 A[4]=9
one of the correct solutions is: 2. All elements below A[2] is less than A[2], all elements after A[2] is more than A[2].
One solution that appeared to my mind is O(nsquare) solution. Is there any better solution?
Start by assuming A[0] is a pole. Then start walking the array; comparing each element A[i] in turn against A[0], and also tracking the current maximum.
As soon as you find an i such that A[i] < A[0], you know that A[0] can no longer be a pole, and by extension, neither can any of the elements up to and including A[i]. So now continue walking until you find the next value that's bigger than the current maximum. This then becomes the new proposed pole.
Thus, an O(n) solution!
In code:
int i_pole = 0;
int i_max = 0;
bool have_pole = true;
for (int i = 1; i < N; i++)
{
if (A[i] < A[i_pole])
{
have_pole = false;
}
if (A[i] > A[i_max])
{
i_max = i;
if (!have_pole)
{
i_pole = i;
}
have_pole = true;
}
}
If you want to know where all the poles are, an O(n log n) solution would be to create a sorted copy of the array, and look to see where you get matching values.
EDIT: Sorry, but this doesn't actually work. One counterexample is [2, 5, 3, 1, 4].
Make two auxiliary arrays, each with as many elements as the input array, called MIN and MAX.
Each element M of MAX contains the maximum of all the elements in the input from 0..M. Each element M of MIN contains the minimum of all the elements in the input from M..N-1.
For each element M of the input array, compare its value to the corresponding values in MIN and MAX. If INPUT[M] == MIN[M] and INPUT[M] == MAX[M] then M is a balancing point.
Building MIN takes N steps, and so does MAX. Testing the array then takes N more steps. This solution has O(N) complexity and finds all balancing points. In the case of sorted input every element is a balancing point.
Create a double-linked list such as i-th node of this list contains A[i] and i. Traverse this list while elements grow (counting maximum of these elements). If some A[bad] < maxSoFar it can't be MP. Remove it and go backward removing elements until you find A[good] < A[bad] or reach the head of the list. Continue (starting with maxSoFar as maximum) until you reach end of the list. Every element in result list is MP and every MP is in this list. Complexity is O(n) since is maximum of steps is performed for descending array - n steps forward and n removals.
Update
Oh my, I confused "any" with "every" in problem definition :).
You can combine bmcnett's and Oli's answers to find all the poles as quickly as possible.
std::vector<int> i_poles;
i_poles.push_back(0);
int i_max = 0;
for (int i = 1; i < N; i++)
{
while (!i_poles.empty() && A[i] < A[i_poles.back()])
{
i_poles.pop_back();
}
if (A[i] >= A[i_max])
{
i_poles.push_back(i);
}
}
You could use an array preallocated to size N if you wanted to avoid reallocations.