Insertion into a binary heap - algorithm

If I have an array representing a minimum binary heap that contains the values {2, 8, 3, 10, 16, 7, 18, 13, 15}, what would the array look like after inserting the value of 4? Also, how would I demonstrate this to be correct?
I deduced it would be 2,4,3,10,8,7,18,13,15,16. Is that correct?

To demonstrate that your min heap is correct, you need to prove recursively that your child nodes are larger than your root node
If your root node is n, your child nodes are 2n+1 and 2n+2, so iterate through your tree and check if child nodes are greater than parent. If this logic is not satisfied anywhere then your heap is bad.
2
8 3
10 16 7 18
13 15
push at end
2
8 3
10 **16** 7 18
13 15 4
compare and replace with parent
2
**8** 3
10 4 7 18
13 15 16
compare and replace with parent-no replacement
**2**
4 3
10 8 7 18
13 15 16

Related

How to replace entries with smaller values while keeping order?

What is an efficient algorithm to replace the values in an image while
minimizing the largest value and maintaining order?
Background
I have a 8.5Gb image which is represented as a rows and columns.
Suppose we have a smaller version (there are no duplicates in input):
4, 5, 9,
2, 3, 7,
8, 6, 1
I need to replace the entries at each pixel to the smallest positive value possible (greater than zero) in the entire matrix
while preserving the row-wise and column-wise ordering.
One possible output (duplicates allowed here) is the following and the maximum value is 5 ( I do not believe we can reduce it to 4):
2, 3, 4,
1, 2, 3,
5, 4, 1
The reason it works:
Input: First Row: 4 < 5 < 9 and first Column: 4 > 2 < 8
Output: First Row: 2 < 3 < 4 and First Column 2 > 1 < 5 (column)
The orderings are being maintained. The same for the other rows and columns:
5 > 3 < 6 <=> 3 > 2 < 4
...
...
----------------------------------------- Attempt: My wrong algorithm -----------------------------------------
1. Each row and column will contain unique elements. So start with the first row and assign integers from the range {1, total the number of rows}:
1 2 3
x x x
x x x
The maximum in that row is currently at 3.
2. Go to the next row which is 2,3,7 and again assign numbers in the range {1, total number of rows}. When we assign 1 we look at all the previous rows if there are conflicts. In this case 1 is already present in the previous row. And we need a number which is smaller than 1. So place a zero there (I will offset every entries by on later).
1 2 3
0 1 2
* * *
The maximum in that row is currently 2.
3. Go to the next row and again fill as above. But 1 already occurred before and we need a number larger than the first and second rows:
So, try 2. The next number needs to be larger than 2 and 1 (column) and smaller than 2 (row). That is a huge problem. I need to change too many cells each time.
For severe clarity, I'll add 10 to each of your values.
Input Ordering
14 15 19 - - -
12 13 17 - - -
18 16 11 - - -
Consider each of the values in order, smallest to largest. Each element receives an ordering value that is the smallest integer available at that location. "Available" means that the assigned number is larger than any in the same row or column.
11 and 12 aren't in the same row or column, so we can assign both of those immediately.
Input Ordering
14 15 19 - - -
12 13 17 1 - -
18 16 11 - - 1
When we consider 13, we see that it is in the same row with a 1, so it must have the next larger value:
Input Ordering
14 15 19 - - -
12 13 17 1 2 -
18 16 11 - - 1
14 has the same problem, being above a 1:
Input Ordering
14 15 19 2 - -
12 13 17 1 2 -
18 16 11 - - 1
Continue this process for each number. Take the maximum of the orderings in that number's row and column. Add 1 and assign that ordering.
Input Ordering
14 15 19 2 3 -
12 13 17 1 2 -
18 16 11 - 4 1
Input Ordering
14 15 19 2 3 4
12 13 17 1 2 3
18 16 11 5 4 1
There's a solution. The "dominance" path 18 > 16 > 15 > [14 or 13] > 12 demonstrates that 5 is the lowest max value.
You can also solve this by converting the locations to a directed graph. Nodes in the same row or column have an edge connecting them; the edge is directed from the smaller to the larger. It will be sufficient to order the values and merely connect the adjacent values: given 14->15 and 15->19, we don't need 14->19 as well.
Add a node 0 with label 0 and an edge to each node that has no other input edges.
Now follow a typical labeling iteration: any node with all its inputs labeled receives a label that is one more than the largest of its inputs.
This is the same algorithm as the above, but the correctness and minimalism are much easier to see.
14 -> 15 -> 19
12 -> 13 -> 17
11 -> 16 -> 18
12 -> 14 -> 18
13 -> 15 -> 16
11 -> 17 -> 19
0 -> 11
0 -> 12
Now, if we shake out the topology of this, starting on the left, we get:
0 11 13 17
12 14 15 16 18
19
This makes the numbering obvious: each node is labeled with the length of its longest path from the start node.
Your memory problem should be edited into your question proposal, or given as a new question. You have non-trivial dependencies along rows and columns. If your data do not fit into memory, then you may want to make a disk-hosted data base to store your pre-processed data. For instance, you could store the graph as a list of edges keyed by dependencies:
11 none
12 none
13 12
14 12
15 13, 14
16 11, 15
17 11, 13
18 14, 16
19 15, 17
You haven't described the shape of your data. At the very worst, you should be able to build this graph data base with one pass to do the rows, and then one pass per column -- or multiple columns in each pass, depending on how many you can fit into memory at once.
Then you can apply the algorithm to the items int he data base. You can speed it up if you keep in memory, not only all nodes with no dependencies, but another list with few dependencies -- "few" being dependent on your memory availability.
For instance, make one pass over the data base to grab every cell with 0 or 1 dependencies. Put the independent nodes in your "active" list; as you process those, add nodes only from the "1-dependency" list as they're freed up. Once you've exhausted those sub-graphs, then make a large pass to (1) update the data base; (2) extract the next sets of nodes with 0 or 1 dependency.
Let's look at this with the example you gave. First, we make a couple of lists from the original graph:
0-dep 11, 12
1-dep 13 (on 12), 14 (on 12)
This pass is trivial: we assign 1 to cells 11 and 12; 2 to cells 13 and 14. Now update the graph:
node dep done (assigned values)
15 none 2, 2
16 15 1
17 none 1, 2
18 16 2
19 15, 17
Refresh the in-memory lists:
0-dep 15, 17
1-dep 16 (on 15), 18 (on 16)
On this pass, both 15 and 17 depend on a node with value 2, so they are both assigned 3. Resolving 15 frees node 16, which gets value 4. This, in turn, frees up node 18, which gets the value 5.
In one final pass, we now have node 19 with no outstanding dependencies. it's maximum upstream value is 3, so it gets the value 4.
In the worst case -- you can't even hold all independent nodes in memory at once -- you can still grab as many as you can fit, assign their values in an in-memory pass, and return to the disk for more to process.
Can you handle the data manipulations from here?

