Minimum Heap Algorithm - java

This is my minHeap algorithm however it doesn't function as expected:
public static int [] fixheap(int heap[], int n, int i){
int j=2*i;
int weight = heap[i];
while (j<=n){
if((j<n) && heap[j] > heap[j+1])
j++;
if(weight <= heap[j]) break;
else
heap[j/2] = heap[j];
j=j*2;
}
heap[j/2]= weight;
return heap;
}
public static void makeheap(int heap[], int n){
for (int i=n/2; i>=0; i--){
fixheap(heap, n ,i);
}
}
When the data elements are added in various orders the algorithm returns incorrect minHeaps. Can anyone see any apparent problems for this minimum heap algorithm?

You are comparing the wrong elements of the array for forming the heap. Try to dry run your program
As the array starts from the index 0, you should take i=n/2-1 initially here.
public static void makeheap(int heap[], int n){
for (int i=n/2 - 1; i>=0; i--){
fixheap(heap, n ,i);
}
}
And then you will have to change your fixheap function to get the correct value for j
j = i*2 + 1

I believe that the way you find the parent and/or the children is incorrect.
Think about it, if the left children is at index1 and the right at index2, how do I get to their parents at index0?
What about finding index0's children (index1 and index2)?

The folllwing code is in python, but I will highlight the lines that do the heavy lifting, and in the process hopefully present a different solution of creating a min-heap
heapArray = []
for heapKey in someArray:
insert(heapArray, int(heapKey))
return heapArray;
def insert(heapArray, heapKey):
heapArray.append(heapKey)
index_of_key = len(heapArray)-1
parent_index_of_key = (index_of_heap_key-1)/2
while index_of_key>0:
if(heapKey < heapArray[parent_index_of_key]):
__swap(index_of_key, parent_index_of_key, heapArray)
index_of_key = parent_index_of_key;
parent_index_of_key = (index_of_key-1)/2
else:
break # we have reached the right spot
In the above example, we re-create the heap (yes that means more memory, but for illustration purposes this maybe a good start). As we create the heap, we simply check the value of the newly inserted key with its parent (via parent_index_of_key).
If the parent is larger than its child, then we swap the value and update the indexes (both for the swapped key and its new parent). We repeat that process until we have either reached the top of the heap or if the heap key can't go any further up the chain
The in-place swaps are clearly more efficient, but the above is more intuitive and easy to follow. Clearly, I won't use the above code, where memory is a large constraint, but would consider it for cases where code conciseness and clarity trump memory utilization.

Related

Java Heap Space error while writing a program for Square root of an Integer

I am trying to find out the square root of an integer, but in case the integer value is too large for instance - 2147395599. Then the following program gives this exception.
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.aakash.BinarySearch.SquareRoot.mySqrt(SquareRoot.java:12)
at com.aakash.BinarySearch.SquareRoot.main(SquareRoot.java:8)
Process finished with exit code 1
Square root Program
package com.aakash.BinarySearch;
import java.util.Arrays;
public class SquareRoot {
public static void main(String[] args) {
int ans = mySqrt(2147395599);
System.out.println(ans);
}
public static int mySqrt(int x) {
int[] arrayUpton = new int[x];
int start =0;
int end = arrayUpton.length-1;
int mid = start + (start-end)/2;
for (int index = start; index <= end; index++) {
arrayUpton[index]=index+1;
}
for (int index = start; index < end; index++) {
if(arrayUpton[index]*arrayUpton[index]==x){
return arrayUpton[index];
} else if (arrayUpton[index]*arrayUpton[index]>x) {
return arrayUpton[index-1];
}
}
return 0;
}
}
You are attempting to allocate an array of nearly 2^31 integers. That will occupy 8GB which is (evidently) too large for your JVMs heap. (And it could well be too large for your computer.)
But your real problem is your algorithm.
You don't need to allocate a huge array to calculate integer square roots. Even if you do it by searching all (positive) int values.
Consider this: your code carefully sets each of the array elements to a number that is one greater than the array subscript. And then it retrieves the values from the array to use them. But if you know that arrayUpton[i] contains i + 1 ... you don't need to retrieve it. Just add 1 to i instead of fetching the (same) value from the array.
In addition:
Irrespective of the tag, your algorithm isn't implementing a binary search.
I'm not even convinced the algorithm will work.
I suggest you do some Googling to see if you can find a better integer square root algorithm.

