QuickSort for big cases leads to stackoverflow - java

I am working on a school project that has to have 3 quicksorts with 1 pointer, 3 quicksorts with 2 pointers and 2 heaps.
I wrote the Quicksorts and one of the heaps so far.
The problem I have is quicksort works fine in small cases however in larger cases I get a stackoverflow.
Nore: each quicksort has an easy case in which it should run insertion sort.
Why do i get stack a overflow?
package prog3;
import java.util.Random;
public class ArraySorts {
public static void QuickSort1(int[] a, int n) {
QuickSort1(a, 0, n - 1);
}
private static void QuickSort1(int[] a, int start, int end) {
if ((end - start+1) <= 20) {
int num = (end + 1) - start;
insertion(a, num);
}
else {
// use first element as division between small and big
Random rand = new Random();
int pivotIndex = start + rand.nextInt(end - start);
swap(a, pivotIndex, start);
int pivot = a[start];
int partitionBook = partitionBook(a, start, end, pivot);
// recursively sort the smalls and then the bigs
QuickSort1(a, start, partitionBook - 1);
QuickSort1(a, partitionBook + 1, end);
}
}
public static void QuickSort2(int[] a, int n) {
// 2 ptr partition, random pivot, easiest case = 20
int left = 0;
int right = n - 1;
QuickSort2(a, left, right);
}
public static void QuickSort2(int[] a, int left, int right) {
if ((right - left + 1) <= 20) {
int num = right - left + 1;
insertion(a, num);
} else {
// int pivot = a[right];
Random rand = new Random();
int pivotIndex = left + rand.nextInt(right - left + 1);
swap(a, pivotIndex, right);
int pivot = a[right];
int partition = partition(a, left, right, pivot);
QuickSort2(a, 0, partition - 1);
QuickSort2(a, partition + 1, right);
}
}
public static void QuickSort3(int[] a, int n) {
QuickSort3(a, 0, n - 1);
}
private static void QuickSort3(int[] a, int start, int end) {
if ((end - start) <= 20) {
int num = (end + 1) - start;
insertion(a, num);
}
else {
// use first element as division between small and big
int pivot = a[start];
int partitionBook = partitionBook(a, start, end, pivot);
// recursively sort the smalls and then the bigs
QuickSort3(a, start, partitionBook - 1);
QuickSort3(a, partitionBook + 1, end);
}
}
public static void QuickSort4(int[] a, int n) {
// 2 ptr partition, random pivot, easiest case = 1
int left = 0;
int right = n - 1;
QuickSort4(a, left, right);
}
public static void QuickSort4(int[] a, int left, int right) {
if ((right - left + 1) <= 1) {
return;
}
// int pivot = a[right];
Random rand = new Random();
int pivotIndex = left + rand.nextInt(right - left + 1);
swap(a, pivotIndex, right);
int pivot = a[right];
// System.out.println("Pivot: " + pivot);
int partition = partition(a, left, right, pivot);
QuickSort4(a, 0, partition - 1);
QuickSort4(a, partition + 1, right);
}
public static void QuickSort5(int[] a, int n) {
// 2 ptr partition, random pivot, easiest case = 500
int left = 0;
int right = n - 1;
QuickSort5(a, left, right);
}
public static void QuickSort5(int[] a, int left, int right) {
if ((right - left + 1) <= 500) {
int num = right - left + 1;
insertion(a, num);
} else {
// int pivot = a[right];
Random rand = new Random();
int pivotIndex = left + rand.nextInt(right - left + 1);
swap(a, pivotIndex, right);
int pivot = a[right];
int partition = partition(a, left, right, pivot);
QuickSort5(a, 0, partition - 1);
QuickSort5(a, partition + 1, right);
}
}
public static void QuickSort6(int[] a, int n) {
QuickSort6(a, 0, n - 1);
}
private static void QuickSort6(int[] a, int start, int end) {
if ((end - start+1) <= 1) {
return;
}
else {
// use first element as division between small and big
Random rand = new Random();
int pivotIndex = start + rand.nextInt(end - start);
swap(a, pivotIndex, start);
int pivot = a[start];
int partitionBook = partitionBook(a, start, end, pivot);
// recursively sort the smalls and then the bigs
QuickSort1(a, start, partitionBook - 1);
QuickSort1(a, partitionBook + 1, end);
}
}
private static int partition(int[] a, int left, int right, int pivot) {
int leftCursor = left - 1;
int rightCursor = right;
while (leftCursor < rightCursor) {
while (a[++leftCursor] < pivot)
;
while (rightCursor > 0 && a[--rightCursor] > pivot)
;
if (leftCursor > rightCursor) {
break;
} else {
swap(a, leftCursor, rightCursor);
}
}
swap(a, leftCursor, right);
return leftCursor;
}
private static int partitionBook(int[] a, int start, int end, int pivot) {
// the index of the last small element
int lastSmall = start;
for (int unknown = start + 1; unknown <= end; unknown++) {
// see if the current element is small
if (a[unknown] < pivot) {
// and if so, put it with the other smalls
lastSmall++;
int temp = a[lastSmall];
a[lastSmall] = a[unknown];
a[unknown] = temp;
}
}
// put the pivot between the smalls and the bigs
int temp = a[start];
a[start] = a[lastSmall];
a[lastSmall] = temp;
return lastSmall;
}
public static void swap(int[] a, int left, int right) {
int temp = a[left];
a[left] = a[right];
a[right] = temp;
}
public static void printArray(int[] a) {
for (int i : a) {
System.out.print(i + " ");
}
}
public static int[] getArray() {
int size = 10;
int[] array = new int[size];
int item = 0;
for (int i = 0; i < size; i++) {
item = (int) (Math.random() * 100);
array[i] = item;
}
return array;
}
/**
* Will return the left child's index
*
* #param iIndex
* The index of the current position (Parent)
* #return The index of the left child
*/
static int Left(int iIndex) {
return ((iIndex << 1) + 1);
}
/**
* Will return the right child's index
*
* #param iIndex
* The index of the current position (Parent)
* #return The index of the right child
*/
static int Right(int iIndex) {
return ((iIndex << 1) + 2);
}
/**
* Will return the parent of the current index
*
* #param iIndex
* The index of the current position (Child)
* #return The index of the parent
*/
int Parent(int iIndex) {
return ((iIndex - 1) >> 1);
}
/**
* Swaps the values of the two index locations
*
* #param firstIndex
* the index of the first number to exchange.
* #param secondIndex
* The index of the second number to exchange.
* #param ipHeap
*/
static void Swap(int firstIndex, int secondIndex, int[] ipHeap) {
int iTemp = ipHeap[firstIndex];
ipHeap[firstIndex] = ipHeap[secondIndex];
ipHeap[secondIndex] = iTemp;
}
/**
* Determines if there needs to have a swap of a child and parent. It will
* determine which child needs to be swapped.
*
* #param parent
* index of the parent (current index)
* #param ipHeap
* The array that needs the operations performed.
* #param iSize
* The adjusted size of the array
* #return The index of the largest value.
*/
static int SwapWithChild(int parent, int[] ipHeap, int iSize) {
int leftChild = Left(parent);
int rightChild = Right(parent);
int iLargest = parent;
if (rightChild < iSize) {
if (ipHeap[leftChild] < ipHeap[rightChild]) {
iLargest = rightChild;
} else {
iLargest = leftChild;
}
if (ipHeap[parent] > ipHeap[iLargest]) {
iLargest = parent;
}
} else if (leftChild < iSize) {
if (ipHeap[parent] < ipHeap[leftChild]) {
iLargest = leftChild;
}
}
if (ipHeap[parent] < ipHeap[iLargest]) {
Swap(parent, iLargest, ipHeap);
}
return iLargest;
}
/**
* Replaces the value of the root with the value of the last element of the
* heap.
*
* #param ipHeap
* The heap to have the root replaced.
* #param iSize
* The size of the heap.
*/
void RemoveRoot(int[] ipHeap, int iSize) {
// Put the last element at the root
ipHeap[0] = ipHeap[iSize - 1];
--iSize;
int iLasti = 0;
int i = SwapWithChild(0, ipHeap, iSize);
while (i != iLasti) {
iLasti = i;
i = SwapWithChild(i, ipHeap, iSize);
}
}
/**
* Exchanges the current index value with that of the parent
*
* #param i
* The index of the current value (Child).
* #param ipHeap
* The heap being working with.
* #return
*/
int SwapWithParent(int i, int[] ipHeap) {
if (i < 1) {
return i;
}
int iParent = Parent(i);
if (ipHeap[i] > ipHeap[iParent]) {
Swap(i, iParent, ipHeap);
return iParent;
} else {
return i;
}
}
/**
* Adds an element to the provided heap
*
* #param iNewEntry
* The value being added to the heap.
* #param ipHeap
* The heap to add the new value.
* #param iSize
* The current size of the heap.
*/
void AddElement(int iNewEntry, int[] ipHeap, int iSize) {
ipHeap[iSize] = iNewEntry;
int iLasti = iSize;
int i = SwapWithParent(iLasti, ipHeap);
while (iLasti != i) {
iLasti = i;
i = SwapWithParent(i, ipHeap);
}
}
/**
* Displays the heap to the console in a linear fashion.
*
* #param ipArray
* The heap to be displayed.
* #param iSize
* The current size of the heap.
*/
static void OutputArray(int[] ipArray, int iSize, int verticalBar) {
for (int i = 0; i < iSize; ++i) {
if (i == verticalBar) {
System.out.print("| ");
}
System.out.print(ipArray[i] + " ");
}
System.out.println();
}
/**
* Sorts the heap
*
* #param ipHeap
* The heap that needs to be sorted.
* #param iSize
* The current size of the heap.
*/
static void sortRoot(int[] ipHeap, int iSize) {
// Swap the last element with the root
Swap(0, iSize - 1, ipHeap);
iSize--;
int iLasti = 0;
int i = SwapWithChild(0, ipHeap, iSize);
while (i != iLasti) {
iLasti = i;
i = SwapWithChild(i, ipHeap, iSize);
}
}
static void heapify(int[] a) {
for (int iLast = a.length >> 1; iLast >= 0; iLast--) {
int i = SwapWithChild(iLast, a, a.length);
while (iLast != i) {
iLast = i;
i = SwapWithChild(i, a, a.length);
}
}
}
static void HeapSort2(int[] a, int n) {
heapify(a);
for (int i = 0; i < n; ++i) {
sortRoot(a, n - i);
OutputArray(a, n, n - 1 - i);
System.out.println();
}
}
public static void HeapSort1(int[] a, int n){
int count =n;
//first place a in max-heap order
heapify(a, count);
int end = count - 1;
while(end > 0){
//swap the root(maximum value) of the heap with the
//last element of the heap
int tmp = a[end];
a[end] = a[0];
a[0] = tmp;
//put the heap back in max-heap order
siftDown(a, 0, end - 1);
//decrement the size of the heap so that the previous
//max value will stay in its proper place
end--;
}
}
public static void heapify(int[] a, int count){
//start is assigned the index in a of the last parent node
int start = (count - 2) / 2; //binary heap
while(start >= 0){
//sift down the node at index start to the proper place
//such that all nodes below the start index are in heap
//order
siftDown(a, start, count - 1);
start--;
}
//after sifting down the root all nodes/elements are in heap order
}
public static void siftDown(int[] a, int start, int end){
//end represents the limit of how far down the heap to sift
int root = start;
while((root * 2 + 1) <= end){ //While the root has at least one child
int child = root * 2 + 1; //root*2+1 points to the left child
//if the child has a sibling and the child's value is less than its sibling's...
if(child + 1 <= end && a[child] < a[child + 1])
child = child + 1; //... then point to the right child instead
if(a[root] < a[child]){ //out of max-heap order
int tmp = a[root];
a[root] = a[child];
a[child] = tmp;
root = child; //repeat to continue sifting down the child now
}else
return;
}
}
static void insertion(int[] a, int n) {
//System.out.println("********** INSERTION************");
if (a.length == 0)
return;
for (int i = 0; i < a.length; i++) {
insertionHelper(a, i);
//OutputArray(a, a.length, i);
}
}
/**
* A private helper method for the insertion sorting.
*
* #param iaArray
* Array to be sorted
* #param pointer
* the current element that needs to be inserted in the proper
* order.
*/
private static void insertionHelper(int[] a, int pointer) {
// verify pointer is not at the begining of the array
if (pointer <= 0)
return;
// if pointer' value is smaller than the previous element, we need to
// swap.
while (pointer > 0 && a[pointer] < a[pointer - 1]) {
Swap(pointer, pointer - 1, a);
pointer--;
}
}
public static String myName() {
return "some name";
}
}