Euler18 dynamic algorithm

Given the array [5, 4, 12, 3, 11, 7, 2, 8, 1, 9] that forms a triangle like so:
5
4 12
3 11 7
2 8 1 9
Result should be 5 + 12 + 7 + 9 = 31.
Write a function that will traverse the triangle and find the largest possible sum of values when you can go from one point to either directly bottom left, or bottom right.
Refering to the dynamic algorithm in that link:
http://www.mathblog.dk/project-euler-18/
Result is 36.
5
4 12
3 11 7
2 8 1 9
5
4 12
11 19 16
5
23 31
36
Where is my mistake ??
The description of Problem 18 starts with an example where the optimal path is “left-right-right”. So you get a new choice of direction after every step, which means that after taking the first step to the right, you are still free to take the second step to the left and eventually come up with 5+12+11+8=36 as the optimal solution in your example, larger than the 31 you assumed. So the computation is correct in solving the problem as described. Your assumption about choosing a direction only once and then sticking with that choice would lead to a different (and rather boring) problem.

Matrix coil (serpentine)

there!
I have a problem in java to generate a matrix like this :
When n= 4
{{1 4 5 16},
{2 3 6 15},
{9 8 7 14},
{10 11 12 13}};
Matrix shoud contain numbers from 1 to n*n.
I do not want any code, I just want to see how the matrix looks like when n=5 and n=6.
I have searched on the internet and found just about the spiral matrix, but not this one.
Thank you!
I think the production rule of this matrix is to start in the top left corner, then fill it in the smallest possible loop by starting counter-clockwise, switching between clockwise and counter-clockwise as soon as the boundary is met.
So, for n = 5 it would look like this:
{{ 1 4 5 16 17},
{ 2 3 6 15 18},
{ 9 8 7 14 19},
{10 11 12 13 20},
{25 24 23 22 21}};
And for n = 6 it would look like this:
{{ 1 4 5 16 17 36},
{ 2 3 6 15 18 35},
{ 9 8 7 14 19 34},
{10 11 12 13 20 33},
{25 24 23 22 21 32},
{26 27 28 29 30 31}};
There are some interesting invariants.
In the first row, every second entry is the square of an even, starting with 4 (2).
In the first column, every second entry is the square of an odd, starting with 1 (1).
The production of the diagonal is F(n) := n == 1 ? 1 : F(n-1) + 2(n-1)
Nice stuff, have fun programming with it.

