I just have a question on how to see which method is being run in a println to verify if my code is correct. I want to see if the brute force code runs or the max sub array method runs when the user inputs numbers. How would I write that in a println in the main method?
package a3;
import java.util.Scanner;
public class MaxSubarraySum2 {
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
System.out.println("Enter number of elements in array");
int N = scan.nextInt();
int[] arr = new int[ N ];
/* Accept N elements */
System.out.println("Enter "+ N +" elements");
for (int i = 0; i < N; i++)
arr[i] = scan.nextInt();
System.out.println("Max sub array sum = "+ max_sum(arr));
}
public static int max_sum(int[] arr)
{
int Crossover = 4;
if (Crossover > arr.length) {
//Max Sub array is being used
return max_sum(arr, 0, arr.length - 1);
}
//Brute Force is being used
else {
int N = arr.length, max = Integer.MIN_VALUE;
for (int i = 0; i < N; i++)
{
int sum = 0;
for (int j = i; j < N; j++)
{
sum += arr[j];
if (sum > max)
max = sum;
}
}
return max;
}
}
// Max Sub Array
public static int max_sum(int[] arr, int low, int mid, int high)
{
int l = Integer.MIN_VALUE, r = Integer.MIN_VALUE;
for (int i = mid, sum = 0; i >= low; i--)
if ((sum += arr[i]) > l)
l = sum;
for (int i = mid +1, sum = 0; i <= high; i++)
if ((sum += arr[i]) > r)
r = sum;
return l + r;
}
public static int max_sum(int[] arr, int low, int high)
{
if (low == high)
return arr[low];
int mid = (low + high)/2;
int max1 = max_sum(arr, low, mid);
int max2 = max_sum(arr, mid + 1, high);
int max3 = max_sum(arr, low, mid, high);
return Math.max(Math.max(max1, max2), max3);
}
}
Does the println have to be in the main function? I would recommend placing such debugging output in the place where the decision is being made:
if (Crossover > arr.length) {
// Max Sub array is being used
System.out.println("Max Sub array is being used");
return max_sum(arr, 0, arr.length - 1);
} else {
// Brute Force is being used
System.out.println("Brute Force is being used");
int N = arr.length, max = Integer.MIN_VALUE;
for (int i = 0; i < N; i++)
{
int sum = 0;
for (int j = i; j < N; j++)
{
sum += arr[j];
if (sum > max)
max = sum;
}
}
return max;
}
Just print stack trace of called method by following:
Thread.dumpStack();
Like:
// Max Sub Array
public static int max_sum(int[] arr, int low, int mid, int high)
{
Thread.dumpStack();
...
}
public static int max_sum(int[] arr, int low, int high)
{
Thread.dumpStack();
...
}
Related
You have been given a random integer array/list(ARR) and a number X. Find and return the number of distinct triplet(s) in the array/list which sum to X.
I have written this code:
public class Solution {
public static void merge(int arr[], int lb, int mid, int ub) {
int n1 = mid - lb + 1;
int n2 = ub - mid;
int arr1[] = new int[n1];
int arr2[] = new int[n2];
for (int i = 0; i < n1; i++)
arr1[i] = arr[lb + i];
for (int j = 0; j < n2; j++)
arr2[j] = arr[mid + 1 + j];
int i = 0, j = 0;
int k = lb;
while (i < n1 && j < n2) {
if (arr1[i] <= arr2[j])
arr[k] = arr1[i++];
else
arr[k] = arr2[j++];
k++;
}
while (i < n1)
arr[k++] = arr1[i++];
while (j < n2)
arr[k++] = arr2[j++];
}
public static void mergeSort(int arr[], int lb, int ub) {
if (lb < ub) {
int mid = lb + (ub - lb) / 2;
mergeSort(arr, lb, mid);
mergeSort(arr, mid + 1, ub);
merge(arr, lb, mid, ub);
}
}
public static int tripletSum(int[] arr, int num) {
mergeSort(arr, 0, arr.length - 1);
int n = arr.length;
int count = 0;
for (int i = 0; i < n - 2; i++) {
int sum = num - arr[i];
int j = i + 1;
int k = n - 1;
while (j < k) {
if (arr[j] + arr[k] == sum) {
count++;
k--;
} else if (arr[j] + arr[k] > sum) {
k--;
} else
j++;
}
}
return count;
}
}
Input array was - 1 3 3 3 3 3 3
Input num = 9
Output Generated - 10
Expected output - 20
Help me out with this I'm trying to find the solution for many hours. Also, the time complexity of the program should not exceed O(n²).
The given code works fine for all test cases.
import java.util.Arrays;
public class Solution {
public static int tripletSum(int[] arr, int num) {
Arrays.sort(arr);
int n = arr.length;
int Numtripletsum = 0;
for(int i=0;i<n;i++)
{
int pairSumFor = num - arr[i];
int numPairs = pairSum(arr, (i+1), (n-1), pairSumFor);
Numtripletsum+=numPairs;
}
return Numtripletsum;
}
private static int pairSum(int[] arr, int startIndex, int endIndex, int num ){
int numPair = 0;
while(startIndex < endIndex){
if(arr[startIndex] + arr[endIndex] < num){
startIndex++;
}
else if(arr[startIndex] + arr[endIndex] > num){
endIndex--;
}
else
{
int elementAtStart = arr[startIndex];
int elementAtEnd = arr[endIndex];
if(elementAtStart == elementAtEnd){
int totalElementsFromStartToEnd = (endIndex - startIndex) + 1;
numPair += (totalElementsFromStartToEnd * (totalElementsFromStartToEnd -1) /2);
return numPair;
}
int tempStartIndex = startIndex + 1;
int tempEndIndex = endIndex - 1;
while(tempStartIndex <= tempEndIndex && arr[tempStartIndex] == elementAtStart){
tempStartIndex+=1;
}
while(tempEndIndex >= tempStartIndex && arr[tempEndIndex] == elementAtEnd){
tempEndIndex-=1;
}
int totalElementsFromStart = (tempStartIndex - startIndex);
int totalElementsFromEnd = (endIndex - tempEndIndex);
numPair += (totalElementsFromStart * totalElementsFromEnd);
startIndex = tempStartIndex;
endIndex = tempEndIndex;
}
}
return numPair;
}
}
I did it in this way, hope I understood it well.
public static int tripletSum(int[] arr, int num) {
int loops = 0; // just to check the quality of the code
int counter = 0;
for (int i1 = 0; i1 < arr.length - 2; i1++) {
for (int i2 = i1 + 1; i2 < arr.length - 1; i2++) {
for (int i3 = i2 + 1; i3 < arr.length; i3++) {
loops++;
if (arr[i1] + arr[i2] + arr[i3] == num) {
counter++;
}
}
}
}
// Check for not exceeding O(n^2)
if (loops <= arr.length * arr.length) {
System.io.println("Well done");
} else {
System.io.println("Too many cycles");
}
return counter;
}
I iterate from "left" to "right" over the array and walking more and more to the "right".
1st, 2nd, 3rd
1st, 2nd, 4th
...
1st, 2nd, nth
2nd, 3rd, 4th
2nd, 3rd, 5th
...
2nd, 3rd, nth
.
.
.
nth - 2, nth - 1, nth
I iterated 35 times, but could iterate 7^2 = 49 times --> "Well done"
You missed one loop. The fixed code:
public static int tripletSum(int[] arr, int num) {
//Your code goes here
mergeSort(arr, 0, arr.length - 1);
int n = arr.length;
int count = 0;
for (int i = 0; i < n - 2; i++) {
int sum = num - arr[i];
for (int j = i+1; j < n-1; j++) {
int k = n-1;
while (j < k) {
if (arr[j] + arr[k] == sum) {
count++;
k--;
} else if (arr[j] + arr[k] > sum) {
k--;
} else {
j++;
}
}
}
}
return count;
}
OK, then optimized version:
public static int tripletSum(int[] arr, int num) {
//Your code goes here
mergeSort(arr, 0, arr.length - 1);
int n = arr.length;
int count = 0;
for (int i = 0; i < n - 2; i++) {
int sum = num - arr[i];
int maxK = n - 1;
for (int j = i + 1; j < n - 1; j++) {
int k = maxK;
while (j < k) {
if (arr[j] + arr[k] == sum) {
count++;
k--;
} else if (arr[j] + arr[k] > sum) {
k--;
maxK--;
} else {
j++;
}
}
}
}
return count;
}
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
For CS homework assignment I am to create random arrays of increasing size in java and plot their runtime on a graph. However, my implementations of Insert, Merge, and Quick sort seem to have the same run times when run with the same input. I've implemented them differently many times and am still getting the same results. Here is my code:
import java.util.*; import java.util.Random;
public class Complexity {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input= new Scanner(System.in);
System.out.println("Enter the array size: ");
int a = input.nextInt();
System.out.println("Enter the number size: ");
int n = input.nextInt();
int[] arr = newArr(a, n);
int[] arr2 = arr.clone();
int[] arr3 = arr.clone();
//INSERT SORT
long startTime = System.nanoTime();
insertSort(arr);
long endTime = System.nanoTime();
long duration = (endTime - startTime)/1000000;
System.out.println("Insert Sort Time:" + duration + "ms");
//MERGE SORT
long start = System.nanoTime();
mergeSort(arr2, 0, a-1);
long end = System.nanoTime();
long dur = (end - start)/1000000;
System.out.println("Merge Sort Time:" + duration + "ms");
//QUICK SORT
long s = System.nanoTime();
quickSort(arr3, 0, a-1);
long e = System.nanoTime();
long d = (e - s);
System.out.println("Quick Sort Time:" + duration + "ms");
}
public static int[] newArr(int a, int n) {
Random rand = new Random();
int newArray[] = new int[a];
for (int i = 0; i < a; i++) {
int number= rand.nextInt(n);
newArray[i]=number;
}
return newArray;
}
public static void quickSort(int[] arr, int low, int high) {
if(low<high) {
int pivotIndex = findPivot(arr, low, high);
quickSort(arr, low, pivotIndex-1);
quickSort(arr, pivotIndex+1, high);
}
}
public static int findPivot(int[] arr, int low, int high) {
int pivot = arr[high];
int nextSmallest = (low-1);
for(int currentIndex = low; currentIndex < high; currentIndex++) {
if(arr[currentIndex] <= pivot) {
nextSmallest++;
int temp = arr[nextSmallest];
arr[nextSmallest] = arr[currentIndex];
arr[currentIndex] = temp;
}
}
int temp = arr[nextSmallest+1];
arr[nextSmallest+1] = arr[high];
arr[high] = temp;
return nextSmallest+1;
}
public static void mergeSort(int[] arr, int left, int right){
if(left<right) {
int middle = (left + right) / 2;
mergeSort(arr, left, middle);
mergeSort(arr, middle+1, right);
merge(arr, left, middle, right);
}
}
public static void merge(int[] arr, int left, int middle, int right){
int leftLength = middle - left + 1;
int rightLength = right - middle;
int newL[] = new int [leftLength];
int newR[] = new int [rightLength];
for (int i=0; i<leftLength; ++i)
newL[i] = arr[left + i];
for (int j=0; j<rightLength; ++j)
newR[j] = arr[middle + 1+ j];
int i = 0, j = 0;
int k = left;
while (i < leftLength && j < rightLength) {
if (newL[i] <= newR[j]) {
arr[k] = newL[i];
i++;
}
else {
arr[k] = newR[j];
j++;
}
k++;
}
while (i < leftLength) {
arr[k] = newL[i];
i++;
k++;
}
while (j < rightLength) {
arr[k] = newR[j];
j++;
k++;
}
}
static void printArray(int arr[], String methodName) {
System.out.print(methodName);
int n = arr.length;
for (int i=0; i<n; ++i)
System.out.print(arr[i] + " ");
System.out.println();
}
public static void insertSort(int[] arr){
int temp;
for(int i = 0; i < arr.length; i++) {
for(int j = i ; j > 0 ; j--){
if(arr[j] < arr[j-1]){
temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
}
}
}
}
}
Each of your print statements prints the duration from insertion sort instead of dur and d.
I'm trying to create a non-recursive version of MergeSort but for some reason merge is keeping the code from running in its entirety.
Mergesort Code:
public void mergeSort(int[] input)
{
int n = input.length;
int size;
int l;
for (size = 1; size <= n-1; size = 2*size)
{
for (l = 0; l < n-1; l += 2*size)
{
int m = l + size -1;
int r = minimum(l + 2*size - 1, n-1);
merge(input, l, m, r);
}
}
}
Merge code:
public static void merge(int[] numbers, int low, int middle, int high)
{
// Copy both parts into the helper array
int helper[];
helper = new int[numbers.length];
for (int i = low; i <= high; i++) {
helper[i] = numbers[i];
}
int i = low;
int j = middle + 1;
int k = low;
// Copy the smallest values from either the left or the right side back
// to the original array
while (i <= middle && j <= high) {
if (helper[i] <= helper[j]) {
numbers[k] = helper[i];
i++;
} else {
numbers[k] = helper[j];
j++;
}
k++;
}
// Copy the rest of the left side of the array into the target array
while (i <= middle) {
numbers[k] = helper[i];
k++;
i++;
}
}
This is how I fill up the input array (which is of size 100):
public static int fillArray()
{
Random r = new Random();
int rand = r.nextInt();
return rand;
}
//followed by these lines of code in the main method:
int[] arr;
arr = new int[100];
for(int i =0; i<arr.length; i++)
{
arr[i] = fillArray();
}
The exception is with numbers[k] = helper[i] in merge().
I know that the contents of the input array are fine because I print out the contents of the array before I perform MergeSort on it. Does anyone know what the problem is?
Fix the m in mergeSort() like this:
int m = Math.min(l + size - 1, n - 1);
You didn't mention what exception you get but I assume its array out of bounds. What prevents your middle variable from exceeding the size of the array?
while (i <= middle) {
numbers[k] = helper[i];
k++;
i++;
}
Put in debugging prints etc.
Question: Where are comparisons being made in each separate sorting method?
Also if you know please tell me which method count numbers are wrong and where to place my counters instead.trying to understand where and how many times sorting methods make comparisons.
Method A B
Selection 4950 4950
Bubble 99 9900
Insertion 99 5049
Merge 712 1028
Shell 413 649
Quick 543 1041
Okay so to explain some parts, basically Array A is an array from 1-100 in ascending order. So this should be the minimum number of comparisons.
Array B is 100-1 in descending order. So I believe it should be the maximum number of comparisons. Array C is just randomly generated numbers, so it changes every time.
I feel like my selection and bubble sorts were counted correctly. Feel free to let me know where comparisons are being made that I haven't counted, or if I'm counting wrong comparisons.
Side note: Made some global variable to count the methods that were recursive in multiple sections.
class Sorting
{
static int[] X = new int[100];
static int mergecount = 0;
static int quickcount = 0;
public static void selectionSort(int list[])
{
int count = 0;
int position = 0, n = list.length;
for(int j = 0; j < n-1; j++)
{
position = j;
for(int k = j+1; k < n; k++)
{
count++;
if(list[k] < list[position])
position = k;
}
Swap(list, j, position);
}
System.out.println("counter" + count);
}
public static void Swap(int list[], int j, int k)
{
int temp = list[j];
list[j] = list[k];
list[k] = temp;
}
public static void bubbleSort(int list[])
{
int count = 0;
boolean changed = false;
do
{
changed = false;
for(int j = 0; j < list.length - 1; j++)
{
count++;
if(list[j] > list[j + 1])
{
Swap(list, j, j+1);
changed = true;
}
}
} while(changed);
System.out.println("counter" + count);
}
public static void insertionSort(int list[])
{
int count = 0;
for(int p = 1; p < list.length; p++)
{
int temp = list[p];
int j = p;
count++;
for( ; j > 0 && temp < list[j - 1]; j = j-1)
{
list[j] = list[j - 1];
count++;
}
list[j] = temp;
}
System.out.println("counter" + count);
}
public static void mergeSort(int list[])
{
mergeSort(list, 0, list.length - 1);
System.out.println("counter" + mergecount);
}
public static void mergeSort(int list[], int first, int last)
{
if(first < last)
{
int mid = (first + last) / 2;
mergeSort(list, first, mid);
mergeSort(list, mid + 1, last);
Merge(list, first, mid, last);
}
}
public static void Merge(int list[], int first, int mid, int last)
{
int count = 0;
int first1 = first, last1 = mid;
int first2 = mid + 1, last2 = last;
int temp[] = new int[list.length];
int index = first1;
while(first1 <= last1 && first2 <= last2)
{
if(list[first1] < list[first2])
{
temp[index] = list[first1++];
mergecount++;
}
else
temp[index] = list[first2++];
index++;
mergecount++;
}
while(first1 <= last1)
temp[index++] = list[first1++];
while(first2 <= last2)
temp[index++] = list[first2++];
for(index = first; index <= last; index++)
list[index] = temp[index];
}
public static void shellSort(int list[])
{
int count = 0;
int n = list.length;
for(int gap = n / 2; gap > 0; gap = gap == 2 ? 1: (int) (gap/2.2))
for(int i = gap; i < n; i++)
{
int temp = list[i];
int j = i;
count++;
for( ; j >= gap && (temp < (list[j - gap])); j -= gap)
{
list[j] = list[j - gap];
count++;
}
list[j] = temp;
}
System.out.println("counter" + count);
}
public static void quickSort(int start, int finish, int list[])
{
int count = 0;
int left = start, right = finish, pivot, temp;
pivot = list[(start + finish) / 2];
do
{
while(list[left] < pivot)
{
left++;
quickcount++;
}
while(pivot < list[right])
{
right--;
quickcount++;
}
if(left <= right)
{
temp = list[left];
list[left++] = list[right];
list[right--] = temp;
quickcount++;
}
} while(left < right);
if(start < right)
quickSort(start, right, list);
if(left < finish)
quickSort(left, finish, list);
}
public static void copy(int list[])
{
for(int i = 0; i < list.length; i++)
X[i] = list[i];
}
public static void restore(int list[])
{
for(int i = 0; i < list.length; i++)
list[i] = X[i];
}
public static void displayArray(int list[])
{
for(int k = 0; k < list.length; k++)
System.out.print(list[k] + " ");
System.out.println();
}
public static void main(String args[])
{
int[] A = new int[100];
for(int i = 0; i < A.length; i++)
A[i] = i + 1;
int[] B = new int[100];
int q = 100;
for(int i = 0; i < B.length; i++)
B[i] = q--;
int[] C = new int[100];
for(int i = 0; i < C.length; i++)
C[i] = (int)(Math.random() * 100 + 1);
displayArray(A);
copy(A);
selectionSort(A);
displayArray(A);
restore(A);
}
Note that QuickSort performance is greatly influenced by your choice of the pivot. With both of your test arrays sorted (ascending / descending) and because you are picking pivot as array[length/2] you are actually always picking the best pivot. So your test case B won't generate maximum number of comparisons for quicksort. If you were picking array[0] as pivot you'd get maximum number of comparisons for test case A and B.
The easiest way to count comparisons is to use a compare function and do it in there.
static int compareCount = 0;
int compareInt(int a, int b) {
compareCount++;
return a - b; // if 0 they are equal, if negative a is smaller, if positive b is smaller
}
Now just use compareInt in all your algorithms and you'll get an accurate count. You'll have to reset compareCount between each run though.
I need to sort an array of integer arrays for a homework problem in one of my classes. I seem to get a StackOverFlowError almost every time. My array is list2[10][10]. My quick sort is separated into 3 methods. quickSort1(int, int) is the main function, partition compares a new partition, and swap simply swaps the integer arrays at list2[i] and list2[j]. the compare(int a, int b) method returns 1 if list2[a] is smaller than list2[b] - 1 if b is smaller than a and 100 if they are equal.
I'm not sure my quick sort is implemented correctly but I know swap and compare work exactly how I say they do. I have a hunch that it mostly recurs forever when I get the StackOverFlowError.
public static int partition(int low, int high)
{
int i = low, j = high;
int pivot = (low+high)/2;
System.out.println(i + " " + j + " " + pivot);
while (i <= j) {
while (compare(i, pivot) > 0)
i++;
while (compare(pivot, j) > 0)
j--;
if (i < j) {
swap(i,j);
i++;
j--;
}
if (i == pivot && i == j-1)
{
return i;
}
if (j == pivot && j-1 == i)
{
return i;
}
}
return i;
}
public static void quickSort1(int low, int high) {
System.out.println("Recursion: " + recursions);
int i = partition(low, high);
System.out.println(i);
if (low < i -1)
{
recursions++;
quickSort1(low, i -1);
}
if (i < high-1)
{
recursions++;
quickSort1(i, high);
}
}
public static void swap( int i, int j)
{
int[] temp = new int[n];
for(int k = 0; k < n; k++) {
temp[k] = list2[i][k];
}
for(int k = 0; k < n; k++) {
list2[i][k] = list2[j][k];
}
for(int k = 0; k < n; k++) {
list2[j][k] = temp[k];
}
}
I don't think these lines are necessary inside the loop while(i <= j):
if (i == pivot && i == j-1)
{
return i;
}
if (j == pivot && j-1 == i)
{
return i;
}
Try removing them from your code.
import java.util.Arrays;
import java.util.Scanner;
public class apples {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter the number of the values");
int num = input.nextInt();
int a[] = new int [num];
System.out.println("Enter the nambers now");
for(int i=0; i<a.length; i++){
a[i] = input.nextInt();
}
Arrays.sort(a);
int min =a[0];
System.out.println("The minmum value is "+min);
int max= a[a.length-1];
System.out.println("The maxemum value is "+max);
int d = max-min;
System.out.println("the difrentc between the max and the min is "+ d);
System.out.println("The Arrays R \t");
for(int g=0; g<=a.length;g++){
int m = a[g];
System.out.println(m);
}
}
}