I want to find a nonempty, contiguous subarray for a given input array of integers, that can have duplicate values. I tried the divide and conquer method to find the maximum consecutive subarray of an array, which returns a different result as expected. Please find the code below.
private static int maxSumRec(int[] a, int low, int high) {
int leftSum = 0, rightSum = 0;
int sum = 0;
if (low == high) { // Base case
return a[low];
}
int mid = (low + high) >> 1; // (low + high) / 2
int maxLeftSum = maxSumRec(a, low, mid);
int maxRightSum = maxSumRec(a, mid + 1, high);
//max-crossing-subarray
for (int i = mid; i >= low; i--) {
sum += a[i];
if (sum > leftSum) {
leftSum = sum;
}
}
sum = 0;
for (int i = mid + 1; i <= high; i++) {
sum += a[i];
if (sum > rightSum) {
rightSum = sum;
}
}
return max3(maxLeftSum, maxRightSum, (leftSum + rightSum));
}
private static int max3(int a, int b, int c) {
return a > b ? (a > c ? a : c) : (b > c ? b : c);
}
public static void main(String[] args) {
//INPUT
int a[] = {
-5, 71, 23, 41, 34, 1, 3, 6, 2, 91, 312, 42, 31, 67, 12, 10, 18, 56, 90, 21, 45, 47, 89, 1999999990,
78, -7, 76, 75, 74, 73, 72, 80, 24, 25, 61, 69, 84, 0, -1, 145, 1902, 200, 199, 198, 197, 196, 195, 194,
78, 77, 76, 75, 74, 73, 72, 80, 24, 25, 61, 69, 84, 0, -1, 145, 1902, 200, 199, 198, 197, 196, 195, 194,
5, 71, 23, 41, 34, 1, 3, 6, 2, 91, 312, 42, 31, 67, 12, 10, 18, 56, 90, 21, 45, 47, 89, 1999999990
};
int maxSum = maxSumRec(a, 0, a.length - 1);
System.out.println("Max sum is " + maxSum);
}
This code returns the result as 2000005400. The non recursive version of MCS returns a different result i.e. 2000010721 and its found from {1-94}.
I'm unable to figure out the reason. Please let me know if there's a bug in the code.
The sum from 1 to 95 (it's :4000010711 ) is actually greater than the one from 1 to 94.
Your ints are too long.
You need to use long to get the right result.
Note:
int are between -2147483648 and 2147483647
int test=2147483647;
System.out.println(test);
System.out.println(test+1);
you will get:
2147483647
-2147483648
Try this :
public class Sample5 {
private static long maxSumRec(int[] a, int low, int high) {
long leftSum = 0, rightSum = 0;
long sum = 0;
if (low == high) { // Base case
return a[low];
}
int mid = (low + high)/2; // (low + high) / 2
long maxLeftSum = maxSumRec(a, low, mid);
long maxRightSum = maxSumRec(a, mid + 1, high);
//max-crossing-subarray
for (int i = mid; i >= low; i--) {
sum += a[i];
if (sum > leftSum) {
leftSum = sum;
}
}
sum = 0;
for (int i = mid + 1; i <= high; i++) {
sum += a[i];
if (sum > rightSum) {
rightSum = sum;
}
}
System.out.println("final left sum "+leftSum);
System.out.println("final right sum "+rightSum);
System.out.println("leftSum+rightSUM:"+(leftSum + rightSum));
return max3(maxLeftSum, maxRightSum, (leftSum + rightSum));
}
private static long max3(long a, long b, long c) {
return a > b ? (a > c ? a : c) : (b > c ? b : c);
}
private static int sum(int[] a,int i,int j){
int r=0;
for(int k=i;k<=j;k++){
r+=a[k];
}
return r;
}
public static void main(String[] args) {
//INPUT
int a[] = {
-5, 71, 23, 41, 34, 1, 3, 6, 2, 91, 312, 42, 31, 67, 12, 10, 18, 56, 90, 21, 45, 47, 89, 1999999990,
78, -7, 76, 75, 74, 73, 72, 80, 24, 25, 61, 69, 84, 0, -1, 145, 1902, 200, 199, 198, 197, 196, 195, 194,
78, 77, 76, 75, 74, 73, 72, 80, 24, 25, 61, 69, 84, 0, -1, 145, 1902, 200, 199, 198, 197, 196, 195, 194,
5, 71, 23, 41, 34, 1, 3, 6, 2, 91, 312, 42, 31, 67, 12, 10, 18, 56, 90, 21, 45, 47, 89, 1999999990
};
long maxSum = maxSumRec(a, 0, a.length-1);
System.out.println("Max sum is " + maxSum);
//WITH INTS
System.out.println("with ints, the sum 1 to 94 is " + sum(a,1,94));
System.out.println("with ints, the sum 1 to 95 is " + sum(a,1,95));
}
}
You will get :
final left sum 2000005311
final right sum 2000005400
leftSum+rightSUM:4000010711
Max sum is 4000010711
with ints, the sum 1 to 94 is 2000010721
with ints, the sum 1 to 95 is -294956585
dont have enough points to add a comment so created an answer for a quick comment:
Ricky's answer works most of the time but for array such as [-2,-1] it won't work. simply add:
leftSum = a[mid];rightSum = a[mid+1];
somewhere before you use them and it'll do the trick.
Related
As the title says, I am looking for a sorting algorithm that can sort the numbers between 1 and 100 using the least amount of statements in only one method which is the main.
Here's an example to give you an idea on how I can check it(using a counter)
class Solution{
public static void main(String[] args) {
//declaration
int count = 0,inner, outer, temp, h = 1; count++;
int [] array = {100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,}; count++;
System.out.println("Before: " + Arrays.toString(array)); count++;
//start of the sort
while (h <= array.length / 3) //start of while loop 1
{
h = h * 3 + 1; count++;
}count++; //end of while loop 1
while (h > 0) //start of while loop 2
{
for (outer = h; outer < array.length; outer++) //start of for loop
{
temp = array[outer]; count++;
inner = outer;count++;
while (inner > h - 1 && array[inner - h] >= temp) //start of while loop 3
{
array[inner] = array[inner - h]; count++;
inner -= h; count++;
}count++; //end of for loop 3
array[inner] = temp; count++;
}count++; //end of for loop
//equation to count for
count = count + array.length-h+1 + array.length - h +1 -1;
h = (h - 1) / 3; count++;
}count++; //end of while loop 2
System.out.println("After: " + Arrays.toString(array) + "\n" + "Counter = " + count);
}
}
The fastest algorithm with example would be quicksort, also as you are asking i believe this would also take the least amount of statments. Below you can find a link and also description of how it works.
https://www.geeksforgeeks.org/quick-sort/
I am new to programming and cannot seem to figure out my errors when trying to write a Quicksort program. I have most of the implementation done with the exception of a few errors that I cannot seem to figure out. Here is my current code:
public class Quicksort {
public static void main(String[] args) {
Integer[] numbers = new Integer[20];
for (int i = 0; i < numbers.length; i++) {
numbers[i] = (int) (Math.random() * 100);
}
printArray(numbers);
quicksort(numbers);
printArray(numbers);
}
public static <T> void printArray(T[] array) {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + (i < array.length - 1 ? ", " : "\n"));
}
}
public static <T> void printArrayPartition(T[] array, int low, int high, int pivot) {
for (int i = 0; i < array.length; i++) {
String element = "" + array[i];
if (i == pivot)
element = "*" + element + "*";
if (i == low)
element = "[" + element;
if (i == high)
element += "]";
System.out.print(element + (i < array.length - 1 ? ", " : "\n"));
}
}
public static <T extends Comparable<T>> void quicksort(T[] array) {
quicksort(array, 0, array.length - 1);
}
private static <T extends Comparable<T>> void quicksort(T[] array, int low, int high) {
if (low < high) {
int pivotIndex = partition(array, low, high);
int pivot = pivotIndex;
printArrayPartition(array, low, high, pivot);
quicksort(array, low - 1, pivotIndex - 1);
quicksort(array, pivotIndex + 1, high + 1);
}
}
private static <T extends Comparable<T>> int partition(T[] array, int low, int high) {
T pivotValue = array[high];
int left = low;
for (int i = 0; i < array.length; i++) {
if (array[i].compareTo(pivotValue) > 0) {
left++;
}
}
swap(array, high, left);
return left;
}
private static <T> void swap(T[] array, int a, int b) {
T temp = array[a];
array[a] = array[b];
array[b] = temp;
}
}
When running this program I am getting ArrayIndexOutOfBounds error and I'm not sure why. I have traced few my code a few times and still cannot seem to figure it out.
Stack trace:
54, 91, 26, 43, 98, 65, 88, 78, 88, 60, 58, 75, 74, 46, 79, 81, 64, 49, 67, 31
[54, 91, 26, 43, 98, 65, 88, 78, 88, 60, 58, 75, 74, 46, 79, 81, 64, 49, *31*, 67]
54, 91, 26, 43, 98, 65, 88, 78, 88, 60, 58, 75, 74, 46, *49*, 81, 64, 79], 31, 67
54, 91, 26, 43, 98, 65, 88, 78, 88, 60, 58, 75, 74, 49], *46*, 81, 64, 79, 31, 67
54, 91, 26, 43, 98, 65, 88, 78, 88, 60, 58, 75, *49*, 74], 46, 81, 64, 79, 31, 67
54, 91, 26, *75*, 98, 65, 88, 78, 88, 60, 58, 43], 49, 74, 46, 81, 64, 79, 31, 67
54, 91, 46], 75, 98, 65, 88, 78, 88, 60, 58, 43, 49, 74, *26*, 81, 64, 79, 31, 67
54, 91, *74*, 75, 98, 65, 88, 78, 88, 60, 58, 43, 49, 46], 26, 81, 64, 79, 31, 67
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -6
at Quicksort.swap(Quicksort.java:79)
at Quicksort.partition(Quicksort.java:72)
at Quicksort.quicksort(Quicksort.java:47)
at Quicksort.quicksort(Quicksort.java:52)
at Quicksort.quicksort(Quicksort.java:52)
at Quicksort.quicksort(Quicksort.java:52)
at Quicksort.quicksort(Quicksort.java:52)
at Quicksort.quicksort(Quicksort.java:52)
at Quicksort.quicksort(Quicksort.java:52)
at Quicksort.quicksort(Quicksort.java:52)
at Quicksort.quicksort(Quicksort.java:41)
at Quicksort.main(Quicksort.java:13)
In your recursive calls:
quicksort(array, low - 1, pivotIndex - 1);
quicksort(array, pivotIndex + 1, high + 1);
You subtract one from low and pivotIndex and then later pass those values to
swap(array, high, left); //via int left = low;
Which in turn calls the index of high and low. When you start the method low is set to zero. And then you subtract one to get a negative number. If the condition: if (array[i].compareTo(pivotValue) > 0) is never met then left will never be increased and you will be passing a negative number to swap(…). And in the swap() method:
T temp = array[a]; //a is left here
array[a] = array[b];
array[b] = temp;
You directly try to call the index of left which might be a negative number, thus the indexoutofboundsexception with a negative index
And in the same fashion the quicksort(array, pivotIndex + 1, high + 1); can add one to high and thus cause it to go out of bounds
So I've been working on this code for quite a while, and I feel I am almost done. However, I keep running into the Stack overflow error over and over and I can't seem to fix it. I want to be able to print out the recursive code after the standard code, but I seem to get the error sometime in the mergesort method. I can't figure out what is causing the error even after looking up recursion and stack overflow. I need help. This is a recursive merge method.
import java.util.*;
import java.lang.*;
import java.io.*;
public class merge_recursive {
public void mergeSort(ArrayList <Comparable> a, int first, int last){
int mid;
int temp;
if (first == last){
}
else{
if (first +1 == last){
//list of 2 values, swap if needed
if(a.get(first).compareTo(a.get(last)) > 0){
swap(a, first, last);
}
}
else {
//general case
mid = (first + last) / 2;
mergeSort(a, first, mid);
mergeSort(a, mid +1, last);
merge(a, first, mid, last);
}
}
}
private void merge(ArrayList <Comparable> a, int first, int mid, int last)
{
int aPtr = first;
int bPtr = mid + 1;
int cPtr = first;
int total = last - first + 1;
int loop;
boolean doneA = false;
boolean doneB = false;
ArrayList <Comparable> c = new ArrayList <Comparable>(a);
for (loop = 1; loop <= total; loop++){
if (doneA){
c.set(cPtr, a.get(bPtr));
bPtr++;
} else if (doneB){
c.set(cPtr, a.get(aPtr));
aPtr++;
} else if (a.get(aPtr).compareTo(a.get(bPtr)) < 0){
// ok to compare, valid data in each sublist
c.set(cPtr, a.get(aPtr));
aPtr++;
} else {
c.set(cPtr, a.get(bPtr));
bPtr++;
}
cPtr++;
if (aPtr > mid){
doneA = true;
}
if (bPtr > last){
doneB = true;
}
}
ArrayList<Comparable> d = new ArrayList <Comparable>();
for (int i = 0; i < c.size()/2; i++){
d.add(i,c.get(c.size()-1));
}
System.out.println("Sorted list: " + d);
}
public ArrayList <Comparable> fillArray(){//sortstep
Scanner console = new Scanner(System.in);
System.out.println();
System.out.print("How many numbers do you wish to generate? ");
int numInts = console.nextInt();
ArrayList <Comparable> temp = new ArrayList<Comparable>();
System.out.print("Largest integer to generate? ");
int largestInt = console.nextInt();
Random randGen = new Random();
for (int loop = 0; loop < numInts; loop++){
temp.add(randGen.nextInt(largestInt) + 1);
}
return temp;
}
public void swap(ArrayList <Comparable> list, int a, int b){
Comparable c = list.get(a);
list.set(a, list.get(b));
list.set(b, c);
}
}
// End of Recursive merge //
import java.util.ArrayList;
public class merge_recursive_Driver {
public static void main(String[] args){
merge_recursive s = new merge_recursive();
ArrayList standard = s.fillArray();
System.out.println("Standard: " + standard);
int first = (int) standard.get(0);
int last = (int) standard.get(standard.size() -1);
s.mergeSort(standard, first, last);
}
}
// End of Driver //
Output:
How many numbers do you wish to generate? 100
Largest integer to generate? 100
Standard: [81, 4, 23, 2, 88, 70, 64, 74, 1, 16, 16, 11, 24, 88, 28, 89,
52, 5, 86, 73, 89, 95, 69, 15, 58, 34, 80, 63, 96, 11, 63, 92, 95, 71,
87, 76, 94, 87, 27, 23, 69, 47, 87, 55, 14, 90, 9, 61, 13, 39, 56, 55,
19, 20, 85, 93, 6, 8, 90, 9, 26, 99, 41, 11, 60, 22, 30, 46, 52, 20, 1,
23, 2, 37, 10, 19, 89, 16, 43, 12, 47, 52, 28, 13, 10, 41, 46, 91, 49,
62, 66, 17, 87, 69, 47, 58, 45, 38, 83, 31]
Exception in thread "main" java.lang.StackOverflowError
at merge_recursive.mergeSort(merge_recursive.java:11)
at merge_recursive.mergeSort(merge_recursive.java:24)
at merge_recursive.mergeSort(merge_recursive.java:24)
at merge_recursive.mergeSort(merge_recursive.java:24)
at merge_recursive.mergeSort(merge_recursive.java:24)
at merge_recursive.mergeSort(merge_recursive.java:24)
and so on and so on.
"first" and "last" are array indexes, not array values. Replace:
int first = (int) standard.get(0);
int last = (int) standard.get(standard.size() -1);
with
int first = 0;
int last = standard.size() -1;
this is my quick sort code on Java. I've tried this code for 3 different types of lists;
Random list
Sorted List
Reversed sorted list
It's working for only sorted list, but for sorted list it prints;
1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 66, 68, 64, 69, 62, 70, 60, 71, 58, 72, 56, 73, 54, 74, 52, 75, 50, 76, 48, 77, 46, 78, 44, 79, 42, 80, 40, 81, 38, 82, 36, 83, 34, 84, 32, 85, 30, 86, 28, 87, 26, 88, 24, 89, 22, 90, 20, 91, 18, 92, 16, 93, 14, 94, 12, 95, 10, 96, 8, 97, 6, 98, 4, 99, 2, 100
For the random list it changes.
I couldn't solve that problem, can anyone help?
Thanks in advance.
class QuickSort {
public int Partition(int[] numbers, int left, int right){
int pivot = numbers[left];
while (true)
{
while (numbers[left] < pivot)
left++;
while (numbers[right] > pivot)
right--;
if (left < right)
{
int temp = numbers[right];
numbers[right] = numbers[left];
numbers[left] = temp;
left++;
right--;
}
else
{
return right;
}
}
}
public void QuickSort(int[] arr, int left, int right){
// For Recusrion
if(left < right)
{
int pivot = Partition(arr, left, right);
if(pivot > 1)
QuickSort(arr, left, pivot - 1);
if(pivot + 1 < right)
QuickSort(arr, pivot + 1, right);
}
}
////////////////////////////////////////////////////////////
public void printArray(int[] arr){
for (int i = 0; i < arr.length; i++){
if (i==arr.length-1)
System.out.print(arr[i]);
else
System.out.print(arr[i]+", ");
}
System.out.println();
}
public int[] fillArraySorted(int len){
int[] result=new int[len];
int counter = 1;
for(int i=0; i<len; i++){
result[i]=counter;
counter++;
}
return result;
}
public int[] fillArrayRan(int len){
int[] result=new int[len];
Random r = new Random();
for(int i=0; i<len; i++){
result[i]=r.nextInt(100)+1;
}
return result;
}
public int[] fillArraySortedReversed(int len){
int[] result=new int[len];
int counter = len;
for(int i=0; i<len; i++){
result[i]=counter;
counter--;
}
return result;
}
}
}
So I am going through some of the common sorting algorithms and have written this:
Code:
public void insertionSort() {
int key;
int i;
for ( int j = 1; j < this.a.length; j++ ) {
key = a[j];
i = j;
while ( i > 0 && a[i-1] > key ) {
a[i] = a[i-1];
i = i - 1;
}
a[i] = key;
}
}
Result:
jan#janspc:~/Dropbox/programming/java/algorithms$ javac sort.java
jan#janspc:~/Dropbox/programming/java/algorithms$ java Test
49, 68, 60, 14, 70, 8, 83, 96, 29, 7, 92, 35, 17, 84, 31, 62, 48, 95, 16, 22, 31, 97, 72, 55, 88, 63, 1, 63, 96, 32, 74, 15, 92, 77, 50, 13, 12, 36, 90, 93, 20, 15, 67, 88, 23, 31, 95, 90, 86, 65, 35, 27, 60, 4, 90, 11, 22, 97, 65, 88, 23, 1, 25, 21, 9, 81, 87, 56, 2, 4, 63, 52, 55, 86, 62, 30, 55, 64, 19, 10, 45, 92, 87, 43, 39, 95, 20, 43, 3, 30, 74, 64, 4, 90, 91, 93, 94, 44, 87, 21,
49, 1, 1, 2, 3, 4, 4, 4, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 16, 17, 19, 20, 20, 21, 21, 22, 22, 23, 23, 25, 27, 29, 30, 30, 31, 31, 31, 32, 35, 35, 36, 39, 43, 43, 44, 45, 48, 50, 52, 55, 55, 55, 56, 60, 60, 62, 62, 63, 63, 63, 64, 64, 65, 65, 67, 68, 70, 72, 74, 74, 77, 81, 83, 84, 86, 86, 87, 87, 87, 88, 88, 88, 90, 90, 90, 90, 91, 92, 92, 92, 93, 93, 94, 95, 95, 95, 96, 96, 97, 97,
Execution took: 110628 nano sek?
As you can see from testing, the first value is not affected by sort. What's wrong with my algorithm?
In the first iteration, the while loop doesn't execute, because i < 0. In the next iteration, the while loop doesn't run because i == 0.
You should probably use while (i >= 0 && a[i] > key) (not tested though)
You need >= here:
while ( i >= 0 && a[i] > key ){
Without this change it never compares the following elements against the first one.
while ( i > 0 && a[i] > key ){ should be while ( i >= 0 && a[i] > key ){
Best luck...
In Insertion Sort we need to check each and every element from array and compare with other element getting more accurate result. The problem in your code in while loop
we need line
while ( i >= 0 && a[i] > key )
Here is another implementation of insertion sort in java
public class InsertionSort {
static int intArray[] = { 1000, 1, 100, 101, 15 };
public static void doSort() {
for (int outer = 1; outer < intArray.length; outer++) {
for(int inner=outer;inner>0; inner--){
if(intArray[inner]<intArray[inner-1]){
int temp=intArray[inner];
intArray[inner]=intArray[inner-1];
intArray[inner-1]=temp;
continue;
}
}
}
}
public static void printArray() {
for (int i = 0; i < intArray.length; i++) {
System.out.print(" " + intArray[i]);
}
}
public static void main(String args[]) {
System.out.print("Array Before Sorting->");
printArray();
doSort();
System.out.print("\nArray After Sorting ->");
printArray();
}
}
Detailed explanation of the code and/or the algortithm can be seen at -
http://www.javabrahman.com/algorithms-in-java/insertion-sort-in-java/
here is a very easy implementation of insertion sort
package insertion_sort;
public class insertion_sort {
public static void main(String ar[]) {
int[] a = {24, 13, 9, 64, 7, 23, 34, 47, 87, 9, 37, 1992};
insertion(a,12);
}
public static void insertion(int[] a, int n) {
for (int i = 1; i <= n - 1; i++) {
int value = a[i];
int hole = i;
while (hole > 0 && a[hole - 1] > value) {
a[hole] = a[hole - 1];
hole = hole - 1;
}
a[hole] = value;
}
print(a);
}
public static void print(int[] A) {
for (int i = 0; i < A.length; i++) {
System.out.print(A[i] + " ");
}
System.out.println();
}
}
Below is the pseudo code of Insertion sort(taken from CLR "Introduction to algorithms" book).
Insertion-Sort(A)
for (j=2 to A.length)
key = A[j]>
i = j-1
while i>0 && A[i]>key
A[i+1] = A[i]
i = i-1
A[i+1] = key
Your code is almost similar to above pseudo code. All you need is to change initialization of int j=0 to int j=1 in for loop:
for ( int j = 1; j < this.a.length; j++ ) {
key = a[j];
i = j - 1;
while ( i > 0 && a[i] > key ) {
a[i + 1] = a[i];
i = i - 1;
}
a[i+1] = key;
}
Corrected code:
public void insertionSort() {
int key;
int i;
for ( int j = 1; j < this.a.length; j++ ) {
key = a[j];
i = j;
while ( i > 0 && a[i-1] > key ) {
a[i] = a[i-1];
i = i - 1;
}
a[i] = key;
}
}
public static int[] insrtSort(int array[]){
for(int i=0 ; i<array.length-1;i++){
int value=array[i+1],k=i;
while(value<array[k] ){
array[k+1]=array[k];
if(k!=0)
k--;
else
array[0]=value;
}
if(k!=0)
array[k+1]=value;
}
return array;
}
This is the same code but as a method that can be passed an array of ints to sort.
public static int[] insertionSort(int[] array) {
int key;
int i;
for ( int j = 1; j < array.length; j++ ) {
key = array[j];
i = j;
while ( i > 0 && array[i-1] < key ) {
array[i] = array[i-1];
i = i - 1;
}
array[i] = key;
}
return array;
}