time limit exceeded on java code of UVA 11516 Wifi - java

I am wondering why my code keeps having this "time limit exceed" on the uva-online judge page (http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2511), it is supposed to execute in 1 second but I don't know which input they use (my code works and do exactly what it supposed).. I am wondering that maybe the while loop of the testCases have something to do, because when I remove it it says wrong answer.. this is my code:
public class Main {
private static final int TAM = 10000; // TAM equals to the posible numbers of houses
private static int[] auxHouses;
private static int nHouses[];
private static int testCases;
private static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
nHouses = new int[TAM];
// First we read the input
// Read the variable of testCases
testCases = scanner.nextInt();
while (testCases > 0) {
float sol = binarySearch(testCases);
System.out.println(sol);
testCases--;
}
}
public static float binarySearch(int tC) {
int routers = 0, houses = 0;
int pivot = 0;
int hi = 0;
// While for the testCases
routers = scanner.nextInt();
houses = scanner.nextInt();
// Read the numbers of the houses
for (int i = 0; i < houses; i++) {
nHouses[i] = scanner.nextInt();
}
if (routers >= houses) {
return 0;
}
// First we sort the array
sortHouses(nHouses, houses);
// Prepare the variables of the index
int lo = 0;
hi = 2 * (nHouses[houses - 1] - nHouses[0] + 1); // 2*(loc[h-1]-loc[0]+1);
// Now we execute the binary search algorithm
while (hi > lo) {
pivot = (lo + hi) / 2;
int start = nHouses[0];
int need = 1;
for (int i = 0; i < houses; i++) {
if (nHouses[i] > start + pivot) {
start = nHouses[i];
need++;
}
}
if (need > routers) {
lo = pivot + 1;
} else {
hi = pivot;
}
}
return (float) hi / 2;
}
public static void sortHouses(int[] nhouses, int length) {
// First we check if the are actually values on the array
if (nhouses.length == 0) {
return;
}
// Copy the array of int into an auxiliary variable and the numbers of
// int in the array
auxHouses = nhouses;
int lengthArray = length;
quickSort(0, lengthArray - 1);
}
public static void quickSort(int low, int high) {
// System.out.println("Array " + Arrays.toString(auxHouses));
int i = low, j = high;
// Get the pivot element from the middle of the list
int pivot = auxHouses[low + (high - low) / 2];
// Divide into two lists
while (i <= j) {
// If the current value from the left list is smaller then the pivot
// element then get the next element from the left list
while (auxHouses[i] < pivot) {
i++;
}
// If the current value from the right list is larger then the pivot
// element then get the next element from the right list
while (auxHouses[j] > pivot) {
j--;
}
// If we have found a values in the left list which is larger then
// the pivot element and if we have found a value in the right list
// which is smaller then the pivot element then we exchange the
// values.
// As we are done we can increase i and j
if (i <= j) {
exchange(i, j);
i++;
j--;
}
}
// Recursion
if (low < j)
quickSort(low, j);
if (i < high)
quickSort(i, high);
}
private static void exchange(int i, int j) {
int temp = auxHouses[i];
auxHouses[i] = auxHouses[j];
auxHouses[j] = temp;
}
}
I have it with the quicksort implemented, but if you use Arrays.sort(..) method instead it says the same thing..TLE, what could be doing wrong?

Related

Why do we use two different loop variables while sorting an array using merge sort?