Why does moving the calculation of an array length out of a recursive function increase runtime?

I'm practicing Java by working through algorithms on leetcode. I just solved the "Construct a binary tree from inorder and postorder traversal" problem and was playing with my code to try to get better performance (as measured by the leetcode compilation/testing). Here is the code I wrote:
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
if(inorder.length == 1){
TreeNode root = new TreeNode(inorder[0]);
return root;
}
if(inorder.length == 0)
return null;
//int j = inorder.length; //Calculate this once, instead of each time the for loop executes
return reBuild(inorder, postorder, 0, inorder.length - 1, 0, postorder.length - 1);
}
public TreeNode reBuild(int[] inorder, int[] postorder, int inStart, int inEnd, int postStart, int postEnd){ //j passed in as argument here
if(inStart > inEnd)
return null; //base case
int rIndex = 0;
int j = inorder.length;
TreeNode root = new TreeNode(postorder[postEnd]); //Root is the last item in the postorder array
if(inStart == inEnd)
return root; //This node has no children
//for(int i = 0; i < inorder.length; ++i)
for(int i = 0; i < j; ++i){ //Find the next root value in inorder and get index
if(inorder[i] == root.val){
rIndex = i;
break;
}
}
root.left = reBuild(inorder, postorder, inStart, rIndex - 1, postStart, postStart - inStart + rIndex - 1); //Build left subtree
root.right = reBuild(inorder, postorder, rIndex + 1, inEnd, postEnd - inEnd + rIndex, postEnd - 1); //Build right subtree
return root;
}
}
My question concerns the for loop in the reBuild function. My first submission calculated the length of inorder each time the loop ran, which is obviously inefficient. I then took this out, and stored the length in a variable j, and used that in the for loop instead. This gave me a boost of ~1ms runtime. So far, so good. Then, I tried moving the calculation of j to the buildTree function, rationalizing that I don't need to calculate it in each recursive call since it doesn't change. When I moved it there and passed it in as a parameter, my runtime went back up 1ms, but my memory usage decreased significantly. Is this a quirk of how leetcode measures efficiency? If not, why would that move increase runtime?
If by calculating the length you mean accessing inorder.length then this is likely why you are losing performance.
When created, arrays hold onto a fixed value for their length called "length". this is a value not a method(thus no real performance used).
If j is never changed (ie j always equals inorder.length) The compiler likely ignores "j = inorder.length;" and simply accesses inorder.length when it sees j. you are then adding complexity to the function call by passing j where inorder (and thus inorder.length) is also present. Though this depends on the compiler implementation and may not actually happen.
In terms of access time, I think public object variables are slower than in-scope variables (think access inorder then access length).
warning hardware talk:
Another thing to consider is registers. These are data storage locations on the CPU itself which the code is actually run from (think HDD/SSD>RAM>cache>registers) and generally cant hold much more than 100 values at a time. Thus depending on the size of the current method (number of variables in scope) the code can run much faster or slower. Java seems to add a lot of overhead to this so for small functions, 1 or 2 extra values in scope can drastically affect the speed (as the program has to access cache).

SelectionSort variation not working

