Max Heap MaxHeapify Java Not finishing - java

Having trouble with the constructor for MaxHeapify when there are more than 2 numbers that need to be ordered. stepping thru the code, it works for the first few and then continues without properly ordering the numbers.
i am not sure why this isn't working, any assistance on which variables or comparisons I seem to be mixing up here would be much appreciated.
public class MaxHeap
{
public int[] heap;
public int index_to_last_element;
protected void maxHeapify(int index)
{
int left = leftchild(index);
int right = rightchild(index);
int largest = index;
if (left < index_to_last_element && left != -1 && heap[left] > heap[index])
largest = left;
if (right < index_to_last_element && right != -1 && heap[right] > heap[largest])
largest = right;
if (largest != index)
{
int temp = heap[index];
heap[index] = heap[largest];
heap[largest] = temp;
maxHeapify(largest);
}
}
public int parent(int pos)
{
return (pos - 1) / 2;
}
public int leftchild(int pos)
{
return 2 * pos + 1;
}
public int rightchild(int pos)
{
return 2 * pos + 2;
}

Related

How can I show the value of array with the Binary Search Tree of Comparison?

I going to do searching the value in the array, did I need to create a method to handle it? For example, the array logged 32,21,13,44,22, and I going to find 22 of the comparison. How can I implement this?
public class binarySearch {
public static void main(String [] args) {
int i = binarySearch(0, new int[]{32,21,13,44,22});
System.out.println("Iterations: " + i);
}
public static int binarySearch(int key, int[] array) {
int left = 0;
int mid;
int right = array.length - 1;
int i = 0;
while (left <= right) {
mid = (left + right) / 2;
int comp = Integer.compare(key, array[mid]);
i++;
if (comp < 0) {
right = mid - 1;
} else if (comp > 0) {
left = mid + 1;
} else {
break; // success
}
}
return i;
}
}
My final answer is here. May help you all in the future.
public static int binarySearch(int key, int[] array) {
int left = 0;
int mid;
int right = array.length - 1;
int i = 0;
while (left <= right) {
mid = (left + right) / 2;
int comp = Integer.compare(key, array[mid]);
i++;
if (comp < 0) {
right = mid - 1;
} else if (comp > 0) {
left = mid + 1;
} else {
break; // success
}
}
return i;
}
If you have shuffled array, all you can do is go through an array and find your number.
BinarySearch works only with sorted array. I think your solution could look like this:
public static int binarySearch(int[] arr, int key) {
Arrays.sort(arr);
return Arrays.binarySearch(arr, key);
}

Efficiently, get the count of numbers in a sorted array that is less than a given number using binary search

My problem statement is this -
Find the count of numbers in a sorted array that are less than a given number, and this should be done efficiently with respect to time. I wrote a program using binary search that gets the count but time complexity wise it's failing. Need help in achieving this.
import java.util.Arrays;
public class SortedSearch {
public static int countNumbers(int[] sortedArray, int lessThan) {
if(sortedArray.length ==1 || sortedArray.length == 0) {
return singleElement(sortedArray, lessThan);
}
else {
return binarySearch(sortedArray, lessThan);
}
}
public static int singleElement(int[] sortedArray, int searchVal) {
if(sortedArray.length == 0) {
return 0;
}
if(sortedArray[0] < searchVal) {
return 1;
}
return 0;
}
private static int binarySearch(int[] sortedArray, int searchVal) {
int low = 0;
int high = (sortedArray.length)-1;
int mid = (low + high)/2;
if((sortedArray.length == 0) || (sortedArray[0] > searchVal)) {
return 0;
}
if(sortedArray[high] < searchVal) {
return sortedArray.length;
}
if(sortedArray[high] == searchVal) {
return sortedArray.length-1;
}
if(sortedArray[mid] < searchVal) {
int newLow = low;
int newHigh = calculateNewHigh(sortedArray, newLow, 0, searchVal);
int[] newArray = Arrays.copyOfRange(sortedArray, newLow, newHigh+1);
return newArray.length;
}
else {
int newLow = low;
int newHigh = mid;
int[] newArray = Arrays.copyOfRange(sortedArray, newLow, newHigh+1);
return binarySearch(newArray, searchVal);
}
}
private static int calculateNewHigh(int[] sortedArray, int low, int previousHigh, int searchVal) {
int newHigh = previousHigh + (sortedArray.length-low)/2;
if(sortedArray[newHigh] < searchVal) {
newHigh = calculateNewHigh(sortedArray, newHigh, newHigh, searchVal);
}
if(sortedArray[newHigh] == searchVal) {
newHigh--;
}
if(sortedArray[newHigh] > searchVal) {
newHigh--;
}
return newHigh;
}
public static void main(String[] args) {
System.out.println(SortedSearch.countNumbers(new int[] { 1, 3, 5, 7 }, 4));
}
}
Since you're using Arrays anyway, way not use the Arrays.binarySearch(int[] a, int key) method, instead of attempting to write your own?
public static int countNumbers(int[] sortedArray, int lessThan) {
int idx = Arrays.binarySearch(sortedArray, lessThan);
if (idx < 0)
return -idx - 1; // insertion point
while (idx > 0 && sortedArray[idx - 1] == lessThan)
idx--;
return idx; // index of first element with given value
}
The while loop1 is necessary because the javadoc says:
If the array contains multiple elements with the specified value, there is no guarantee which one will be found.
1) This loop is not optimal if e.g. all values are the same, see e.g. Finding multiple entries with binary search