I was learning to merge sort an integer array, when I noticed that while copying the sorted array elements to the original array, we need two separate loop variables to run simultaneously, while the values at those indices are copied to the original array. Here is the code for reference:
class MergeSort {
public static void sort(int arr[], int si, int ei, int mid) {
int merged[] = new int[ei - si + 1];
int index1 = si; // tracks the first array
int index2 = mid + 1; // tracks the second array
int i = 0;
while (index1 <= mid && index2 <= ei) {
if (arr[index1] <= arr[index2]) {
merged[i++] = arr[index1++];
} else {
merged[i++] = arr[index2++];
}
} // end of while
while (index1 <= mid) {
merged[i++] = arr[index1++];
}
while (index2 <= ei) {
merged[i++] = arr[index2++];
}
// to copy merged[] to arr[]
int j = si;
for (i = 0; i < merged.length; i++, j++) {
arr[j] = merged[i];
}
} // end sort()
public static void divide(int arr[], int si, int ei) {
// base case
if (si >= ei) {
return;
} // end of base case
int mid = si + (ei - si) / 2; // same as (ei-si)/2 but with less space complexity
divide(arr, si, mid);
divide(arr, mid + 1, ei);
sort(arr, si, ei, mid);
} // end of divide
public static void main(String args[]) {
int arr[] = { 1, 8, 0, 7, -4 };
int n = arr.length;
divide(arr, 0, n - 1);
for (int i = 0; i < n; i++) {
System.out.print(arr[i] + " ");
} // end of for
} // end of main
} // end of class
Notice that while copying the values of the array merged[] to the array arr[], we are using two separate variables i and j. I did try using only one loop variable, which went like:
for (int i = 0; i < arr.length; i++) {
arr[i] = merged[i];
}
but received an incorrect output. If anyone knows why we need two separate variables for the operation, please let me know. Thank you :)
You could use a single variable in this final loop, but you must add the offset of the start of the slice in the destination array:
for (int i = 0; i < arr.length; i++) {
arr[si + i] = merged[i];
}

How could I improve the speed/performance for this problem, Java