I have to implement a Selection Sort in Java according to these parameters:
Implement a variation to the SelectionSort that locates both the smallest and largest elements while scanning the list and positions them at the beginning and the end of the list, respectively. On pass number one, elements x0,...,xn-1 are scanned; on pass number two, elements x1,...,xn-2 are scanned; and so on.
I am passing the method an array of size 32, and when I print the array it is not sorted. What's the matter with my code?
static void selectionSort() {
scramble();
int smallIndex = 0; //index of smallest to test
int largeIndex = array.length - 1; //index of largest to test
int small = 0; //smallest
int large; //largest
int smallLimit = 0; //starts from here
int largeLimit = array.length - 1; //ends here
int store; //temp stored here
int store2;
for(int i = 0; i < array.length/2; i++) { //TODO not working...
small = array[smallLimit];
large = array[largeLimit];
for(int j = smallLimit; j <= largeLimit; j++) {
if(array[j] < small) {
smallIndex = j;
small = array[j];
}
else if(array[j] > large) {
largeIndex = j;
large = array[j];
}
}
store = array[smallLimit];
store2 = array[smallIndex];
array[smallLimit] = store2;
array[smallIndex] = store;
store = array[largeLimit];
array[largeLimit] = array[largeIndex];
array[largeIndex] = store;
smallLimit++;
largeLimit--;
}
print();
}
Think about the extreme cases: what happens when the largest or smallest item is found at smallLimit or largeLimit. When that happens you have two problems:
largeIndex and smallIndex are not set. They maintain their values from a previous iteration.
Swapping the smallest item to its correct place moves the largest item. The second swap moves the smallest item where the largest should go, and the largest ends up in a random location. Step through the code on paper or in a debugger if you find this hard to visualize.
These problems are easy to fix. You could have avoided the problem following a few guidelines:
Use fewer moving parts. You can always get the value of small using smallIndex, if you just used smallIndex there would be no danger of different variables falling out of step.
Declare the variables in the smallest possible scope. If smallIndex was declared in the loop body and not outside the compiler would have told you there's a chance it was not set before the swap.
Destructive updates like the first swap here can always make a previous calculation obsolete. When you can't avoid this from happening, look for ways two updates can step on each other's toes.
Like #Joni, clearly pointed out, there is big caveat with swapping two elements twice during a traversal of the array. Since you have to implement the sorting algorithm in-place, you need to take into account the positions of the elements to be swapped as it happens in succession.
Another limiting case that you need to see is when there are just three elements left i.e. the last iteration of the for loop. This is how I would go about it:
store = array[smallLimit];
store2 = array[smallIndex];
array[smallLimit] = small;
array[smallIndex] = store;
smallLimit++;
//No problem with swapping the first two elements
store = array[largeLimit];
//However the first swap might cause the other elements to shift
//So we do this check
if((array[largeIndex] == large))
{array[largeLimit] = array[largeIndex];
array[largeIndex] = store;
largeLimit--;
}
//Just a limiting case, where amongst the last three elements, first swap happens.
//The smallest element is in place, just take care of the other two elements.
if(largeLimit - smallLimit == 1){
if(array[largeLimit] != large){
array[smallLimit] = array[largeLimit];
array[largeLimit] = large;
largeLimit--;
}
}
Working DEMO for the snippet mentioned above, building upon your code. Hope it gets you started in the right direction.

Compare elements in an array of string in Java