The reason that you get stack overflow exception is because you call method QuickSort1 in QuickSort1 and there is a limit when you implement recursive function like that. You can increase your call stack size using -Xss command line arg like:
java -Xss4m

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);
}

Implementing a heap

I am trying to implement a heap data structure, i wrote the maxHeapify method which builda maximum heap, and used it in my insert method in which i insert at the end then rearrange the heap to remain a max heap.
but it doesn't appear to work, any help would be appreciated.
public class Heap { // a class to implement a heap
private int[] data; // the heap array
private static final int FRONT = 1;
private int maxSize = 0;
private int currentSize; // the current size of the data in the array
public Heap(int maxSize) {
this.currentSize = 1;
this.maxSize = maxSize;
data = new int[maxSize + 1];
}
public int[] getData() {
return data;
}
public void setData(int[] data) {
this.data = data;
}
public int getMaxSize() {
return maxSize;
}
public void setMaxSize(int maxSize) {
this.maxSize = maxSize;
}
public int getCurrentSize() {
return currentSize;
}
public void setCurrentSize(int currentSize) {
this.currentSize = currentSize;
}
#SuppressWarnings("unused")
private int parent(int index) {// the index of the parent
return index / 2;
}
private int left(int index) { // the index of the left child
return (2 * index);
}
private int right(int index) { // the index of the right child
return (2 * index) + 1;
}
private void swap(int i, int j) { // to swap two elements
int temp = data[i];
data[i] = data[j];
data[j] = temp;
}
private void maxHeapify(int i) { // to build a max heap
int left = left(i); // a method to return the index of the left child
int right = right(i);// a method to return the index of the right child
int largest = i;
int x = currentSize;
if (left <= currentSize && data[left] > data[i]) {
largest = left;
}
if (right <= currentSize && data[right] > data[largest]) {
largest = right;
}
if (largest != i) {
int temp = data[i];
data[i] = data[largest];
data[largest] = temp;
maxHeapify(largest);
}
}
public void maxHeap() {
for (int i = currentSize / 2; i >= 1; i--) {
maxHeapify(i);
}
}
public void insert(int newData) { // insert to the heap
data[currentSize] = newData;
currentSize++;
maxHeapify(FRONT);
}
public int deleteMax() { // delete max from the heap
int maxValue = data[FRONT];
data[FRONT] = data[data.length - 1];
maxHeapify(FRONT);
currentSize--;
return maxValue;
}
public void sort() {// heap sort
maxHeap();
for (int i = maxSize; i > 1; i--) {
swap(FRONT, maxSize);
maxSize--;
maxHeapify(FRONT);
}
}
public void clear() {
maxSize = 0;
}
public boolean isEmpty() {
return maxSize == 0;
}
public boolean isFull() {
return currentSize == data.length;
}
public void printHeap() {// prints the heap
for (int i = 1; i <= maxSize / 2; i++) {
System.out.print(
" PARENT : " + data[i] + " LEFT CHILD : " + data[2 * i] + " RIGHT CHILD :" + data[2 * i + 1]);
System.out.println();
}
}
}
Your function maxHeapify works when you add new number on root of your heap. I mean to say in maxHeapify, you are moving from root to child. But during insertion you are inserting element to the last. You have to move from down to up.
maxHeapify : going root to down.
After inserting element to data array, you have to check upward from child to parent exact opposite of maxHeapify.
This should work:
/**
* Parent.
*
* #param pos the pos
* #return the int
*/
private int parent(int pos)
{
return pos / 2;
}
/**
* Left.
*
* #param pos the pos
* #return the int
*/
private int left(int pos)
{
return (2 * pos);
}
/**
* Right.
*
* #param pos the pos
* #return the int
*/
private int right(int pos)
{
return (2 * pos) + 1;
}
/**
* Checks if is leaf.
*
* #param pos the pos
* #return true, if is leaf
*/
private boolean isLeaf(int pos)
{
if (pos >= (size / 2) && pos <= size)
{
return true;
}
return false;
}
/**
* Swap.
*
* #param fpos the fpos
* #param spos the spos
*/
private void swap(int fpos,int spos)
{
int tmp;
tmp = data[fpos];
data[fpos] = data[spos];
data[spos] = tmp;
}
/**
* Max heapify.
*
* #param pos the pos
*/
private void maxHeapify(int pos)
{
if (!isLeaf(pos))
{
if ( data[pos] < data[left(pos)] || data[pos] < data[right(pos)])
{
if (data[left(pos)] > data[right(pos)])
{
swap(pos, left(pos));
maxHeapify(left(pos));
}else
{
swap(pos, right(pos));
maxHeapify(right(pos));
}
}
}
}
/**
* Insert.
*
* #param newElement the element
*/
public void insert(int newElement)
{
data[++size] = newElement;
int current = size;
while(data[current] > data[parent(current)])
{
swap(current,parent(current));
current = parent(current);
}
}
You required to shift up after adding the new element at last position.
For an example.
public void insert(int value) {
if (heapSize == data.length)
throw new HeapException( storage is overflow");
else {
heapSize++;
data[heapSize - 1] = value;
siftUp(heapSize - 1);
}
}
private void siftUp(int nodeIndex) {
//code to hepify.
}

Adding extra sort criteria in quick sort in java

So i have this code to quick sort a list of students by grade.
public static void quickSort(Student[] school){
quickSort(school, 0, school.length - 1); // quicksort all the elements in the array
}
private static void quickSort(Student[] school, int start, int end) {
int i = start; // index of left-to-right scan
int k = end; // index of right-to-left scan
if (end - start >= 1) // check that there are at least two elements to sort
{
Student pivot = school[start]; // set the pivot as the first element in the partition
while (k > i) // while the scan indices from left and right have not met,
{
while (school[i].getStudentGrade() <= pivot.getStudentGrade() && i <= end && k > i) // from the left, look for the first
{
i++;
// element greater than the pivot
}
while (school[k].getStudentGrade() > pivot.getStudentGrade() && k >= start && k >= i) // from the right, look for the first
{
k--; // element not greater than the pivot
}
if (k > i) // if the left seekindex is still smaller than
{
swap(school, i, k); // the right index, swap the corresponding elements
}
}
swap(school, start, k); // after the indices have crossed, swap the last element in
// the left partition with the pivot
quickSort(school, start, k - 1); // quicksort the left partition
quickSort(school, k + 1, end); // quicksort the right partition
} else // if there is only one element in the partition, do not do any sorting
{
return; // the array is sorted, so exit
}
}
//Swap 2 index values in array
private static void swap(Student[] school, int index1, int index2)
{
Student temp = school[index1];
school[index1] = school[index2];
school[index2] = temp;
}
I only can't figure out how to add an extra sort criteria so students with the same grade are sorted based on there student number which i get by using student.getStudentNumber.
Instead of directly using a compare function, pass a java.util.Comparator<T>.
This way you can implement different Comparators for different sort criteria.
The comparator would look like this:
import java.util.Comparator;
public class StudentComparator implements Comparator<Student> {
#Override
public int compare(final Student s1, final Student s2) {
final int gradeDiff = s1.getStudentGrade() - s2.getStudentGrade();
if (0 != gradeDiff) {
return gradeDiff;
}
final int numberDiff = s1.getStudentNumber() - s2.getStudentNumber();
if (0 != numberDiff) {
return numberDiff;
}
// addd mor criteria here if wanted
return 0;
}
}
Used this now
public class QuickSort {
public static void quickSort(Student[] school) {
quickSort(school, 0, school.length - 1);
}
private static void quickSort(Student[] school, int start, int end) {
int pivotIndex = start;
int storeIndex = pivotIndex + 1;
if (end - start >= 1) {
for (int i = pivotIndex + 1; i <= end; i++) {
if (school[i].getStudentGrade() > school[pivotIndex].getStudentGrade()) {
swap(school, storeIndex, i);
storeIndex++;
} else if(school[i].getStudentGrade() == school[pivotIndex].getStudentGrade()){
if(school[i].getStudentNumber() > school[pivotIndex].getStudentNumber()){
swap(school, storeIndex, i);
storeIndex ++;
}
}
}
swap(school, pivotIndex, storeIndex - 1);
pivotIndex = storeIndex - 1;
quickSort(school, start, pivotIndex - 1);
quickSort(school, pivotIndex + 1, end);
} else {
return;
}
}
//Swap 2 index values in array
private static void swap(Student[] school, int index1, int index2) {
Student temp = school[index1];
school[index1] = school[index2];
school[index2] = temp;
}
}

Binomical coefficient using the memoizazion methood

I wrote a function that recursively calculates the binomical coefficient term of n and k using the memoizazion methood, I get an OutOfBoundException when i execute, I'll be happy to hear some directions about the mistake I've done.
Thank you all.
public class Binomial {
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
int k = Integer.parseInt(args[1]);
StdOut.print(binomial(n, k));
}
/**
* Recursively calculates the binomical coefficient term of n and k using
* the memoizazion methood
*
* #param n
* the upper nonnegative integer of the binomical coefficient
* #param k
* the lower nonnegative integer of the binomical coefficient
* #returns the computed binomical coefficient
*/
public static long binomial(int n, int k) {
long[][] mem = new long[n + 1][k + 1];
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= n; j++) {
mem[i][j] = -1;
}
}
return binomial(n, k, mem);
}
public static long binomial(int n, int k, long[][] mem) {
if (k > n)
return 0;
if (k == 0 || n == 0)
return 1;
if (mem[n - 1][k] == -1) {
mem[n - 1][k] = binomial(n - 1, k, mem);
}
if (mem[n - 1][k - 1] == -1) {
mem[n - 1][k - 1] = binomial(n - 1, k - 1, mem);
}
return (mem[n - 1][k] + mem[n - 1][k - 1]);
}
}
A very simple mistake cause this error in function public static long binomial(int n, int k) change n in inner for with k, I mean :
public static long binomial(int n, int k) {
long[][] mem = new long[n + 1][k + 1];
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= k; j++) {
mem[i][j] = -1;
}
}
return binomial(n, k, mem);
}
is your correct function.

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