I saw this challenge on https://www.topcoder.com/ for Beginners. And I really wanted to complete it. I've got so close after so many failures. But I got stuck and don't know what to do no more. Here is what I mean
Question:
Read the input one line at a time and output the current line if and only if you have already read at least 1000 lines greater than the current line and at least 1000 lines less than the current line. (Again, greater than and less than are with respect to the ordering defined by String.compareTo().)
Link to the Challenge
My Solution:
public static void doIt(BufferedReader r, PrintWriter w) throws IOException {
SortedSet<String> linesThatHaveBeenRead = new TreeSet<>();
int lessThan =0;
int greaterThan =0;
Iterator<String> itr;
for (String currentLine = r.readLine(); currentLine != null; currentLine = r.readLine()){
itr = linesThatHaveBeenRead.iterator();
while(itr.hasNext()){
String theCurrentLineInTheSet = itr.next();
if(theCurrentLineInTheSet.compareTo(currentLine) == -1)++lessThan;
else if(theCurrentLineInTheSet.compareTo(currentLine) == 1)++greaterThan;
}
if(lessThan >= 1000 && greaterThan >= 1000){
w.println(currentLine);
lessThan = 0;
greaterThan =0;
}
linesThatHaveBeenRead.add(currentLine);
}
}
PROBLEM
I think the problem with my solution, is because I'm using nested loops which is making it a lot slower, but I've tried other ways and none worked. At this point I'm stuck. The whole point of this challenge is to make use of the most correct data-structure for this problem.
GOAL:
The goal is to use the most efficient data-structure for this problem.
Let me try to present just an accessible refinement of what to do.
public static void
doIt(java.io.BufferedReader r, java.io.PrintWriter w)
throws java.io.IOException {
feedNonExtremes(r, (line) -> { w.println(line);}, 1000, 1000);
}
/** Read <code>r</code> one line at a time and
* output the current line if and only there already were<br/>
* at least <code>nHigh</code> lines greater than the current line <br/>
* and at least <code>nLow</code> lines less than the current line.<br/>
* #param r to read lines from
* #param sink to feed lines to
* #param nLow number of lines comparing too small to process
* #param nHigh number of lines comparing too great to process
*/
static void feedNonExtremes(java.io.BufferedReader r,
Consumer<String> sink, int nLow, int nHigh) {
// collect nLow+nHigh lines into firstLowHigh; instantiate
// - a PriorityQueue(firstLowHigh) highest
// - a PriorityQueue(nLow, (a, b) -> String.compareTo(b, a)) lowest
// remove() nLow elements from highest and insert each into lowest
// for each remaining line
// if greater than the head of highest
// add to highest and remove head
// else if smaller than the head of lowest
// add to lowest and remove head
// else feed to sink
}
Made you a little example with Binary search, now in Java code. It will only use Binary search when newLine is within limits of the sorting.
public static void main(String[] args) {
// Create random lines
ArrayList<String> lines = new ArrayList<String>();
Random rn = new Random();
for (int i = 0; i < 50000; i++) {
int lenght = rn.nextInt(100);
char[] newString = new char[lenght];
for (int j = 0; j < lenght; j++) {
newString[j] = (char) rn.nextInt(255);
}
lines.add(new String(newString));
}
// Here starts logic
ArrayList<String> lowerCompared = new ArrayList<String>();
ArrayList<String> higherCompared = new ArrayList<String>();
int lowBoundry = 1000, highBoundry = 1000;
int k = 0;
int firstLimit = Math.min(lowBoundry, highBoundry);
// first x lines sorter equal
for (; k < firstLimit; k++) {
int index = Collections.binarySearch(lowerCompared, lines.get(k));
if (index < 0)
index = ~index;
lowerCompared.add(index, lines.get(k));
higherCompared.add(index, lines.get(k));
}
for (; k < lines.size(); k++) {
String newLine = lines.get(k);
boolean lowBS = newLine.compareTo(lowerCompared.get(lowBoundry - 1)) < 0;
boolean highBS = newLine.compareTo(higherCompared.get(0)) > 0;
if (lowerCompared.size() == lowBoundry && higherCompared.size() == highBoundry && !lowBS && !highBS) {
System.out.println("Time to print: " + newLine);
continue;
}
if (lowBS) {
int lowerIndex = Collections.binarySearch(lowerCompared, newLine);
if (lowerIndex < 0)
lowerIndex = ~lowerIndex;
lowerCompared.add(lowerIndex, newLine);
if (lowerCompared.size() > lowBoundry)
lowerCompared.remove(lowBoundry);
}
if (highBS) {
int higherIndex = Collections.binarySearch(higherCompared, newLine);
if (higherIndex < 0)
higherIndex = ~higherIndex;
higherCompared.add(higherIndex, newLine);
if (higherCompared.size() > highBoundry)
higherCompared.remove(0);
}
}
}
You need to implement binary search and also need to handle duplicates.
I've done some code sample here which does what you want ( may contains bugs).
public class CheckRead1000 {
public static void main(String[] args) {
// generate strings in revert order to get the worse case
List<String> aaa = new ArrayList<String>();
for (int i = 50000; i > 0; i--) {
aaa.add("some string 123456789" + i);
}
// fast solution
ArrayList<String> sortedLines = new ArrayList<>();
long st1 = System.currentTimeMillis();
for (String a : aaa) {
checkIfRead1000MoreAndLess(sortedLines, a);
}
System.out.println(System.currentTimeMillis() - st1);
// doIt solution
TreeSet<String> linesThatHaveBeenRead = new TreeSet<>();
long st2 = System.currentTimeMillis();
for (String a : aaa) {
doIt(linesThatHaveBeenRead, a);
}
System.out.println(System.currentTimeMillis() - st2);
}
// solution doIt
public static void doIt(SortedSet<String> linesThatHaveBeenRead, String currentLine) {
int lessThan = 0;
int greaterThan = 0;
Iterator<String> itr = linesThatHaveBeenRead.iterator();
while (itr.hasNext()) {
String theCurrentLineInTheSet = itr.next();
if (theCurrentLineInTheSet.compareTo(currentLine) == -1) ++lessThan;
else if (theCurrentLineInTheSet.compareTo(currentLine) == 1) ++greaterThan;
}
if (lessThan >= 1000 && greaterThan >= 1000) {
// System.out.println(currentLine);
lessThan = 0;
greaterThan = 0;
}
linesThatHaveBeenRead.add(currentLine);
}
// will return if we have read more at least 1000 string more and less then our string
private static boolean checkIfRead1000MoreAndLess(List<String> sortedLines, String newLine) {
//adding string to list and calculating its index and the last search range
int indexes[] = addNewString(sortedLines, newLine);
int index = indexes[0]; // index of element
int low = indexes[1];
int high = indexes[2];
//we need to check if this string already was in list for instance
// 1,2,3,4,5,5,5,5,5,6,7 for 5 we need to count 'less' as 4 and 'more' is 2
int highIndex = index;
for (int i = highIndex + 1; i < high; i++) {
if (sortedLines.get(i).equals(newLine)) {
highIndex++;
} else {
//no more duplicates
break;
}
}
int lowIndex = index;
for (int i = lowIndex - 1; i > low; i--) {
if (sortedLines.get(i).equals(newLine)) {
lowIndex--;
} else {
//no more duplicates
break;
}
}
// just calculating how many we did read more and less
if (sortedLines.size() - highIndex - 1 > 1000 && lowIndex > 1000) {
return true;
}
return false;
}
// simple binary search will insert string and return its index and ranges in sorted list
// first int is index,
// second int is start of range - will be used to find duplicates,
// third int is end of range - will be used to find duplicates,
private static int[] addNewString(List<String> sortedLines, String newLine) {
if (sortedLines.isEmpty()) {
sortedLines.add(newLine);
return new int[]{0, 0, 0};
}
// int index = Integer.MAX_VALUE;
int low = 0;
int high = sortedLines.size() - 1;
int mid = 0;
while (low <= high) {
mid = (low + high) / 2;
if (sortedLines.get(mid).compareTo(newLine) < 0) {
low = mid + 1;
} else if (sortedLines.get(mid).compareTo(newLine) > 0) {
high = mid - 1;
} else if (sortedLines.get(mid).compareTo(newLine) == 0) {
// index = mid;
break;
}
if (low > high) {
mid = low;
}
}
if (mid == sortedLines.size()) {
sortedLines.add(newLine);
} else {
sortedLines.add(mid, newLine);
}
return new int[]{mid, low, high};
}
}