I have to write a method that will compare elements in an array of strings and return the index of the largest element. It's going to be done recursively using a divide and conquer approach. I have an idea, and I was just looking to see if my idea was right or if it should be done in a different way.
I was planning on looking at the array from the left side to mid -1, then look at mid, and then look at mid +1 to right. I have a variable that will keep track of the largest index, and then after that make the recursive call for the left side and the right side.
Does that sound like a good way to approach this problem?
This is what I have so far:
public int longest()
{
longest(0, a.length-1);
return longestIndex;
}
private int longest( int left, int right)
{
int longestIndex;
int mid;
if(left > right)
{
longestIndex = -1;
}
else if(left == right)
{
longestIndex = 0;
}
else
{
longestIndex = 0;
mid = (left + right) / 2;
longest(left, mid - 1);
if (a[mid].compareTo(a[longestIndex]) > 0)
{
longestIndex = mid;
}
longest(mid + 1, right);
}
return longestIndex;
}
Also, since the methods are supposed to return an int, how would I pass the longestIndex n the private method up to the public method so that it would show up in my test program when longest is called?
Does it have to be recursive? Using recursion for this sounds like a case of:
And your recursion looks totally wrong anyways, because not only you are not keeping track of the actual index but also your base cases and recursive calls don't make any sense.
If I were compelled to use recursion, I would do something like:
int longest(array):
return longest_helper(0, 0, array)
int longest_helper(max_index, curr_idx, array):
# base case: reached the end of array
if curr_idx == array.length:
return max_index
if array[curr_idx].length > array[max_index].length:
max_index = curr_idx
# recursive call
return longest_helper(max_index, curr_idx + 1, array)
And then I would proceed to drop the class and tell the professor to give students problems where recursion is actually helpful next time around.
Since it doesn't look like the array is sorted, the easiest (and fastest) way to do this would just be go through the whole thing (pseudocode):
max_index = 0
max_length = array[0].length
for index in 1 .. array.length:
if array[index].length > max_length:
max_length = array[index].length
max_index = index
return max_index
This is your fourth question in two days on recursion. It is good that you are putting homework tag but your time would be better spent understanding how recursion works.
My recommendation is to take a few colored discs (poker chips or playing cards of a single suite work well), work out manually the recursive solution to Towers of Hanoi and then come back and look at the individual questions you have been asking.
In all likelihood you will be able to answer all the questions yourself. You would also be able to accept the answers, increasing you chances in future of getting responses when you face tougher questions.

Problem with recursive backtracking

