This is my solution for finding out the maximum sum of a subarray for a given array using Segment Tree (http://www.spoj.com/problems/GSS1/) but I am getting TLE (Time Limit Exceeded error) for this. Can anyone suggest more optimizations for this code?
public class segmentTree {
int st[];
segmentTree(int arr[], int n){
int x = (int)Math.ceil(Math.log(n)/Math.log(2));
int maxSize = (int)Math.pow(2, x)<<1 - 1;
st = new int[maxSize];
constructSTUtil(arr, 0, n-1, 0);
}
int getMid(int s, int e) {
return s + (e - s)>>1;
}
int getSumUtil(int ss, int se, int qs, int qe, int si)
{
if (qs <= ss && qe >= se)
return st[si];
if (se < qs || ss > qe)
return 0;
int mid = getMid(ss, se);
return getSumUtil(ss, mid, qs, qe, si<<1 + 1) +
getSumUtil(mid + 1, se, qs, qe, si<<1 + 2);
}
int getSum(int n, int qs, int qe)
{
if (qs < 0 || qe > n - 1 || qs > qe) {
return -1;
}
return getSumUtil(0, n - 1, qs, qe, 0);
}
int constructSTUtil(int arr[], int ss, int se, int si)
{
if (ss == se) {
st[si] = arr[ss];
return arr[ss];
}
int mid = getMid(ss, se);
st[si] = constructSTUtil(arr, ss, mid, si<<1 + 1) +
constructSTUtil(arr, mid + 1, se, si<<1 + 2);
return st[si];
}
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(in.readLine().trim());
int array[] = new int[n];
String arr[] = new String[n];
arr = in.readLine().split(" ");
for(int i=0; i<n; i++){
array[i] = Integer.parseInt(arr[i].trim());
}
segmentTree tree = new segmentTree(array, n);
int m = Integer.parseInt(in.readLine());
while(m-- > 0){
String ind[] = new String[2];
ind = in.readLine().split(" ");
int x = Integer.parseInt(ind[0].trim());
int y =Integer.parseInt(ind[1].trim());
int maxSum = -999999999;
for(int i=x-1; i<=y-1; i++){
for(int j=x-1; j<=y-1; j++){
if(tree.getSum(n, i, j) > maxSum)
maxSum = tree.getSum(n, i, j);
}
}
System.out.println(maxSum);
}
}
}
Related
I am trying to implement merge sort algorithm with some optimization like using temp storage only once and avoiding the copy till the last.Everything is okay and many test files are passing except some.The thing that is happening here is with unsorted array,the algorithm is showing some problems.I have written print statements in my code trying to reach the problem,but unable to do so.As many tests are passing,i believe there is nothing major wrong in the program,just it misses something.
I have tried to implement the program and it is successful in many ways,just 3 cases doesn't pass.But,the main problem i am facing is that test case Mergesort_two() doesn't pass because its simple .It's just calling two numbers and asserting in sorted form,but my program is denying it.I believe its a minor error which i am unable to figure out.
public static void mergesort(int[] input, int[] temp,
int start, int end,
boolean intoTemp) {
if (start == end) {
return;
}
if ((start + 1) == end) {
if (intoTemp == true) {
temp[start] = input[start];
return;
}
}
if (start < end) {
if (intoTemp == false) {
intoTemp = true;
int mid = (start + end)/2;
mergesort(input, temp, start, mid, intoTemp);
mergesort(input, temp, mid, end, intoTemp);
merge(input, temp, start, mid, end);
System.out.println("Input Array: " + Arrays.toString(input) +
" Temp: " + Arrays.toString(temp) + " intoTemp: " +
intoTemp + "Start Mid End: " + start + " " + mid + " " + end);
}
else if(intoTemp == true) {
intoTemp = false;
int mid = (start + end)/2;
mergesort(input, temp, start, mid, intoTemp);
mergesort(input, temp, mid, end, intoTemp);
merge(temp, input, start, mid, end);
System.out.println("Input Array: " + Arrays.toString(input) +
" Temp: " + Arrays.toString(temp) + " intoTemp: " +
intoTemp + "Start Mid End: " + start + " " + mid + " " + end);
}
}
if (start == 0 && end == input.length) {
System.arraycopy(temp, 0, input, 0, input.length);
}
}
/** Merges input[start...mid-1] with input[mid...end-1] into
* output[start...end-1]. The input array should not be modified at
* all, and only start...end-1 of the output array should be changed.
*
* #param input Input array
* #param output Output array
* #param start Starting index
* #param mid Midpoint index
* #param end Ending index+1
*/
public static void merge(int[] input, int[] output,
int start, int mid, int end) {
if (input == null || (start == mid && mid == end)) {
return;
}
int i = start;
int j = mid - 1;
int k = mid;
int index = start;
while (i <= j && k < end) {
if (input[i] <= input[k]) {
output[index] = input[i];
i++;
index++;
}
if (input[i] > input[k]) {
output[index] = input[i];
k++;
index++;
}
}
while (i <= j) {
output[index] = input[i];
index++;
i++;
}
while (k < end) {
output[index] = input[k];
index++;
k++;
}
}
}
////// Test Cases
#Test
public void testMergesort_Two() {
System.out.println("mergesort one element");
int[] array = new int[2];
// Already sorted
array[0] = 10; array[1] = 13;
CSSE240_Assign4.mergesort(array);
assertEquals(array[0], 10);
assertEquals(array[1], 13);
// Unsorted
array[0] = 3; array[1] = -4;
CSSE240_Assign4.mergesort(array);
assertEquals(array[0], -4);
assertEquals(array[1], 3);
}
#Test
public void testMergesort_Large() {
System.out.println("mergesort one large");
Random rng = new Random();
for(int s = 3; s < 20; ++s) {
int[] array = new int[s];
int[] orig = new int[s];
// Fill with random values.
for(int i = 0; i < s; ++i) {
array[i] = rng.nextInt();
orig[i] = array[i];
}
CSSE240_Assign4.mergesort(array);
Arrays.sort(orig);
// Make sure both arrays agree
for(int i = 0; i < s; ++i)
assertEquals(orig[i], array[i]);
}
}
#Test
public void testMergeInterleaved() {
// Various cases where the left/right halves are interleaved. We test
// this by picking a modulo m and moving all the elements where
// e % m < m/2 to the right side.
System.out.println("merge reverse sorted");
for(int s = 3; s < 20; ++s) {
int[] array = new int[s];
int mid = 0;
// Move the elements of the array around into the two halves.
for(int m = 2; m < 5; ++m) {
// Populate the array with 0...s-1
for (int i = 0; i < s; ++i) {
array[i] = i;
}
int[] left = new int[s];
int[] right = new int[s];
int lc = 0, rc = 0;
for(int i = 0; i < s; ++i)
if(array[i] % m < m/2)
right[rc++] = array[i];
else
left[lc++] = array[i];
// Copy back into the array
int j = 0;
for(int i = 0; i < lc; ++i)
array[j++] = left[i];
for(int i = 0; i < rc; ++i)
array[j++] = right[i];
mid = lc; // Midpoint
int[] output = new int[s];
Arrays.fill(output, -1);
// TODO: check different endpoints...
CSSE240_Assign4.merge(array, output, 0, mid, s);
for(int i = 0; i < s; ++i)
assertEquals(output[i], i);
}
}
}
testMergesort_Two Failed : expected <-4> but was <3>
testMergeInterleaved Failed: expected <0> but was <1>
testMergeSort_Large Failed : expected:<-1131373963> but was:<-2038582366>
Changes noted in comments.
public static void mergesort(int[] input, int[] temp,
int start, int end,
boolean intoTemp) {
if (start == end) {
return;
}
if ((start + 1) == end) {
if (intoTemp == true) {
temp[start] = input[start];
return;
}
}
if (intoTemp == false) {
intoTemp = true;
int mid = (start + end)/2;
mergesort(input, temp, start, mid, intoTemp);
mergesort(input, temp, mid, end, intoTemp);
merge(temp, input, start, mid, end);
} else {
intoTemp = false;
int mid = (start + end)/2;
mergesort(input, temp, start, mid, intoTemp);
mergesort(input, temp, mid, end, intoTemp);
merge(input, temp, start, mid, end);
}
}
public static void merge(int[] input, int[] output,
int start, int mid, int end) {
int i = start;
int j = mid; // using j instead of k
// and mid instead of j
int index = start;
while (i < mid && j < end) { // using mid
if (input[i] <= input[j]) {
output[index] = input[i];
i++;
index++;
} else { // change
output[index] = input[j]; // was input[i]
j++;
index++;
}
}
while (i < mid) { // using mid
output[index] = input[i];
i++; // changed order for consistency
index++;
}
while (j < end) {
output[index] = input[j];
j++; // changed order for consistency
index++;
}
}
I'm trying to find the next greatest number from the user input.If the user gives 23 it shows the output as 32.If there is number greater number then it has to print the same given number.But if the user gives 03 it shows 3 but it has to show 30.Because it takes 03 as octal number.How can i change the code to show the correct output as 30?
public class Main
{
static void swap(char ar[], int i, int j)
{
char temp = ar[i];
ar[i] = ar[j];
ar[j] = temp;
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int num = in .nextInt();
char[] chars = ("" + num).toCharArray();
int i;
int n = chars.length;
for (i = n - 1; i > 0; i--)
{
if (chars[i] > chars[i - 1])
break;
}
if (i == 0)
System.out.println(num);
else {
int x = chars[i - 1], min = i;
for (int j = i + 1; j<n; j++)
{
if (chars[j] > x && chars[j]<chars[min])
min = j;
}
swap(chars, i - 1, min);
Arrays.sort(chars, i, n);
for (i = 0; i<n; i++)
System.out.print(chars[i]);
}
}
}
package com.demo;
import java.util.Arrays;
import java.util.Scanner;
public class Demo {
static void swap(char ar[], int i, int j)
{
char temp = ar[i];
ar[i] = ar[j];
ar[j] = temp;
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
//int num = in .nextInt();
char[] chars=null;
String numStr=in.next();
int num= Integer.valueOf(numStr);
if(numStr.startsWith("0")) {
chars= ("0" + num).toCharArray();
}else {
chars= ("" + num).toCharArray();
}
int i;
int n = chars.length;
for (i = n - 1; i > 0; i--)
{
if (chars[i] > chars[i - 1])
break;
}
if (i == 0)
System.out.println(num);
else {
int x = chars[i - 1], min = i;
for (int j = i + 1; j<n; j++)
{
if (chars[j] > x && chars[j]<chars[min])
min = j;
}
swap(chars, i - 1, min);
Arrays.sort(chars, i, n);
for (i = 0; i<n; i++)
System.out.print(chars[i]);
}
}
}
public static int findNextGreatestNumber(int[] arr, int k) {
int delta = Integer.MAX_VALUE;
int res = 0;
for (int a : arr) {
if (a - k > 0 && a - k < delta) {
delta = a - k;
res = a;
}
}
return delta == Integer.MAX_VALUE ? k : res;
}
You are reading the numbers from standard input as integers. Try reading them as strings instead:
Scanner in = new Scanner(System.in);
String num = in.nextLine();
char[] chars = num.toCharArray();
In your main(),take the input as String only, instead of taking it as integer.
String num=in.next();
What's wrong with my 3-way partition quicksort? When input data less then 100000 it work normal time. When input data = 100000 it work around 9 sec.
I use Dijkstra 3-way partition. If input data consists of a large number of identical elements everything work normal, when input data random work too slow.
static void randomizedQuickSort(int[] a, int l, int r) {
if (l >= r) {
return;
}
int[] m = Partition3(a, l, r);
randomizedQuickSort(a, l, m[0] - 1);
randomizedQuickSort(a, m[1] + 1, r);
}
private static int[] Partition3(int[] nums, int l, int r) {
Random random = new Random();
int k = random.nextInt(r - l + 1) + l;
int mid = nums[k];
int m1 = 0;
int i = 0;
int m2 = r;
while (m1 <= m2) {
if (nums[m1] < mid) {
swap(nums, i, m1);
i++;
m1++;
} else if (nums[m1] > mid) {
swap(nums, m1, m2);
m2--;
} else {
m1++;
}
}
return new int[]{i, m2};
}
You are doing something wrong as the number of swaps is O(n^2) If you count the number of calls to swap you get something like (the first number is the number of elements)
10000: Took 0.078000 seconds, and 33432534 swaps
20000: Took 0.291000 seconds, and 166934755 swaps
40000: Took 1.102000 seconds, and 702291723 swaps
80000: Took 4.482000 seconds, and 2837543629 swaps
160000: Took 17.590000 seconds, and 11373050608 swaps
The problem is the lines
int m1 = 0;
int i = 0;
where you sort from the start of the array on every sort.
int m1 = l; // sort from the start of the section.
int i = l;
The full version is....
public static void main(String[] args) {
for (int t = 100_000; t <= 100_000_000; t *= 10) {
int[] nums = new int[t];
for (int i = 0; i < nums.length; i++) {
nums[i] = random.nextInt();
}
long start = System.currentTimeMillis();
swaps = 0;
randomizedQuickSort(nums, 0, nums.length - 1);
long time = System.currentTimeMillis() - start;
for (int i=0;i<nums.length-1;i++)
if (nums[0] > nums[1])
throw new AssertionError();
System.out.printf("%d: Took %f seconds, and %d swaps%n", t, time / 1e3, swaps);
}
}
static void randomizedQuickSort(int[] a, int l, int r) {
if (l >= r) {
return;
}
long m = Partition3(a, l, r);
int m0 = (int) (m >> 32);
int m1 = (int) m;
randomizedQuickSort(a, l, m0 - 1);
randomizedQuickSort(a, m1 + 1, r);
}
static final Random random = new Random();
static long swaps = 0;
private static long Partition3(int[] nums, int l, int r) {
int k = random.nextInt(r - l + 1) + l;
int mid = nums[k];
int m1 = l;
int i = l;
int m2 = r;
while (m1 <= m2) {
if (nums[m1] < mid) {
swap(nums, i, m1);
i++;
m1++;
} else if (nums[m1] > mid) {
swap(nums, m1, m2);
m2--;
} else {
m1++;
}
}
return ((long) i << 32) | m2;
}
private static void swap(int[] nums, int i, int j) {
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
swaps++;
}
prints
100000: Took 0.018000 seconds, and 2032183 swaps
1000000: Took 0.168000 seconds, and 24872604 swaps
10000000: Took 1.709000 seconds, and 287681791 swaps
100000000: Took 19.015000 seconds, and 3353327832 swaps
With the Introduction to algorithm .The Professor intro that the random quick sort can decrease the percentage of bad situation and improve the performance of time cost.But I wonder if there any problem with my code that cause the result
in contrast.
Here are my java code
public class quickSort {
public final int size = 200000;
public final int times = 10;
#Test
public void quick_sort() {
int test1[] = new int[size];
int test2[];
int k = 0;
long t1 = 0;
long t2 = 0;
for (int i = 0; i < size; i++) {
test1[i] = i;
}
test2 = test1.clone();
while (k < times) {
shuffle(test1);
shuffle(test2);
long start1 = System.currentTimeMillis();
split1(test1, 0, test1.length -1);
t1 += System.currentTimeMillis() - start1;
long start2 = System.currentTimeMillis();
split2(test2, 0, test2.length -1);
t2 += System.currentTimeMillis() - start2;
k++;
}
System.out.println("normal quick sort time is" + t1 + "ms");
System.out.println("random quick sort time is " + t2 + "ms");
}
public void split1(int[] arr, int start, int end) {
if (start >= end) {
return;
} else {
int middle = sort(arr, start, end);
split1(arr, start, middle - 1);
split1(arr, middle + 1, end);
}
}
public void split2(int[] arr, int start, int end) {
if (start >= end) {
return;
} else {
int middle = random_sort(arr, start, end);
split2(arr, start, middle - 1);
split2(arr, middle + 1, end);
}
}
// random quick sort
public int random_sort(int[] arr, int start, int end) {
int random = start + new Random().nextInt(end - start + 1);
int key = arr[random];
int loop = start;
int front = random == start ? start + 1 : start;
while (loop <= end) {
if (loop == random) {
loop++;
continue;
}
if (arr[loop] < key) {
int temp = arr[loop];
arr[loop] = arr[front];
arr[front] = temp;
front = front + 1 == random ? front += 2 : front + 1;
}
loop++;
}
if (front < end) {
int temp = arr[random];
arr[random] = arr[front];
arr[front] = temp;
} else {
front = end;
}
return front;
}
// normal quick sort
public int sort(int[] arr, int start, int end) {
int loop = start;
int key = arr[start];
int front = start + 1;
while (loop <= end) {
if (key > arr[loop]) {
int temp = arr[loop];
arr[loop] = arr[front];
arr[front++] = temp;
}
loop++;
}
if (front != 1) {
int temp = arr[front - 1];
arr[front - 1] = arr[start];
arr[start] = temp;
}
return front - 1;
}
// shuffle the Array
public void shuffle(int[] arr) {
int length = arr.length;
int random_num = 0;
for (int i = 0; i < length; i++) {
random_num = new Random().nextInt(length);
int temp = arr[i];
arr[i] = arr[random_num];
arr[random_num] = temp;
}
}
}
I was asked to sort and search an array. The sorting the array was simple and my code worked but then whenever I try to call the binary search method it works for the first element in the array but gives me "-1" as a result
My full code is as follows:
public static void main(String[] args) {
int[] array = new int[5];
array[0] = 50;
array[1] = 40;
array[2] = 10;
array[3] = 20;
array[4] = 100;
sort(array, (array.length - 1));
for (int x = 0; x < array.length; x++) {
System.out.println(" " + array[x]);
}
System.out.println("");
System.out.println("Binary search (R): " + rBsearch(array, 0, (array.length), 20));
}
public static void sort(int[] a, int last) {
if (last > 0) {
int max = findMax(a, last);
swap(a, last, max);
sort(a, last - 1);
}
}
public static int rBsearch(int[] L, int low, int high, int k) {
int mid = (low + high) / 2;
if (low > high) {
return -1;
} else if (L[mid] == k) {
return mid;
} else if (L[mid] < k) {
return rBsearch(L, k, mid + 1, high);
} else {
return rBsearch(L, k, low, mid - 1);
}
}
public static int findMax(int[] arr, int last) {
int max = 0;
for (int i = 0; i <= last; i++) {
if (arr[i] > arr[max]) {
max = i;
}
}
return max;
}
public static void swap(int[] arr, int last, int max) {
int temp = arr[last];
arr[last] = arr[max];
arr[max] = temp;
}
You goofed up the binary search intervals
public static int rBsearch(int[] L, int low, int high, int k) {
int mid = (low + high) / 2;
if (low > high) {
return -1;
} else if (L[mid] == k) {
return L[mid];
} else if (L[mid] < k) {
return rBsearch(L, mid + 1, high, k);
} else {
return rBsearch(L, low, mid - 1, k);
}
}
You did a mistake in calling the rBsearch method in the following lines
Instead of
else if (L[mid] < k) {
return rBsearch(L, k, mid + 1, high);
} else {
return rBsearch(L, k, low, mid - 1);
}
You should use
else if (L[mid] < k) {
return rBsearch(L, mid + 1, high,k); //the order of the parameters
} else {
return rBsearch(L, low, mid - 1,k);
}
Easiest way is:
Convert you array to list: Arrays.asList(array)
For sort: Collections#sort
For search: Collections#binarySearch
See this
Take Array From User
Sort Array using Build-in Function of Java...
then Search Element using Binary Search....
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Scanner;
class BinarySearch
{
public static void main(String args[])
{
int array[];
Scanner input = new Scanner(System.in);
System.out.println("Enter number of elements:");
int Size_Of_Array = input.nextInt();
array = new int[Size_Of_Array];
System.out.println("Enter " + Size_Of_Array + " integers");
for (int counter = 0; counter < Size_Of_Array; counter++)
array[counter] = input.nextInt();
Arrays.sort(array);
System.out.println("Sorting Array is :-");
for (int counter = 0; counter < Size_Of_Array; counter++)
System.out.println(array[counter]);
System.out.println("Enter the search value:");
int Searching_item = input.nextInt();
int First_Index=0;
int Last_Index=Size_Of_Array-1;
int Middle_Index=(First_Index+Last_Index)/2;
while(First_Index <= Last_Index)
{
if(array[Middle_Index] < Searching_item)
{
First_Index=Middle_Index+1;
}
else if ( array[Middle_Index] == Searching_item )
{
System.out.println(Searching_item + " found at location " + (Middle_Index + 1) + ".");
break;
}
else
{
Last_Index = Middle_Index - 1;
}
Middle_Index = (First_Index + Last_Index)/2;
if ( First_Index > Last_Index )
{
System.out.println(Searching_item + " is not found.\n");
}
}
}
}
Result of BinarySearch