Find Median from a 2D Matrix where each row should be sorted and the multiplication of row and column number should be odd

Suppose a matrix of 3X3 where the elements are [{1,2,3}{3,6,6}{5,9,9}]. The expected output is 5. But the added code here showing 9. As the solution here is a copy from internet, please help me to understand the code as well. How the min-max value help to find the median and the other approaches as well as the use of binary search.
public class Solution {
public int binarySearch(ArrayList<Integer> arr, int x)
{
int l = 0, r = arr.size() - 1;
while (l <= r)
{
int m = l + (r-l)/2;
if (arr.get(m) == x)
return m;
if (arr.get(m) < x)
l = m + 1;
else
r = m - 1;
}
return -1;
}
public int findMedian(ArrayList<ArrayList<Integer>> A) {
int start=0;
int end=A.size()*A.get(0).size();
int value=-1;
int row=A.size();
int col=A.get(0).size();
int max=Integer.MIN_VALUE;
int min=Integer.MAX_VALUE;
for(int i=0;i<A.size();i++){
if(A.get(i).get(0)<min){
min=A.get(i).get(0);
}
if(A.get(i).get(col-1)>max){
max=A.get(i).get(col-1);
}
}
int desiredIndex=(row * col+1)/2;
while(min<max){
int mid=min+(max-min)/2;
int place = 0;
int index = 0;
for(int i = 0; i < row; ++i)
{
index = binarySearch(A.get(i),mid);
System.out.println("index of : "+index);
if(index < 0)
index = Math.abs(index) - 1;
else
{
while(index <A.get(i).size() && A.get(i).get(index) == mid)
index += 1;
}
place = place + index;
}
if (place < desiredIndex)
min = mid + 1;
else
max = mid;
}
return min;
}
}
I'm not sure where you were searching, but the solution to your problem is readily available online:
public class MedianInRowSorted {
// function to find median in the matrix
static int binaryMedian(int m[][],int r, int c)
{
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for(int i=0; i<r ; i++)
{
// Finding the minimum element
if(m[i][0] < min)
min = m[i][0];
// Finding the maximum element
if(m[i][c-1] > max)
max = m[i][c-1];
}
int desired = (r * c + 1) / 2;
while(min < max)
{
int mid = min + (max - min) / 2;
int place = 0;
int get = 0;
// Find count of elements smaller than mid
for(int i = 0; i < r; ++i)
{
get = Arrays.binarySearch(m[i],mid);
// If element is not found in the array the
// binarySearch() method returns
// (-(insertion_point) - 1). So once we know
// the insertion point we can find elements
// Smaller than the searched element by the
// following calculation
if(get < 0)
get = Math.abs(get) - 1;
// If element is found in the array it returns
// the index(any index in case of duplicate). So we go to last
// index of element which will give the number of
// elements smaller than the number including
// the searched element.
else
{
while(get < m[i].length && m[i][get] == mid)
get += 1;
}
place = place + get;
}
if (place < desired)
min = mid + 1;
else
max = mid;
}
return min;
}
You can test it by running this code inside your main method:
int matrix [][] = {{1,2,3},{3,6,6},{5,9,9}};
System.out.println(binaryMedian(matrix, 3, 3));
It'll return 5, which is the correct median. Let me know if you have any questions and I can go more in depth as to how the function works!

Count swaps in mergesort

I'm trying to count minimum swaps(only consecutive swaps) in an array sorted by mergesort. It works for some cases but this case doesn't work for example: http://puu.sh/kC9mg/65e055807f.png. The first number is how many numbers it should sort, then you enter the numbers. In that case it should print 1 because the number of minimum consecutive swaps is 1 in this case which will swap 4 and 3.
This is the code I have:
public class MergeSort {
private int[] numbers;
private int[] helper;
private int number;
private long swapCounter = 0;
public MergeSort(int[] inputNumbers)
{
numbers = inputNumbers;
number = inputNumbers.length;
helper = new int[number];
mergesort(0, number-1);
}
private void mergesort(int low, int high) {
// check if low is smaller then high, if not then the array is sorted
if (low < high) {
// Get the index of the element which is in the middle
int middle = low + (high - low) / 2;
// Sort the left side of the array
mergesort(low, middle);
// Sort the right side of the array
mergesort(middle + 1, high);
// Combine them both
merge(low, middle, high);
}
}
private void merge(int low, int middle, int high) { // Merge it
long internCounter = 0;
for (int i = low; i <= high; i++) { // Copy both parts into the helper array
helper[i] = numbers[i];
}
int i = low;
int j = middle + 1;
int k = low;
while (i <= middle && j <= high) { // Copy the smallest values from either the left or the right side back to the original array
if (helper[i] < helper[j]) {
numbers[k] = helper[i];
i++;
internCounter++;
} else {
numbers[k] = helper[j];
j++;
swapCounter += internCounter;
}
k++;
}
while (i <= middle) { // Copy the rest of the left side of the array into the target array
numbers[k] = helper[i];
k++;
i++;
swapCounter += internCounter;
}
}
public long getCounter() // Get the counter
{
return this.swapCounter;
}
}
And this is my main class:
import java.util.Scanner;
public class Fr {
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
int numberOfStudents;
int[] inputNumbers2;
numberOfStudents = input.nextInt();
inputNumbers2 = new int[numberOfStudents];
for(int i = 0; i < numberOfStudents; i++)
{
inputNumbers2[i] = input.nextInt();
}
MergeSort ms = new MergeSort(inputNumbers2);
System.out.println(ms.getCounter());
input.close();
}
}
Do anyone have any thoughts what could be wrong?
I don't think you need the intern counter at all. Just count how many positions you swap an element when taking an element from the high half:
public class MergeSort {
private int[] numbers;
private int[] helper;
private int number;
private long swapCounter = 0;
public MergeSort(int[] inputNumbers)
{
numbers = inputNumbers;
number = inputNumbers.length;
helper = new int[number];
mergesort(0, number-1);
}
private void mergesort(int low, int high) {
// check if low is smaller then high, if not then the array is sorted
if (low < high) {
// Get the index of the element which is in the middle
int middle = low + (high - low) / 2;
// Sort the left side of the array
mergesort(low, middle);
// Sort the right side of the array
mergesort(middle + 1, high);
// Combine them both
merge(low, middle, high);
}
}
private void merge(int low, int middle, int high) { // Merge it
for (int i = low; i <= high; i++) { // Copy both parts into the helper array
helper[i] = numbers[i];
}
int i = low;
int j = middle + 1;
int k = low;
while (i <= middle && j <= high) { // Copy the smallest values from either the left or the right side back to the original array
if (helper[i] < helper[j]) {
numbers[k] = helper[i];
i++;
} else {
numbers[k] = helper[j];
swapCounter += (j-k);
j++;
}
k++;
}
while (i <= middle) { // Copy the rest of the left side of the array into the target array
numbers[k] = helper[i];
k++;
i++;
}
}
public long getCounter() // Get the counter
{
return this.swapCounter;
}
}

