Debugging Max Heap in Java - java

Awhile back I was programming in C++ and I found a tutorial on making a max heap. This was the code and it seems to produce a correctly order heap.`
#include <iostream>
const int size = 14;
static int A[size] = {1, 2, 5, 10, 2, 11, 12, 7, 23, 22, 34, 54, 12, 22};
int left(int i)
{
return (2*i)+1;
}
int right(int i)
{
return (2*i)+2;
}
//a leaf of a value less than the size of the array
//and larger than the center of the array
bool isLeaf(int i)
{
if(i >= (size/2) && i <= size)
{
return true;
}
return false;
}
void maxHeapify(int i)
{
//if it isn't a leaf it may need to be swapped
if(!isLeaf(i))
{
//if the value is less than it's right or left child
if(A[i] < A[left(i)] || A[i] < A[right(i)])
{
//if the left child is smaller
if(A[left(i)] > A[right(i)])
{
//swap the left child with the index
std::cout << "Swapping " << A[i] << " and " << A[left(i)] << std::endl;
int a = A[i];
A[i] = A[left(i)];
A[left(i)] = a;
//and run maxHeapify in it. This will push the value to
//it's lowest point and order all things below the parent
maxHeapify(left(i));
}
else
{
//else swap with the right child since it is larger
std::cout << "Swapping " << A[i] << " and " << A[right(i)] << std::endl;
int a = A[i];
A[i] = A[right(i)];
A[right(i)] = a;
//run maxheap on that value. This will push the value to it's lowest position
maxHeapify(right(i));
}
}
}
}
bool buildHeap()
{
//need to run for each node that is not a leaf
for(int i = (size/2); i >= 0; i--)
{
maxHeapify(i);
}
return true;
}
int main()
{
std::cout << "before: " << std::endl;
for(int i = 0; i < size; i++)
{
std::cout << A[i] << ", ";
}
std::cout << std::endl;
buildHeap();
std::cout << "After: " << std::endl;
for(int i = 0; i < size; i++)
{
std::cout << A[i] << ",";
}
std::cout << std::endl;
return 0;
}
The output of the above is:
Before:
1, 2, 5, 10, 2, 11, 12, 7, 23, 22, 34, 54, 12, 22,
Swapping 12 and 22
Swapping 11 and 54
Swapping 2 and 34
Swapping 10 and 23
Swapping 5 and 54
Swapping 5 and 12
Swapping 2 and 34
Swapping 2 and 22
Swapping 1 and 54
Swapping 1 and 22
Swapping 1 and 12
After:
54,34,22,23,22,12,12,7,10,2,2,11,5,1,
Currently I am studying for a midterm and I am trying to reproduce my code in java. I have been looking at this for awhile and I can't seem to find where I am going wrong. Here is the broken java:
Main.java
public class Main {
/**
* #param args
*/
public static void main(String[] args) {
int[] a = { 1, 2, 5, 10, 2, 11, 12, 7, 23, 22, 34, 54, 12, 22 };
System.out.println("Begfore");
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + ", ");
}
Heap h = new Heap(a);
h.buildHeap();
h.print();
System.out.println();
System.out.println(a.length);
}
}
Heap.java
public class Heap {
int[] heap;
public Heap(int[] a) {
// heap = new int[a.length];
heap = a;
}
public void buildHeap() {
for (int i = heap.length / 2; i >= 0; i--) {
maxHeapify(i);
}
}
public int getLeft(int a) {
return (2 * a) + 1;
}
public int getRight(int a) {
return (2 * a) + 2;
}
private boolean isLeaf(int a) {
if (a >= ((heap.length) / 2) && a <= heap.length) {
return true;
} else {
return false;
}
}
public void maxHeapify(int a) {
if (!isLeaf(a)) {
if (heap[a] < heap[getLeft(a)] || heap[a] < heap[getRight(a)]) {
if (getLeft(a) <= heap.length && getRight(a) < heap.length) {
if (heap[getLeft(a)] > heap[getRight(a)]) {
int watcher = heap[a];
heap[a] = heap[getLeft(a)];
heap[getLeft(a)] = watcher;
maxHeapify(getLeft(a));
} else {
int watcher = heap[a];
heap[a] = heap[getRight(a)];
heap[getRight(a)] = watcher;
maxHeapify(getRight(a));
}
}
}
}
}
public void print() {
System.out.println("heap");
for (int i = 0; i < heap.length; i++) {
System.out.print(heap[i] + ", ");
}
}
}
Which doesn't produce a correct max ordered heap.
Java output: 54, 34, 12, 23, 22, 12, 1, 7, 10, 2, 2, 11, 5, 22,

This code has some Basic problems. Let me explain them.
First of all in Max Heapify function, you do not need to check for the condition that whether it is a leaf or not. This brings me to your max heapify function call.
The heapify function is always called from indices heap.length/2 - 1 to 0, notice that you have not used the -1. This allows the heapify to always be saved from the leaves because in a binary heap whether max on min, the leaves are placed at indices heap.length/2 to heap.length-1.
Another mistake with this code is with the way indices are used. There are 2 ways to use indices.
Either use real indices from 0 to heap.length -1 in this case there should not be any condition such as
<=heap.length or >=heap.length
But you have used conditions like this in you heapify code.
Or use fake indices which range from 1 to heap.length and whenever you use them inside [ ] just subtract -1. This works perfectly in my java code.
Hope this helps. I can give you the java code if you want.

Related

Find the largest drop between two numbers in an array. What is the time complexity of this code?

I have an array full of numbers. I need to find the maximum difference between 2 numbers but the biggest number is before the smallest number in the array.
public static int maximalDrop(int[] a)
For example:
for the array 5, 21, 3, 27, 12, 24, 7, 6, 4 the result will be 23 (27 - 4)
for the array 5, 21, 3, 22, 12, 7, 26, 14 the result will be 18 (21 - 3)
I think I write it in time complexity O(N) is my code ok? What is that time complexity of my code? Here is the method that I write:
public static int maximalDrop(int[] a) {
int i = 0;
int temp = 0;
int result = -1;
int k = a.length - 1;
boolean finishCheckLoop = false;
while (k > i) {
if (a[i] < a[i + 1] || finishCheckLoop == true) {
i++;
finishCheckLoop = false;
} else if (a[i] >= a[k] || a[i] <= a[k]) {
if (a[k] < 0)
temp = Math.abs(a[k]) + a[i];
else if (a[k] > 0)
temp = a[i] - a[k];
result = Math.max(temp, result);
k--;
}
if (i == k) {
k = a.length - 1;
finishCheckLoop = true;
}
}
return result;
}
Your code seems to be O(N), but it is quite complex for the task.
A simpler (and faster) version:
public static int maximalDrop(int[] a) {
int maxDrop = 0;
int drop = 0;
int max = Integer.MIN_VALUE;
int cur;
for (int i = 0; i < a.length; i++) {
cur = a[i];
if (cur > max) {
max = cur;
}
drop = max - cur;
if (drop > maxDrop) {
maxDrop = drop;
}
}
return maxDrop;
}
Disclaimer, I don't really write java, so I'm not sure if the Integer.MIN_VALUE is correct.
Yes, your code has a time complexity of O(N), but it's not readable and was probably hard to write.
Almost all of us have this bad tendency to start coding before we know how to solve the problem.
The code presented here seems like a product of this technique.
To improve the code, we should pick up a pen and paper and think simple. Note that we need to return the maximal drop from left to right so there are quite a few cases
Let's keep high, low and maximalDrop variables:
The current number is a new low:
low = current number.
Update the maximalDrop if necessary.
The current number is a new high - the previous low is irrelevant.
Else - do nothing.
Now it's easy to code:
public static int maximalDrop(int[] a) {
if (a.length == 0) {
return -1;
}
int h = a[0], l = a[0];
int maxDrop = -1;
for (int curr : a) {
if (curr < l) {
l = curr;
maxDrop = Math.max(h - l, maxDrop);
} else if (curr > h) {
h = curr;
l = Integer.MAX_VALUE;
}
}
return maxDrop;
}
Output examples:
System.out.println(maximalDrop(new int[]{5, 21, 3, 27, 12, 24, 7, 6, 4})); // 23
System.out.println(maximalDrop(new int[]{5, 21, 3, 22, 12, 7, 26, 14})); // 18
System.out.println(maximalDrop(new int[]{5, 6})); // -1

Java: Binary Search

Is this an ok implementation of the binary search algorithm? It works but its an implementation I came up with and differs from my instructors. Can anyone punch a hole in it for me?
package algorithm.linearsearch;
public class BinarySearch {
public static void main(String[] args) {
System.out.println(binarySearch(
new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 26, 109, 1001, 1100 },
26));
}
private static int binarySearch(int[] array, int target) {
int p = 0;
int r = array.length - 1;
int q;
while (p <= r) {
q = (p + r) / 2;
if (array[q] == target) {
System.out.println("value: " + array[q]);
return q;
}
if (array[q] > target) {
r = q + 1;
} else {
p = q - 1;
}
}
return -1;
}
}
Just this
if (array[q] > target) {
r = q + 1;
} else {
p = q - 1;
}
should be
if (array[q] > target) {
r = q - 1; // index lower to current pivot
} else {
p = q + 1; // index upper to current pivot
}
One thing i can say. Your program is expected to return index if found or return -1 if not found. So you don't need to print value as its input taken from user regarding which element to find.
You need a check initially if your array is null return -1 to avoid null pointer exception which will happen when you calculate length of array.

How to iterate over array of integers to find a sequence based on an O(N) solution?

I saw following question and tried to find an answer for that.
Question: Given a sequence of positive integers A and an integer T, return whether there is a *continuous sequence* of A that sums up to exactly T
Example
[23, 5, 4, 7, 2, 11], 20. Return True because 7 + 2 + 11 = 20
[1, 3, 5, 23, 2], 8. Return True because 3 + 5 = 8
[1, 3, 5, 23, 2], 7 Return False because no sequence in this array adds up to 7
Note: We are looking for an O(N) solution. There is an obvious O(N^2) solution which is a good starting point but is not the final solution we are looking for.
My answer to above question is:
public class Tester {
public static void main(String[] args) {
int[] myArray = {23, 5, 4, 7, 2, 11};
System.out.println(isValid(myArray, 20));
}
public static boolean isValid(int[] array, int sum) {
int pointer = 0;
int temp = 0;
while (pointer < array.length)
{
for (int i = pointer; i < array.length; i++)
{
if (array[i] > sum)
break;
temp += array[i];
if (temp == sum)
return true;
else if (temp > sum)
break;
// otherwise continue
}
temp = 0;
pointer++;
}
return false;
}
}
I think my answer is O(N^2) which is not acceptable based on Question. Is there a solution based on O(N)?
You only need to loop once actually which is O(N).
Start adding from index 0 and once you exceed the sum start removing from the beginning of the array. if temp falls below sum continue looping.
public static boolean isValid(int[] array, int sum) {
int init = 0,temp = 0;
for (int i = 0; i < array.length; i++) {
temp += array[i];
while (temp > sum) {
temp -= array[init];
init++;
}
if (temp == sum)
return true;
}
return false;
}
What you should do is to have two indices (start and stop) then you increase stop until the sum is the required (and return true) or above. Then you increase start until the sum is the required (and return true or below. Then you repeat this until you reach the end of the array. You can update the sum incrementally (add the element when you increase stop and subtract when you increase start). This ought to be O(N).
Here's an example:
public class t {
public static void main(String[] args) {
int[] myArray = {23, 5, 4, 7, 2, 11};
System.out.println(isValid(myArray, 20));
}
public static boolean isValid(int[] array, int sum) {
int start = 0;
int stop = 0;
int tsum = 0;
while( true )
{
if( tsum < sum )
{
if( stop >= array.length )
break;
tsum += array[stop];
stop++;
}
else if( tsum > sum )
{
tsum -= array[start];
start++;
}
else if( tsum == sum )
return true;
// System.out.println(start + " -- " + stop + " => " + tsum);
}
return false;
}
}

Recursive function to promote binary ARRAY

How can I promote binary array using recursion func.
The function receives binary array V and increases the value of the number represented by V the following number with the same number of unity. Function returns true if the operation can be performed (java)
Example:
v = {0,0,0,1,1,0,0,1,1} => return true, v = {0,0,0,1,1,0,1,0,1}
i write this:
public static boolean incrementSameOnes(int[] vec) {
boolean succ=false;
int[] v=new int[vec.length-1];
if(vec.length==1){
return false;
}
if (vec[vec.length-1]==1 && vec[vec.length-2]==0)
{
vec[vec.length-2] = 1;
vec[vec.length-1] = 0;
System.out.print(Arrays.toString(vec));
return true;
}else {
for(int j=0;j<vec.length-1;j++)
v[j]=vec[j];
succ=incrementSameOnes(v);
}
return succ;
}
If I understand you correctly, you want to find the next higher integer with the same amount of set bits in the binary representation, correct? If so, I propose:
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] x = { 1, 1, 1, 0, 1, 1, 0 };
System.out.println("original: " + Arrays.toString(x));
if (promote(x)) System.out.println("promoted: " + Arrays.toString(x));
else System.out.println("not promotable");
}
private static boolean promote(int[] x) {
// convert to integer value
int value = 0;
for (int i = 0; i < x.length; i++) {
value += x[x.length - 1 - i] * (1 << i);
}
int newValue = value + 1, maxValue = 1 << x.length;
int nBits = getNumberOfSetBits(value);
// increase value until same amount of set bits found
while (newValue < maxValue && getNumberOfSetBits(newValue) != nBits)
newValue++;
// convert back to array
if (newValue < maxValue) {
for (int i = 0; i < x.length; i++) {
x[x.length - 1 - i] = (newValue & (1 << i)) >> i;
}
return true;
} else {
return false;
}
}
// kung fu magic to get number of set bits in an int
// see http://stackoverflow.com/a/109025/1137043
private static int getNumberOfSetBits(int i) {
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}
}
output:
original: [1, 1, 1, 0, 1, 1, 0]
promoted: [1, 1, 1, 1, 0, 0, 1]
EDIT: For a 2D array like in your example, the conversion to int and back to your array format would look a bit different but I would recommend the same approach.

Array even & odd sorting

I have an array where I have some numbers. Now I want to sort even numbers in a separate array and odd numbers in a separate. Is there any API to do that? I tried like this
int[] array_sort={5,12,3,21,8,7,19,102,201};
int [] even_sort;
int i;
for(i=0;i<8;i++)
{
if(array_sort[i]%2==0)
{
even_sort=Arrays.sort(array_sort[i]);//error in sort
System.out.println(even_sort);
}
}
Plain and simple.
int[] array_sort = {5, 12, 3, 21, 8, 7, 19, 102, 201 };
List<Integer> odd = new ArrayList<Integer>();
List<Integer> even = new ArrayList<Integer>();
for (int i : array_sort) {
if ((i & 1) == 1) {
odd.add(i);
} else {
even.add(i);
}
}
Collections.sort(odd);
Collections.sort(even);
System.out.println("Odd:" + odd);
System.out.println("Even:" + even);
Your question as stated doesn't make sense, and neither does the code. So I'm guessing that you want to separate the elements of an array into two arrays, one containing odds and the other evens. If so, do it like this:
int[] input = {5, 12, 3, 21, 8, 7, 19, 102, 201};
List<Integer> evens = new ArrayList<Integer>();
List<Integer> odds = new ArrayList<Integer>();
for (int i : input) {
if (i % 2 == 0) {
evens.add(i);
} else {
odds.add(i);
}
}
You can then convert a list of Integer to a sorted array if int as follows:
List<Integer> list ...
int[] array = new int[list.size()];
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}
Arrays.sort(array);
or if a sorted List<Integer> is what you need, just do this:
Collections.sort(list);
It's simple to do this using Guava.
Use Ints.asList to create a List<Integer> live view of an int[]
Define a Function<Integer,Boolean> isOdd
Use Ordering that compares onResultOf(isOdd), naturally (i.e. false first, then true)
If necessary, compound that with an Ordering.natural()
Here's the snippet:
int[] nums = {5,12,3,21,8,7,19,102,201};
Function<Integer,Boolean> isOdd = new Function<Integer,Boolean>() {
#Override
public Boolean apply(Integer i) {
return (i & 1) == 1;
}
};
Collections.sort(
Ints.asList(nums),
Ordering.natural().onResultOf(isOdd)
.compound(Ordering.natural())
);
System.out.println(Arrays.toString(nums));
// [8, 12, 102, 3, 5, 7, 19, 21, 201]
Note that all the even numbers show up first, then all the odd numbers. Within each group, the numbers are sorted naturally.
External links
polygenelubricants.com - Writing more elegant comparison logic with Guava's Ordering
There are some things to know first :
You must initialize an array before using it. For example int[] even_sort = new int[3];
In java arrays have a static size. That means that you won't be able to add as many elements as you want. You have to choose a size before. You should take a look at Java Collections, it's a good way to get rid of this "rule" the java way.
The Arrays.sort() method apply on arrays only. Here array_sort[i] is an int
Arrays.sort() sorts an array but doesn't return anything.
If you really want to use arrays (but you shouldn't) you can do something like this to resize one :
int[] even_sort = new int[3]{1, 2, 3};
int[] temp = new int[4];
System.arraycopy(even_sort, 0, temp, 0, even_sort.length);
even_sort = temp;
even_sort[3] = 4;
Another way would be creating an utility method which uses reflection to create the new array :
import java.lang.reflect.Array;
public Object resizeArray(Object originalArray, int newSize){
int originalSize = Array.getLength(originalArray);
Class arrayType = originalArray.getClass().getComponentType();
Object newArray = Array.newInstance(arrayType, newSize);
System.arraycopy(originalArray, 0, newArray, 0, Math.min(originalSize, newSize));
return newArray;
}
So if you still want to use array for some reasons (but you still shouldn't) here is a code to filter, resize and sort your array.
int[] arrayToFilterAndSort = {5, 12, 3, 21, 8, 7, 19, 102, 201};
int[] sortedEvens = new int[0];
for(int current : arrayToFilterAndSort){
if((current & 1) == 1){
sortedEvens = resizeArray(sortedEvens, sortedEvens.length + 1);
sortedEvens[sortedEvens.length - 1] = current;
}
}
Arrays.sort(sortedEvens);
Resources :
oracle.com - Arrays tutorial
oracle.com - Collections tutorial
javadoc - Arrays.sort()
package com.java.util.collection;
import java.util.Arrays;
/**
* Given n random numbers. Move all even numbers on left hand side and odd numbers on right hand side and
* then sort the even numbers in increasing order and odd numbers in decreasing order For example,
* i/p : 3 6 9 2 4 10 34 21 5
* o/p: 2 4 6 10 34 3 5 9 21
* #author vsinha
*
*/
public class EvenOddSorting {
public static void eventOddSort(int[] arr) {
int i =0;
int j =arr.length-1;
while(i<j) {
if(isEven(arr[i]) && isOdd(arr[j])) {
i++;
j--;
} else if(!isEven(arr[i]) && !isOdd(arr[j])) {
swap(i,j,arr);
} else if(isEven(arr[i])){
i++;
} else{
j--;
}
}
display(arr);
// even number sorting
Arrays.sort(arr,0,i);
Arrays.sort(arr,i,arr.length);
// odd number sorting
display(arr);
}
public static void display(int[] arr) {
System.out.println("\n");
for(int val:arr){
System.out.print(val +" ");
}
}
private static void swap(int pos1, int pos2, int[] arr) {
int temp = arr[pos1];
arr[pos1]= arr[pos2];
arr[pos2]= temp;
}
public static boolean isOdd(int i) {
return (i & 1) != 0;
}
public static boolean isEven(int i) {
return (i & 1) == 0;
}
public static void main(String[] args) {
int arr[]={3, 6, 9 ,2, 4, 10, 34, 21, 5};
eventOddSort(arr);
}
}
int arr[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
cout << "The Even no are : \n";
for (int i = 1; i <= 10; i++) // for start for only i....(even nos)
{
if (i % 2 == 0)
{
cout << i;
cout << " ";
}
}
cout << "\nThe Odd no are : \n";
for (int j = 1; j <= 10; j++) // for start for only j....(odd nos)
{
if (j % 2 != 0)
{
cout << j;
cout << " ";
}`enter code here`
}
package srikanth dukuntla;
public class ArrangingArray {
public static void main(String[] args) {
int j=0;
int []array={1,2,3,5,4,55,32,0};
System.out.println(array.length);
int n=array.length/2;
for (int i=0; i<array.length; i++){
if(array[i]%2!=0){
j=1;
int temp=array[array.length-j];
if(temp % 2!=0){
while((array[array.length-(j+1)]%2!=0) && (array.length-(j+1)>n)){
j++;
}
int temp2=array[array.length-(j+1)];
array[array.length-(j+1)] =array[i];
array[i]=temp2;
}else // inner if
{
array[array.length-j] =array[i];
array[i]=temp;
}
}else //main if
{
//nothing needed
}
}
for(int k=0;k<array.length;k++) {
System.out.print(" "+ array[k]);
}
}
}
List < Integer > odd = new ArrayList < Integer > ();
List < Integer > even = new ArrayList < Integer > ();
int a [] = {0,2,3,98,1,6546,45323,1134564};
int i;
for (i = 0; i < a.length; i++) {
if (a[i] % 2 == 0) {
even.add(a[i]);
} else {
odd.add(a[i]);
}
}
System.out.print("Even: " + even + "\n");
System.out.print("Uneven: " + odd + "\n");
}
}

Categories

Resources