Build heap algorithm(s) on an array.Generate outcomes without brute-forcing

The Build-Heap algorithm given in CLRS
BUILD-MAX-HEAP(A)
1 heap-size[A] ← length[A]
2 for i ← ⌊length[A]/2⌋ downto 1
3 do MAX-HEAPIFY(A, i)
It produces only One of several possible cases.Are there other algorithms which would yield a different case than that of the above algorithm.
For input array
A={4,1,3,2,16,9,10,14,8,7}
Build-Heap produces A={16,14,10,8,7,9,3,2,4,1} which satisfies heap property.
May be this is the most efficient algorithm to build a heap out of an array but there are several other permutations of the array which also have the heap property.
When i generated all permutations of the array and performed a test for heap property.I got 3360 permutations of the array which had the heap property.
Count1 16 9 14 4 8 10 3 2 1 7
Count2 16 9 14 4 8 10 3 1 2 7
Count3 16 9 14 4 8 10 2 1 3 7
Count4 16 9 14 4 8 10 2 3 1 7
Count5 16 9 14 4 8 10 7 2 1 3
Count6 16 9 14 4 8 10 7 2 3 1
Count7 16 9 14 4 8 10 7 1 3 2
Count8 16 9 14 4 8 10 7 1 2 3
Count9 16 9 14 4 8 10 7 3 1 2
Count10 16 9 14 4 8 10 7 3 2 1
...........................................................
Count3358 16 8 14 7 4 9 10 2 1 3
Count3359 16 8 14 7 4 9 10 3 2 1
Count3360 16 8 14 7 4 9 10 3 1 2
So is there a different build-heap algorithm which would give an output which differs from that of the above algorithm or which gives some of the 3360 possible outcomes?
Once we have used the build-heap to get an array which satisfies the heap property.How can we generate maximum number of other cases using this array.We can swap the leaf nodes of the heap to generate some of the cases.Is there any other way to get more possible cases without checking all permutations for heap property test?
Given the range of values in the array and all values being distinct.Can we say anything about the total number of possible cases that will satisfy the heap property?
Any heap building algorithm will be sensitive to the order in which items are inserted. Even the Build-Heap algorithm will generate a different heap if you give it the same elements, but in a different order.
Remember that when you're building a heap, the partially-built part must maintain the heap property after each insertion. So that's going to limit the different permutations that can be generated by any particular algorithm.
Given a heap, it's fairly easy to generate at least some of the permitted permutations.
A node doesn't care about the relative size of its two child nodes. Therefore, you can swap the children of any node, then do a sift-up on the smaller of the two to ensure that the heap property is maintained for that subtree (i.e., if it's smaller than one of its sub-nodes, swap it with that sub-node, and continue doing the same down that path until it gets to a spot where it's larger than either sub-node, or it's moved close enough to the end of the array that it's a leaf node.