Algorithm comparison in java: test program does not work

I'm trying to compare the execution of the java implementation of QuickSort and its hybrid version (using InsertionSort for those partitions which are smaller than an integer k). I wrote a test class to analyze the behaviour of the algorithms for some values ok k (1 <= k <= 25). For each value of k the class compares for different sizes of the input array the two algorithms.
I can't run the program for some values of the size of the array, for instance for values greater than 4000. The execution reach some different values and then freeze, after a while it will finish but I have no output of the computation. (I'm using eclipse).
What could be the problem? I wish to perform the comparation of the two algoritms for an array size from 10 to 10000 (at least). The code is listed below:
public class Main {
private static final int MAX_K = 25;
private static final int MAX_SIZE = 4500;
private static final int ADD_SIZE = 100;
private static int size = 10;
private static QuickSort qSort;
private static HybridSort hSort;
private static void initArray(int[] A) {
Random rand = new Random();
for (int i = 0; i < A.length; i++) {
// A[i] = (int)(Math.random()*100000);
A[i] = rand.nextInt();
}
}
private static int[] A = new int[10];
private static int[] B = new int[10];
public static void main(String[] args) {
try {
FileWriter fstream = new FileWriter("out.txt");
BufferedWriter out = new BufferedWriter(fstream);
out.write("Init file");
qSort = new QuickSort();
hSort = new HybridSort();
/************************************************/
/* Comparison */
/************************************************/
for (int i = 1; i <= MAX_K; i++) {
hSort.setK(i);
int p = 0;
for (int j = size; j <= MAX_SIZE; j = j + ADD_SIZE) {
A = new int[j];
B = new int[j];
initArray(A);
initArray(B);
long sTime = System.nanoTime();
qSort.quickSort(A, 0, A.length - 1);
long qDuration = System.nanoTime() - sTime;
sTime = System.nanoTime();
hSort.hybridSort(B, 0, B.length - 1);
long hDuration = System.nanoTime() - sTime;
out.append(/* "\nA: " +printArray(A)+ */"K: " + i + " A["
+ j + "]\tQ = " + qDuration + " H = " + hDuration
+ "\n");
String h = Long.toString(hDuration);
String q = Long.toString(qDuration);
if (h.length() < q.length()) {
p++;
out.append("\t#OUTPERM for K: "
+ i
+ "\t\t"
+ hDuration
+ "\t\t < \t\t "
+ qDuration
+ "\t\t\t\t| A[]\t\t"
+ A.length
+ ((q.length() - h.length()) == 2 ? "\t Magn. 2"
: "") + "\n");
}
}
if (p > 0)
out.append("#P= " + p + " for K= " + i + "\n\n");
}
out.append("Close file");
out.close();
} catch (IOException e) {
}
}
}
The algorithm classes:
public class QuickSort {
public void quickSort(int[] A, int left, int right){
if (left < right) {
int m = Partition(A, left, right);
quickSort(A, left, m-1);
quickSort(A, m, right);
}
}
private int Partition(int[] A, int left, int right){
int pivot = A[right];
int i = left;
int j = right;
while (true) {
while ( (A[j] > pivot)) {
j--;
}
while ((A[i] < pivot)) {
i++;
}
if (i < j){
int swap = A[j];
A[j] = A[i];
A[i] = swap;
}else{
return i;
}
}
}
}
public class HybridSort {
int k;
int m;
InsertionSort iSort;
public HybridSort() {
k = 3;
iSort = new InsertionSort();
}
public void hybridSort(int[] A, int left, int right) {
if (left < right) {
if ((right - left) < k) {
iSort.sort(A,left,right);
} else {
m = Partition(A, left, right);
hybridSort(A, left, m - 1);
hybridSort(A, m, right);
}
}
}
private int Partition(int[] A, int left, int right) {
int pivot = A[right];
int i = left;
int j = right;
while (true) {
while ((A[j] > pivot) && (j >= 0)) {
j--;
}
while ((A[i] < pivot) && (i < A.length)) {
i++;
}
if (i < j) {
int swap = A[j];
A[j] = A[i];
A[i] = swap;
} else {
return i;
}
}
}
public void setK(int k) {
this.k = k;
}
}
Your implementation of Partition is not correct. Consider the small test below (I made Partition static for my convenience).
Both while loops won't be executed, because A[i] == A[j] == pivot. Moreover, i<j, so the two elements will be swapped, resulting in exactly the same array. Therefore, the outer while loop becomes infinite.
The same problem occurs for any array for which the first and last element are the same.
public class Test {
public static void main(String[] args) {
int[] A = {1, 1};
Partition(A, 0, 1);
}
private static int Partition(int[] A, int left, int right){
int pivot = A[right];
int i = left;
int j = right;
while (true) {
while ( (A[j] > pivot)) {
j--;
}
while ((A[i] < pivot)) {
i++;
}
if (i < j){
int swap = A[j];
A[j] = A[i];
A[i] = swap;
}else{
return i;
}
}
}
}
Have you tried increasing memory settings for your code to run in eclipse.
You may find this Setting memory of Java programs that runs from Eclipse helpful.
Some tips / possible solution?:
I haven't read your implementation of QuickSort or HybridSort but I am assuming they are correct.
If you are comparing the performance of two algorithms you should most definitely compare their performance to indentical inputs. Currently you are generating two random arrys (albeit of the same size). This isn't necessarily going to be an accurate test as I can easily find a test case where one algorithm will outperform the other if the random generator is out to troll you.
Your logic for comparing the two algorithms is a bit weird and incorrect according to me. Why do you compare the lengths of the strings of the times? according to your logic 1 is the same as 9 and 1,000,000,000 is the same as 9,999,999,999 which is clearly incorrect. One algorithm is almost 10 times faster than the other.
Moreover, one reason for no output might be the reason that you are only outputing when hybridsort is better than quicksort and not the other way around. I am sure there are other reasons as well but this could be one easily noticable reason (if your implementations are incorrect).
I do notice that you close your outputstream which is good as that is a very common reason why there is no output. You should however, close steams in the finally section of the try-catch as then they are guaranteed to close. You could be getting an IOException and in your case this would also not close the outputsteam and consequently lead to no ouput in your file.
Here is a sample structure that I would follow for doing any comparitive testing. It is easy to read and easy to debug with enough output for you to figure out which algorithm performs better. This is merely a suggestion.
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Random;
public class Tester {
private static int[] initArray(int size) {
Random rand = new Random();
int[] arr = new int[size];
for (int i = 0; i < arr.length; i++) {
arr[i] = rand.nextInt();
}
return arr;
}
public static void main(String[] args) {
final int MAX_ITERATIONS = 25;
final int INITIAL_ARRAY_SIZE = 10;
final int MAX_ARRAY_SIZE = 4500;
final int ARRAY_SIZE_INCREMENT = 100;
long start;
int[] score = null;
PrintWriter out = null;
try {
out = new PrintWriter(new FileOutputStream("out.txt"));
for (int arraySize = INITIAL_ARRAY_SIZE; arraySize <= MAX_ARRAY_SIZE; arraySize += ARRAY_SIZE_INCREMENT) {
// score[0] is for quickSort and score[1] is for hybridSort
score = new int[2];
for (int iteration = 0; iteration < MAX_ITERATIONS; iteration++) {
int[] testArray = initArray(arraySize);
int[] testArrayCopy = new int[arraySize];
System.arraycopy(testArray, 0, testArrayCopy, 0, arraySize);
start = System.nanoTime();
// Do quicksort here using testArray
long qSortfinish = System.nanoTime() - start;
System.arraycopy(testArray, 0, testArrayCopy, 0, arraySize);
start = System.nanoTime();
// Do hybridsort here using testArrayCopy
long hybridSortfinish = System.nanoTime() - start;
// Keep score
if (qSortfinish < hybridSortfinish)
score[0]++;
else if (qSortfinish > hybridSortfinish) {
score[1]++;
} else {
score[0]++;
score[1]++;
}
}
out.println("Array Size: " + arraySize + " QuickSort: " + score[0] + " HybridSort: " + score[1]);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (out != null)
out.close();
}
}
}

Categories

Resources