Is there a way to fix my Max heapify within my code

The issue is that I am trying to fix the max heapify, it is not working as the error keeps occurring. I have been following the pseudocode from several books, yet errors are still shown. I am trying to exchange the A[i] to A[largest] by using = to exchange but it is giving an error instead
class Heap {
// public for JUnit testing purposes
public ArrayList<Integer> array;
public int heap_size;
public Heap(int size) {
}
public Heap(List<Integer> source) {
this(source, false);
}
public Heap(List<Integer> source, boolean incremental) {
}
public static int parent(int index) {
return index/2;
}
public static int left(int index) {
return 2 * index;
}
public static int right(int index) {
return (2 * index) + 1;
}
public void maxHeapify(int i, int A)
{
int l = left(i);
int r = right(i);
if(l <= A.heap_size && A[l] > A[i])
largest = l;
else
largest = i;
if(r <= A.heap_size && A[r] > A[largest])
largest = r;
if(largest != i)
{
A[i] = A[largest];
maxHeapify(A,largest);
}
}
public void buildMaxHeap() {
}
public void insert(Integer k) {
}
public Integer maximum() {
return 0;
}
public Integer extractMax() {
return 0;
}
}
I am expecting it to run but i get an error
Heap.java:31: error: int cannot be dereferenced
if(l <= A.heap_size && A[l] > A[i])
^
Heap.java:31: error: array required, but int found
if(l <= A.heap_size && A[l] > A[i])
^
Heap.java:31: error: array required, but int found
if(l <= A.heap_size && A[l] > A[i])
^
Heap.java:32: error: cannot find symbol
largest = l;
^
symbol: variable largest
location: class Heap
If you can, please help.
== is a comparison operator. If you want to assign a value you should use the = operator:
A[i] = A[largest];
According to the error messages, the problem is that the argument A of maxHeapify is an integer value. You need to pass the argument A as an array.
public void maxHeapify(int i, int[] A) {
int largest = i;
int l = left(i);
int r = right(i);
if(l < A.length && A[l] > A[largest])
largest = l;
if(r < A.length && A[r] > A[largest])
largest = r;
if(largest != i)
{
int tmp = A[i];
A[i] = A[largest];
A[largest] = tmp;
maxHeapify(largest, A);
}
}
I have tested the above maxHeapify in the following code.
public class HeapMain {
public static void main(String[] args) {
// Note: ignore the value at index 0
int[] A = new int[]{-1, 3, 9, 10, 4, 2, 33, 5};
Heap heap = new Heap(A.length);
for (int i = heap.parent(A.length - 1); i > 0; i--) {
heap.maxHeapify(i, A);
}
// You will get => 33 9 10 4 2 3 5
for (int i = 1; i < A.length; i++) {
System.out.print(A[i]);
System.out.print(" ");
}
System.out.println();
}
}
Note: parent, left and right method assume that the nodes of the heap in an array are saved from index 1.
The following URL might be helpful.
https://www.youtube.com/watch?v=ixdWTKWSz7s

What is the size above depth of BST

This is what I have so far. I need to computes the size of the tree above at depth k.
public static int above(Node t, int k) {
if (t == null) { return 0; }
if (t.key > k)
return (above(t.left, k - 1) + above(t.right, k - 1) + 1);
else {
return above(t.left, k - 1) + above(t.right, k - 1);
}
}
EDIT: This code works and computes the size of the tree at depth k.
public static int at(Node t, int k) {
if(t == null) return 0;
if(k == 0) return 1;
return at(t.left, k - 1) + at(t.right, k - 1);
}
I would of thought something more like this would do it... but maybe I don't understand the problem correctly.
public static int above(Node t, int k) {
if (t == null) { return 0; }
if (k > 0) {
return (above(t.left, k - 1) + above(t.right, k - 1) + 1);
} else {
return 1;
}
}
This code computes the tree size till depth k where root is at depth 1.
static int depth=0;
static int tree_size=0,k=3;
private static void inorder(Node head) {
if(head!=null){
depth++;
inorder(head.left);
if(depth<=k)
tree_size++;
inorder(head.right);
depth--;
}
}

Segment Tree Codechef TLE