Quicksort algorithm

I used the quicksort algorithm to sort
11 8 9 4 2 5 3 12 6 10 7
and I got the list:
4 3 2 5 9 11 8 12 6 10 7.
5 was used as a pivot. Now I am stuck. How do I proceed to sort the lowersublist and the uppersublist?
pivot=5 11 8 9 4 2 5 3 12 6 10 7
Move pivot to position 0 5 8 9 4 2 11 3 12 6 10 7
i (position 1 = 8)
j (position 6 = 3) ⇒ swap 8 and 3 5 3 9 4 2 11 8 12 6 10 7
i (position 2 = 9)
j (position 4 = 2) ⇒ swap 9 and 2 5 3 2 4 9 11 8 12 6 10 7
i (position 3 = 4)
– no smaller elements than 5 ⇒ swap 5 and 4 4 3 2 5 9 11 8 12 6 10 7
– list after the partition
Quicksort is a recursive algorithm. Once you have sorted the elements by the pivot, you get two sets of items. The first with all elements smaller or equal to the pivot, and the second with all elements larger than the pivot. What you do now, is that you apply quicksort again to each of these sets (with an appropriate pivot).
To do this, you will have to choose a new pivot every time. You can do something like always pick the first element, or draw one at random.
Once you reach a point where a set contains only one element, you stop.
A good way to understand these things is to try to sort a deck of cards using this algorithm. All cards are face down, and you are only allowed to look at two cards at a time, compare these and switch them if necessary. You must pretend to not remember any of the cards that are face down for that to work.
A key component of the algorithm is that the chosen pivot value came from the original list, which means (in your case) the element with the value 5 is now in the correct final position after the first partitioning:
4 3 2 5 9 11 8 12 6 10 7
This should be fairly obvious and follows simple intuition. If every element to the left of an item is smaller than that item and every element to the right is larger, then the item must be in the correct, sorted position.
The insight necessary to understanding the entire Quicksort algorithm is that you can just keep doing this to each of the sublists -- the list of values to the left of the pivot and the list containing all values to the right -- to arrive at the final, sorted list. This is because:
Each partitioning puts one more element in its proper position
Each iteration removes one element -- the pivot -- from the list of elements left to process (which is why we'll eventually reach the base case of zero (or one, depending on how you do it) elements)
Let's assume you chose the partition value of 5 based on the following pseudo-code:
Math.floor(list.length / 2)
For our purposes, the actual choice of a pivot doesn't really matter. This one works for your orginal choice, so we'll go with it. Now, let's play this out 'till the end (starting where you left off):
concat(qs([4 3 2]), 5, qs([9 11 8 12 6 10 7])) =
concat(qs([2]), 3, qs([4]), 5, qs([9, 11, 8, 6, 10, 7]), 12, qs([])) =
concat(2, 3, 4, 5, qs([6, 7]), 8, qs([9, 11, 10]), 12) =
concat(2, 3, 4, 5, qs([6]), 7, qs([]), 8, qs([9, 10]), 11, qs([]), 12) =
concat(2, 3, 4, 5, 6, 7, 8, qs([9]), 10, qs([]), 11, 12) =
concat(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
Note that each time you see a single call to qs it will follow this pattern:
qs(<some_left_list>), <the_pivot>, qs(<some_right_list>)
And each call of qs on one line results in two more such calls on the following line (representing the processing of both new sublists (except note that I immediately decompose calls to qs on single-value lists)).
It's a good idea to go through this exercise yourself. Yes, with actual pen and paper.

Resources