How to know if an index in a binary heap is on an odd level? - c++

If I have a binary heap , with the typical properties of left neighbor of position "pos" being (2*pos)+1 while right neighbor is (2*pos)+2 and parent node in (pos-1) )/ 2, how can I efficiently determine if a given index represents a node on an odd level (with the level of the root being level 0) ?

(Disclaimer: This is a more complete answer based on Jarod42's comment.)
The formula you want is:
floor(log2(pos+1)) mod 2
To understand why, look at the levels of the first few nodes:
0 Level: 0
1 2 1
3 4 5 6 2
7 8 9 10 11 12 13 14 3
0 -> 0
1 -> 1
2 -> 1
3 -> 2
...
6 -> 2
7 -> 3
...
The first step is to find a function that will map node numbers to level numbers in this way. Adding one to the number and taking a base 2 logarithm will give you almost (but not quite) what you want:
log2 (0+1) = log2 1 = 0
log2 (1+1) = log2 2 = 1
log2 (2+1) = log2 3 = 1.6 (roughly)
log2 (3+1) = log2 4 = 2
....
log2 (6+1) = log2 7 = 2.8 (roughly)
log2 (7+1) = log2 8 = 3
You can see from this that rounding down to the nearest integer in each case will give you the level of each node, hence giving us floor(log2(pos+1)).
As Jarod42 said, it's then a case of looking at the parity of the level number, which just involves taking the number mod 2. This will give either 0 (the level is even) or 1 (the level is odd).

Related

Using AND bitwise operator between a number, and its negative counterpart

I stumbled upon this simple line of code, and I cannot figure out what it does. I understand what it does in separate parts, but I don't really understand it as a whole.
// We have an integer(32 bit signed) called i
// The following code snippet is inside a for loop declaration
// in place of a simple incrementor like i++
// for(;;HERE){}
i += (i&(-i))
If I understand correctly it uses the AND binary operator between i and negative i and then adds that number to i. I first thought that this would be an optimized way of calculating the absolute value of an integer, however as I come to know, c++ does not store negative integers simply by flipping a bit, but please correct me if I'm wrong.
Assuming two's complement representation, and assuming i is not INT_MIN, the expression i & -i results in the value of the lowest bit set in i.
If we look at the value of this expression for various values of i:
0 00000000: i&(-i) = 0
1 00000001: i&(-i) = 1
2 00000010: i&(-i) = 2
3 00000011: i&(-i) = 1
4 00000100: i&(-i) = 4
5 00000101: i&(-i) = 1
6 00000110: i&(-i) = 2
7 00000111: i&(-i) = 1
8 00001000: i&(-i) = 8
9 00001001: i&(-i) = 1
10 00001010: i&(-i) = 2
11 00001011: i&(-i) = 1
12 00001100: i&(-i) = 4
13 00001101: i&(-i) = 1
14 00001110: i&(-i) = 2
15 00001111: i&(-i) = 1
16 00010000: i&(-i) = 16
We can see this pattern.
Extrapolating that to i += (i&(-i)), assuming i is positive, it adds the value of the lowest set bit to i. For values that are a power of two, this just doubles the number.
For other values, it rounds the number up by the value of that lowest bit. Repeating this in a loop, you eventually end up with a power of 2. As for what such an increment could be used for, that depends on the context of where this expression was used.

Can we really avoid extra space when all the values are non-negative?

This question is a follow-up of another one I had asked quite a while ago:
We have been given an array of integers and another number k and we need to find the total number of continuous subarrays whose sum equals to k. For e.g., for the input: [1,1,1] and k=2, the expected output is 2.
In the accepted answer, #talex says:
PS: BTW if all values are non-negative there is better algorithm. it doesn't require extra memory.
While I didn't think much about it then, I am curious about it now. IMHO, we will require extra memory. In the event that all the input values are non-negative, our running (prefix) sum will go on increasing, and as such, sure, we don't need an unordered_map to store the frequency of a particular sum. But, we will still need extra memory (perhaps an unordered_set) to store the running (prefix) sums that we get along the way. This obviously contradicts what #talex said.
Could someone please confirm if we absolutely do need extra memory or if it could be avoided?
Thanks!
Let's start with a slightly simpler problem: all values are positive (no zeros). In this case the sub arrays can overlap, but they cannot contain one another.
I.e.: arr = 2 1 5 1 1 5 1 2, Sum = 8
2 1 5 1 1 5 1 2
|---|
|-----|
|-----|
|---|
But this situation can never occur:
* * * * * * *
|-------|
|---|
With this in mind there is algorithm that doesn't require extra space (well.. O(1) space) and has O(n) time complexity. The ideea is to have left and right indexes indicating the current sequence and the sum of the current sequence.
if the sum is k increment the counter, advance left and right
if the sum is less than k then advance right
else advance left
Now if there are zeros the intervals can contain one another, but only if the zeros are on the margins of the interval.
To adapt to non-negative numbers:
Do as above, except:
skip zeros when advancing left
if sum is k:
count consecutive zeros to the right of right, lets say zeroes_right_count
count consecutive zeros to the left of left. lets say zeroes_left_count
instead of incrementing the count as before, increase the counter by: (zeroes_left_count + 1) * (zeroes_right_count + 1)
Example:
... 7 0 0 5 1 2 0 0 0 9 ...
^ ^
left right
Here we have 2 zeroes to the left and 3 zeros to the right. This makes (2 + 1) * (3 + 1) = 12 sequences with sum 8 here:
5 1 2
5 1 2 0
5 1 2 0 0
5 1 2 0 0 0
0 5 1 2
0 5 1 2 0
0 5 1 2 0 0
0 5 1 2 0 0 0
0 0 5 1 2
0 0 5 1 2 0
0 0 5 1 2 0 0
0 0 5 1 2 0 0 0
I think this algorithm would work, using O(1) space.
We maintain two pointers to the beginning and end of the current subsequence, as well as the sum of the current subsequence. Initially, both pointers point to array[0], and the sum is obviously set to array[0].
Advance the end pointer (thus extending the subsequence to the right), and increase the sum by the value it points to, until that sum exceeds k. Then advance the start pointer (thus shrinking the subsequence from the left), and decrease the sum, until that sum gets below k. Keep doing this until the end pointer reaches the end of the array. Keep track of the number of times the sum was exactly k.

What is the maximum number of comparisons to heapify an array?

Is there a general formula to calculate the maximum number of comparisons to heapify n elements?
If not, is 13 the max number of comparisons to heapify an array of 8 elements?
My reasoning is as such:
at h = 0, 1 node, 0 comparisons, 1* 0 = 0 comparisons
at h = 1, 2 nodes, 1 comparison each, 2*1 = 2 comparisons
at h = 2, 4 nodes, 2 comparisons each, 4*2 = 8 comparisons
at h = 3, 1 node, 3 comparisons each, 1*3 = 3 comparisons
Total = 0 + 2 + 8 + 3 =13
Accepted theory is that build-heap requires at most (2N - 2) comparisons. So the maximum number of comparisons required should be 14. We can confirm that easily enough by examining a heap of 8 elements:
7
/ \
3 1
/ \ / \
5 4 8 2
/
6
Here, the 4 leaf nodes will never move down. The nodes 5 and 1 can move down 1 level. 3 could move down two levels. And 7 could move down 3 levels. So the maximum number of level moves is:
(0*4)+(1*2)+(2*1)+(3*1) = 7
Every level move requires 2 comparisons, so the maximum number of comparisons would be 14.

What will be the output of the following pseudo code for input 7?

Please help me to understand the following code and what will be the possiable output.
What will be the output of the following pseudo code for input 7?
1.Input n
2.Set m = 1, T = 0
3.if (m > n)
Go to step 9
5.else
T = T + m
m = m + 1
8.Go to step 3
9.Print T
0
n is less than n so go to step 9 which is print T which is equal to 0 as set in step 2.
T should be 28. It will loop till m>7 (since n=7) and in each iteration T adds m to itself, since T is 0 initially it is only summing up m after incrementing it by 1 in each iteration.So if you add 1+2+3.....+7 you get 28 and that is when the loop breaks since m is now equal to 8.
for m = 1 2 3 4 5 6 7 and for 8 m>n will be true and it will go to step 9
T=(T+M)= 1 3 6 10 15 21 28 basically T is a series where next is added as 2,3,4,5,6,7 to prev number 2 3 4 5 6 7 if one look from other angle

Formula Sequence

I need help finding the formula of the sequence for the next problem.
What I think and have for now is Sn=n(10^n-1)/9 but it just works in some cases...
Here is the description of the problem:
Description
Sn is based upon the sequence positive integers numbers. The value n can be found n times, so the first 25 terms of this sequence are as follows:
1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 6 6 7 7 7 7...
For this problem, you have to write a program that calculates the i-th term in the sequence. That is, determine Sn(i).
Input specification
Input may contain several test cases (but no more than 10^5). Each test case is given in a line of its own, and contains an integer i (1 <= i <= 2 * 10^9). Input ends with a test case in which i is 0, and this case must not be processed.
Output specification
For each test case in the input, you must print the value of Sn(i) in a single line.
Sample input
1
25
100
0
Sample output
1
7
14
Thanks solopilot! I made the code but the online judge show me Time Limit Exceeded, what could be my error?
#include <iostream> #include <math.h> using namespace std; int main() {int i;
int NTS;
cin>>i;
while (i>=1){
NTS=ceil((sqrt(8*i+1)-1)/2);
cout<<" "<<NTS<<endl;
cin>>i;
}
return 0;}
F(n) = ceiling((sqrt(8*n+1)-1)/2)
Say F(n) = a.
Then n ~= a * (a+1) / 2.
Rearranging: a^2 + a - 2n ~= 0.
Solving: a = F(n) = (-1 + sqrt(1+8n)) / 2.
Ignore the negative answer.
The pattern looks like a pyramid.
Level : 1 3 6 10 15 21 28...
No : 1 2 3 4 5 6 7...
Level = n(n+1)/2 => elements
3 = 3*4/2 => 6
6 = 6*7/2 => 21