Hey guys, recently posted up about a problem with my algorithm.
Finding the numbers from a set which give the minimum amount of waste
Ive amended the code slightly, so it now backtracks to an extent, however the output is still flawed. Ive debugged this considerablychecking all the variable values and cant seem to find out the issue.
Again advice as opposed to an outright solution would be of great help. I think there is only a couple of problems with my code, but i cant work out where.
//from previous post:
Basically a set is passed to this method below, and a length of a bar is also passed in. The solution should output the numbers from the set which give the minimum amount of waste if certain numbers from the set were removed from the bar length. So, bar length 10, set includes 6,1,4, so the solution is 6 and 4, and the wastage is 0. Im having some trouble with the conditions to backtrack though the set. Ive also tried to use a wastage "global" variable to help with the backtracking aspect but to no avail.
SetInt is a manually made set implementation, which can add, remove, check if the set is empty and return the minimum value from the set.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package recursivebacktracking;
/**
*
* #author User
*/
public class RecBack {
int WASTAGE = 10;
int BESTWASTAGE;
int BARLENGTH = 10;
public void work()
{
int[] nums = {6,1,2,5};
//Order Numbers
SetInt ORDERS = new SetInt(nums.length);
SetInt BESTSET = new SetInt(nums.length);
SetInt SOLUTION = new SetInt(nums.length);
//Set Declarration
for (int item : nums)ORDERS.add(item);
//Populate Set
SetInt result = tryCutting(ORDERS, SOLUTION, BARLENGTH, WASTAGE);
result.printNumbers();
}
public SetInt tryCutting(SetInt possibleOrders, SetInt solution, int lengthleft, int waste)
{
for (int i = 0; i < possibleOrders.numberInSet(); i++) // the repeat
{
int a = possibleOrders.min(); //select next candidate
System.out.println(a);
if (a <= lengthleft) //if accecptable
{
solution.add(a); //record candidate
lengthleft -= a;
WASTAGE = lengthleft;
possibleOrders.remove(a); //remove from original set
if (!possibleOrders.isEmpty()) //solution not complete
{
System.out.println("this time");
tryCutting(possibleOrders, solution, lengthleft, waste);//try recursive call
BESTWASTAGE = WASTAGE;
if ( BESTWASTAGE <= WASTAGE )//if not successfull
{
lengthleft += a;
solution.remove(a);
System.out.println("never happens");
}
} //solution not complete
}
} //for loop
return solution;
}
}
Instead of using backtracking, have you considered using a bitmask algorithm instead? I think it would make your algorithm much simpler.
Here's an outline of how you would do this:
Let N be number of elements in your set. So if the set is {6,1,2,5} then N would be 4. Let max_waste be the maximum waste we can eliminate (10 in your example).
int best = 0; // the best result so far
for (int mask = 1; mask <= (1<<N)-1; ++mask) {
// loop over each bit in the mask to see if it's set and add to the sum
int sm = 0;
for (int j = 0; j < N; ++j) {
if ( ((1<<j)&mask) != 0) {
// the bit is set, add this amount to the total
sm += your_set[j];
// possible optimization: if sm is greater than max waste, then break
// out of loop since there's no need to continue
}
}
// if sm <= max_waste, then see if this result produces a better one
// that our current best, and store accordingly
if (sm <= max_waste) {
best = max(max_waste - sm);
}
}
This algorithm is very similar to backtracking and has similar complexity, it just doesn't use recursion.
The bitmask basically is a binary representation where 1 indicates that we use the item in the set, and 0 means we don't. Since we are looping from 1 to (1<<N)-1, we are considering all possible subsets of the given items.
Note that running time of this algorithm increases very quickly as N gets larger, but with N <= around 20 it should be ok. The same limitation applies with backtracking, by the way. If you need faster performance, you'd need to consider another technique like dynamic programming.
For the backtracking, you just need to keep track of which element in the set you are on, and you either try to use the element or not use it. If you use it, you add it to your total, and if not, you proceeed to the next recursive call without increasing your total. Then, you decrement the total (if you incremented it), which is where the backtracking comes in.
It's very similar to the bitmask approach above, and I provided the bitmask solution to help give you a better understanding of how the backtracking algorithm would work.
EDIT
OK, I didn't realize you were required to use recursion.
Hint1
First, I think you can simplify your code considerably by just using a single recursive function and putting the logic in that function. There's no need to build all the sets ahead of time then process them (I'm not totally sure that's what you're doing but it seems that way from your code). You can just build the sets and then keep track of where you are in the set. When you get to the end of the set, see if your result is better.
Hint2
If you still need more hints, try to think of what your backtracking function should be doing. What are the terminating conditions? When we reach the terminating condition, what do we need to record (e.g. did we get a new best result, etc.)?
Hint3
Spoiler Alert
Below is a C++ implementation to give you some ideas, so stop reading here if you want to work on it some more by yourself.
int bestDiff = 999999999;
int N;
vector< int > cur_items;
int cur_tot = 0;
int items[] = {6,1,2,5};
vector< int > best_items;
int max_waste;
void go(int at) {
if (cur_tot > max_waste)
// we've exceeded max_waste, so no need to continue
return;
if (at == N) {
// we're at the end of the input, see if we got a better result and
// if so, record it
if (max_waste - cur_tot < bestDiff) {
bestDiff = max_waste - cur_tot;
best_items = cur_items;
}
return;
}
// use this item
cur_items.push_back(items[at]);
cur_tot += items[at];
go(at+1);
// here's the backtracking part
cur_tot -= items[at];
cur_items.pop_back();
// don't use this item
go(at+1);
}
int main() {
// 4 items in the set, so N is 4
N=4;
// maximum waste we can eliminiate is 10
max_waste = 10;
// call the backtracking algo
go(0);
// output the results
cout<<"bestDiff = "<<bestDiff<<endl;
cout<<"The items are:"<<endl;
for (int i = 0; i < best_items.size(); ++i) {
cout<<best_items[i]<<" ";
}
return 0;
}

Categories