I am trying to solve this CodeChef problem:
There are N coins kept on the table, numbered from 0 to N - 1. Initially, each coin is kept tails up.
You have to perform two types of operations:
Flip all coins numbered between A and B inclusive. This is represented by the command "0 A B"
Answer how many coins numbered between A and B inclusive are heads up. This is represented by the command "1 A B".
Input: The first line contains two integers, N and Q. Each of the next Q lines are either of the form "0 A B" or "1 A B" as mentioned above.
Output: Output 1 line for each of the queries of the form "1 A B" containing the required answer for the corresponding query.
What I have used is a segment tree. So that every time user enter a query of type 1 A B the output is the sum at that interval [A,B]. However I am getting a Time Limit Exceeded error. I believe the error is due to the update step 0 A B. After updating the elements in the array I reconstruct the tree. The code is given below. Can someone help me with a faster way to update?
BTW - I am getting the desired output for the sample input.
public class SegmentTree
{
private int[] tree;
private int maxsize;
private int height;
private static int elems[];
private final int STARTINDEX = 0;
private final int ENDINDEX;
private final int ROOT = 0;
public SegmentTree(int size)
{
height = (int)(Math.ceil(Math.log(size) / Math.log(2)));
maxsize = 2 * (int) Math.pow(2, height) - 1;
tree = new int[maxsize];
ENDINDEX = size - 1;
}
private int leftchild(int pos)
{
return 2 * pos + 1;
}
private int rightchild(int pos)
{
return 2 * pos + 2;
}
private int mid(int start, int end)
{
return (start + (end - start) / 2);
}
private int getSumUtil(int startIndex, int endIndex, int queryStart, int queryEnd, int current)
{
if (queryStart <= startIndex && queryEnd >= endIndex)
{
return tree[current];
}
if (endIndex < queryStart || startIndex > queryEnd)
{
return 0;
}
int mid = mid(startIndex, endIndex);
return getSumUtil(startIndex, mid, queryStart, queryEnd, leftchild(current))
+ getSumUtil( mid + 1, endIndex, queryStart, queryEnd, rightchild(current));
}
public int getSum(int queryStart, int queryEnd)
{
if(queryStart < 0 || queryEnd > tree.length)
{
return -1;
}
return getSumUtil(STARTINDEX, ENDINDEX, queryStart, queryEnd, ROOT);
}
private int constructSegmentTreeUtil(int startIndex, int endIndex, int current)
{
if (startIndex == endIndex)
{
tree[current] = elems[startIndex];
return tree[current];
}
int mid = mid(startIndex, endIndex);
tree[current] = constructSegmentTreeUtil(startIndex, mid, leftchild(current))
+ constructSegmentTreeUtil(mid + 1, endIndex, rightchild(current));
return tree[current];
}
public void constructSegmentTree()
{
constructSegmentTreeUtil(STARTINDEX, ENDINDEX, ROOT);
}
public static void main(String[]args) throws IOException
{
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer str = new StringTokenizer(buf.readLine());
int n = Integer.parseInt(str.nextToken());
int q = Integer.parseInt(str.nextToken());
SegmentTree segmentTree = new SegmentTree(n);
int elements[] = new int[n];
for(int i = 0; i < n; i++) {
elements[i] = 0;
}
elems = elements;
segmentTree.constructSegmentTree();
while (q-- > 0) {
str = new StringTokenizer(buf.readLine());
int x = Integer.parseInt(str.nextToken());
int a = Integer.parseInt(str.nextToken());
int b = Integer.parseInt(str.nextToken());
if(x == 0) {
for(int j = a; j <= b; j++)
{
elems[j] = elems[j]^1;
}
segmentTree.constructSegmentTree();
}
else {
int num = segmentTree.getSum(a, b);
System.out.println(num);
}
}
}
}
EDIT:
According to GeeksForGeeks, tree construction costs O(n) and the update method is O(log n). So here are the new methods for update:
private void updateTreeUtil(int startIndex, int endIndex, int updatePos, int update, int current)
{
if ( updatePos < startIndex || updatePos > endIndex)
{
return;
}
tree[current] = tree[current] + update;
if (startIndex != endIndex)
{
int mid = mid(startIndex, endIndex);
updateTreeUtil(startIndex, mid, updatePos, update, leftchild(current));
updateTreeUtil(mid+1, endIndex, updatePos, update, rightchild(current));
}
}
public void update(int update, int updatePos)
{
int updatediff = update - elems[updatePos];
elems[updatePos] = update;
updateTreeUtil(STARTINDEX, ENDINDEX, updatePos, updatediff, ROOT);
}
And now the if loop in main method modified to this:
if(x == 0) {
for(int j = a; j <= b; j++)
{
segmentTree.update(elems[j]^1, j);
}
}
But still getting TLE error.
In the tutorial of GeeksForGeeks, their running time of update is O(log n), in case of updating a single element. However, when doing update for an interval, you have to use Lazy Propagation to ensure O(log n) update time, which is basically only update nodes which are visited, and hence ensure the sum of visited nodes are correct. You may search for many good tutorial on Lazy Propagation, for example:
http://se7so.blogspot.hk/2012/12/segment-trees-and-lazy-propagation.html
Wish that helps.

Categories