My condition is not outputting the right numbers, the list is not changed trough the loop, this is my condition.
if (j + 1 <= length)
{
insertionSort(arrayIn, indexIn + 1);
}
}
The condition for the recursive call:
if (j + 1 <= length)
is wrong.
You should make the recursive call as long as indexIn is smaller than the last index of the array:
if (indexIn < length - 1) {
insertionSort(arrayIn, indexIn + 1);
}
The rest of your code is fine.
You could try this:
public static void insertionSort(int arrayIn[], int indexIn) {
if (indexIn <= 1)
return;
insertionSort(arrayIn, indexIn - 1);
int last = arrayIn[indexIn - 1];
int j = indexIn - 2;
while (j >= 0 && arrayIn[j] > last) {
arrayIn[j + 1] = arrayIn[j];
j--;
}
arrayIn[j + 1] = last;
}
public static void main(String[] args){
int[] array = {1, 3, 2, 4};
insertionSort(array, array.length);
for (int i = 0; i < array.length; i++){
System.out.print(array[i] + " ");
}
}
I could a ArrayIndexOutOfBound operation, in your code,
Instead of,
if (j + 1 <= length)
{
insertionSort(arrayIn, indexIn + 1);
}
Use this,
if (j + 1 < length)
{
insertionSort(arrayIn, indexIn + 1);
}
And you have print your content of your array too,
public static void main(String[] args) {
int[] arr = new int[]{2, 3, 4, 1, 5};
insertionSort(arr, 0);
for(int i : arr)
{
System.out.print(i + " ");
}
}
Output:
1 2 3 4 5
Related
I'm studying the 3 Sum to implement it on my own, and came across the following implementation with the rules:
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note: Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4},
A solution set is:
(-1, 0, 1)
(-1, -1, 2)
And implementation (sorts the array, iterates through the list, and uses another two pointers to approach the target):
import java.util.*;
public class ThreeSum {
List<List<Integer>> threeSum(int[] num) {
Arrays.sort(num);
List<List<Integer>> res = new LinkedList<>();
for (int i=0; i<num.length-2; i++) {
if (i==0 || (i>0 && num[i] != num[i-1])) { //HERE
int lo = i+1;
int hi = num.length-1;
int sum = 0 - num[i];
while (lo < hi) {
if (num[lo] + num[hi] == sum) {
res.add(Arrays.asList(num[i], num[lo], num[hi]));
while (lo < hi && num[lo] == num[lo+1]) lo++; //HERE
while (lo < hi && num[hi] == num[hi-1]) hi--; //HERE
lo++; hi--;
} else if (num[lo] + num[hi] < sum) lo++;
else hi--;
}
}
}
return res;
}
//Driver
public static void main(String args[]) {
ThreeSum ts = new ThreeSum();
int[] sum = {-1, 0, 1, 2, -1, -4};
System.out.println(ts.threeSum(sum));
}
}
And my question is (located where commented: //HERE), what's the reason for checking num[i] != num[i-1], num[lo] == num[lo+1], and num[hi] == num[hi-1]? Supposedly they are supposed to skip the same result, but what does that mean? Examples would really help.
Thank you in advance and will accept answer/up vote.
Imagine you have {-1,-1,0,1,2,4} and considering triplet num[0], num[2], num[3] (-1,0,1).
lo=0 here. To exclude triplet num[1], num[2], num[3] with the same values, we should increment lo and pass over duplicate
This will prevent the list to have duplicate triplet.
For example, with you test :
int[] sum = {-1, 0, 1, 2, -1, -4};
will be sorted like :
sum = {-4, -1, -1, 0, 1, 2};
You see that you have -1 twice. Without these test, you would test twice if -1 = 0 + 1. This is not usefull so the algo simply search the next different value.
You could remove duplicate in the sorted List to prevent these test.
Thanks to MBo, we can't remove duplicate since we can have triplet with same value (but with different index)
All the three sentences is used to avoid the duplicate output.
Consider a sorted list {-2, -2 , 1, 1}
If there is no checking for num[i] != num[i-1], the output of the program would be(-2, 1, 1)and(-2, 1, 1), which are two duplicate triplets.
The checking for num[lo] != num[lo + 1]and num[hi] != num[hi - 1] are for the same reason.
Consider a sorted list
{-2,-1,-1,0,3}
If there is no checking for num[lo], you will get (-2,-1,3) and (-2,-1,3) as the output.
Still, I want to recommend a better solution for this problem. You can numerate the sum of two numbers in the list and find the 3rd number by hash or binary search. It will helps you to gain a O(n^2logn) time complexity rather than O(n^3). (I was wrong, the time complexity of this algorithm is O(n^2), sorry for that.)
Following program finds pairs of three integer with O(N*2)
Sort the input Array
and iterate each element in for loop and check for sum in program which is developed for Two sum.
Two sum in linear time after sorting ->
https://stackoverflow.com/a/49650614/4723446
public class ThreeSum {
private static int countThreeSum(int[] numbers) {
int count = 0;
for (int i = 0; i < numbers.length; i++) {
int front = 0, rear = numbers.length - 1;
while (front < rear) {
if (numbers[front] + numbers[rear] + numbers[i] == 0) {
System.out.printf(String.format("Front : {%d} Rear : {%d} I : {%d} \n", numbers[front],
numbers[rear], numbers[i]));
front++;
rear--;
count++;
} else {
if (Math.abs(numbers[front]) > Math.abs(numbers[rear])) {
front++;
} else {
rear--;
}
}
}
}
return count;
}
public static void main(String[] args) {
int[] numbers = { 1, 3, 5, 7, 12, 16, 19, 15, 11, 8, -1, -3, -7, -8, -11, -17, -15 };
Arrays.sort(numbers);
System.out.println(countThreeSum(numbers));
}
}
It's worked with any NSum (3Sum, 4Sum, 5Sum, ...) and quite fast.
public class ThreeSum {
private static final int RANDOM_RANGE = 20;
private Integer array[];
private Integer arrayIndex[];
private int result[];
private int bagLength;
private int resultIndex = 0;
private void generateData(int size) {
array = new Integer[size];
Random random = new Random();
for (int i = 0; i < size; i++) {
array[i] = random.nextInt(RANDOM_RANGE) - (RANDOM_RANGE/2);
}
}
private void markArrayIndex(int size) {
arrayIndex = new Integer[size];
for (int i = 0; i < size; i++) {
arrayIndex[i] = i;
}
}
private void prepareBeforeCalculate(int size, int sumExpected, int bagLength) {
this.bagLength = bagLength;
result = new int[bagLength];
generateData(size);
markArrayIndex(size);
}
void calculate(int size, int sumExpected, int bagLength) {
prepareBeforeCalculate(size, sumExpected, bagLength);
Arrays.sort(arrayIndex, (l, r) -> array[l].compareTo(array[r]));
System.out.println(Arrays.toString(array));
long startAt = System.currentTimeMillis();
if (sumExpected > 0) findLeft(sumExpected, 0, 0, array.length);
else findRight(sumExpected, 0, 0 - 1, array.length - 1);
System.out.println("Calculating in " + ((System.currentTimeMillis() - startAt) / 1000));
}
private void findLeft(int total, int indexBag, int left, int right) {
while (left < array.length && array[arrayIndex[left]] < 0 && indexBag < bagLength) {
navigating(total, arrayIndex[left], indexBag, left, right);
left++;
}
}
private void findRight(int total, int indexBag, int left, int right) {
while (right >= 0 && array[arrayIndex[right]] >= 0 && indexBag < bagLength) {
navigating(total, arrayIndex[right], indexBag, left, right);
right--;
}
}
private void navigating(int total, int index, int indexBag, int left, int right) {
result[indexBag] = index;
total += array[index];
if (total == 0 && indexBag == bagLength - 1) {
System.out.println(String.format("R[%d] %s", resultIndex++, toResultString()));
return;
}
if (total > 0) findLeft(total, indexBag + 1, left + 1, right);
else findRight(total, indexBag + 1, left, right - 1);
}
private String toResultString() {
int [] copyResult = Arrays.copyOf(result, result.length);
Arrays.sort(copyResult);
int iMax = copyResult.length - 1;
StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {
b.append(array[copyResult[i]]);
if (i == iMax)
return b.append(']').toString();
b.append(", ");
}
}
}
public class ThreeSumTest {
#Test
public void test() {
ThreeSum test = new ThreeSum();
test.calculate(100, 0, 3);
Assert.assertTrue(true);
}
}
Im trying to solve a google foobar challenge but I am stuck on how to change this to use recursion. any pointers would be helpful
public static int[] answer(int[] l, int t) {
// convert the array into a list
List<Integer> list = new ArrayList<>();
for (int i : l) {
list.add(i);
}
for (int i = 0; i < list.size(); i++) {
Integer n = list.get(i);
if (i >= 1) {
Integer nMinus1 = list.get(i - 1);
Integer nMinus2;
Integer nMinus3;
Integer nMinus4;
Integer nMinus5;
Integer nMinus6;
if (n + nMinus1 == t) {
// done
return new int[]{i - 1, i};
} else if (i >= 2) {
nMinus2 = list.get(i - 2);
if (n + nMinus1 + nMinus2 == t) {
// done
return new int[]{i - 2, i};
} else if (i >= 3) {
nMinus3 = list.get(i - 3);
if (n + nMinus1 + nMinus2 + nMinus3 == t) {
// done
return new int[]{i - 3, i};
} else if (i >= 4) {
nMinus4 = list.get(i - 4);
if (n + nMinus1 + nMinus2 + nMinus3 + nMinus4 == t) {
// done
return new int[]{i - 4, i};
} else if (i >= 5) {
nMinus5 = list.get(i - 5);
if (n + nMinus1 + nMinus2 + nMinus3 + nMinus4 + nMinus5 == t) {
// done
return new int[]{i - 5, i};
} else if (i >= 6) {
nMinus6 = list.get(i - 6);
if (n + nMinus1 + nMinus2 + nMinus3 + nMinus4 + nMinus5 + nMinus6 == t) {
// done
return new int[]{i - 6, i};
}
}
}
}
}
}
}
}
return new int[]{-1, -1};
}
Here is the question:
Given the list l as [4, 3, 5, 7, 8] and the key t as 12, the function answer(l, t) would return the list [0, 2] because the list l contains the sub-list [4, 3, 5] starting at index 0 and ending at index 2, for which 4 + 3 + 5 = 12, even though there is a shorter sequence that happens later in the list (5 + 7). On the other hand, given the list l as [1, 2, 3, 4] and the key t as 15, the function answer(l, t) would return [-1, -1] because there is no sub-list of list l that can be summed up to the given target value t = 15.
You probably don't need an arraylist. You could perform a double loop on the array l. Why do you want recursion?
You could do something like:
public static int[] answer(int[] l, int t) {
int[] rets = {-1, -1};
int sum=0;
for (int i=0; i<l.length; i++) {
sum=0;
for (int j=i; j<l.length; j++) {
sum+=l[j];
if (sum > t) break;
if (sum == t) {
rets[0] = i;
rets[1] = j;
return rets;
}
}
}
return rets;
}
Just submitted my solution.. it got accepted, so I know it was accepted by Google:
(I believe this will be slightly faster than above solution since it will break the loops and return if the target is greater than sum of all numbers in the array.)
public static int[] answer(int[] l, int t){
int sum =0;
List<Integer> indexes = new ArrayList<>();
for(int j=0;j<l.length;j++){
sum = 0;
indexes.clear();
for(int i=j;i<l.length;i++){
sum += l[i];
indexes.add(i);
if(sum >= t){
break;
}
}
if(sum == t){
break;
}
else if(sum > t){
continue;
}
else{
return new int[] {-1,-1};
}
}
int[] returnArray = new int[2];
if(indexes.size()>0){
returnArray[0] = indexes.get(0);
returnArray[1] = indexes.get(indexes.size()-1);
}
return returnArray;
}
I want to find all the pairs of numbers from an array whose sum is equal to 10, and am trying to improve upon this bit of code here:
for (int j = 0; j < arrayOfIntegers.length - 1; j++)
{
for (int k = j + 1; k < arrayOfIntegers.length; k++)
{
int sum = arrayOfIntegers[j] + arrayOfIntegers[k];
if (sum == 10)
return j + "," + k;
}
}
However, I'm having trouble moving through the array. Here's what I have so far:
int[] arrayOfIntegers = {0, 5, 4, 6, 3, 7, 2, 10};
Arrays.sort(arrayOfIntegers);
System.out.println(Arrays.toString(arrayOfIntegers));
int left = arrayOfIntegers[0];
int right = (arrayOfIntegers[arrayOfIntegers.length - 1]);
while (left < right)
{
int sum = left + right;
if (sum == 10) //check to see if equal to 10
{
System.out.println(left + "," + right);
}
if (sum > 10) // if sum is more than 10, move to lesser number
{
right --;
}
if (sum < 10) // if sum is less than 10, move to greater number
{
left++;
}
} // end of while
Try this code by passing the value of the sum and array in which you want to find the pair of elements equals to a given sum using one for loop
private void pairofArrayElementsEqualstoGivenSum(int sum,Integer[] arr){
List numList = Arrays.asList(arr);
for (int i = 0; i < arr.length; i++) {
int num = sum - arr[i];
if (numList.contains(num)) {
System.out.println("" + arr[i] + " " + num + " = "+sum);
}
}
}
You need to capture the values as well as the indexes:
int[] arrayOfIntegers = {0, 5, 4, 6, 3, 7, 2, 10};
Arrays.sort(arrayOfIntegers);
System.out.println(Arrays.toString(arrayOfIntegers));
int left = 0;
int right = arrayOfIntegers.length - 1;
while (left < right)
{
int leftVal = arrayOfIntegers[left];
int rightVal = (arrayOfIntegers[right]);
int sum = leftVal + rightVal;
if (sum == 10) //check to see if equal to 10
{
System.out.println(arrayOfIntegers[left] + "," + arrayOfIntegers[right]);
right --;
left++;
}
if (sum > 10) // if sum is more than 10, move to lesser number
{
right --;
}
if (sum < 10) // if sum is less than 10, move to greater number
{
left++;
}
} // end of while
output:
[0, 2, 3, 4, 5, 6, 7, 10]
0,10
3,7
4,6
This is sample code with javascrypt. Someone can use it
var arr = [0, 5, 4, 6, 3, 7, 2, 10]
var arr1 = arr;
for(var a=0; a<arr.length;a++){
for(var b=0; b<arr.length; b++){
if(arr[a]+arr[b]===10 && a!==b){
console.log(arr[a]+" + "+arr[b])
arr.splice(a,1);
}
}
}
Java - Using single loop
public static void findElements() {
List<Integer> list = List.of(0, 5, 4, 6, 3, 7, 2, 10);
for (int i = 0; i < list.size(); i++) {
int sum = 0;
if (i < list.size() - 1) {
sum = list.get(i) + list.get(i + 1);
if (sum == 10) {
System.out.println("Element: " + list.get(i) + "," + list.get(i + 1));
}
} else {
if (list.get(i) == 10) {
System.out.println("Element: " + list.get(i));
}
}
}
}
I'm trying to make the merge sort to use only (n/2 + 1) extra space and still O(n log n) time. This is my homework.
The original quesetion:
Write the non-recursive version of merge sort. Your program should run
in O(n log n) time and use n/2 + O(1) extra spaces.
The program will split an array in to two like normal merge sort. The left part will be in another array, which is ceil(n/2) long, so it will fit the requirement.
The right part will be in the original array. So it will be half in-place sorting
Sorry, I don't know how to explain further.
I think this is basically correct. But I kept on facing OutOfBounds error.
I know the code is quite long and messy. But can anyone help me about that?
I spent about 5 hours to implement this. Please help me.
package comp2011.lec6;
import java.util.Arrays;
public class MergeSort {
public static void printArr(int[] arr){
for(int i = 0; i < arr.length; i++){
System.out.printf("%d ", arr[i]);
}
}
public static void mergeSort(int[] arr){
if(arr.length<2) {
return;
}
int n, lBegin, rBegin;
n = 1;
int[] leftArr = new int[arr.length - (arr.length/2)];
while(n<arr.length) {
lBegin = 0;
rBegin = n;
while(rBegin + n <= arr.length) {
mergeArrays(arr, lBegin, lBegin+n, rBegin, rBegin+n, leftArr);
lBegin = rBegin+n;
rBegin = lBegin+n;
}
if(rBegin < arr.length) {
mergeArrays(arr, lBegin, lBegin+n, rBegin, arr.length, leftArr);
}
n = n*2;
}
}
public static void mergeArrays(int[] array, int startL, int stopL, int startR, int stopR, int[] leftArr) {
// int[] right = new int[stopR - startR + 1];
// int[] left = new int[stopL - startL + 1];
// for(int i = 0, k = startR; i < (right.length - 1); ++i, ++k) {
// right[i] = array[k];
// }
System.out.println("==============");
System.out.println("stopL: " + stopL +" startL: " + startL);
for(int i = 0, k = startL; i <= (stopL - startL); ++i, ++k) {
System.out.println(leftArr[i]);
leftArr[i] = array[k];
}
// right[right.length-1] = Integer.MAX_VALUE;
leftArr[stopL - startL] = Integer.MAX_VALUE;
System.out.println("leftArr: " + Arrays.toString(leftArr));
System.out.println("RightArr: " + Arrays.toString(Arrays.copyOfRange(array, startR, stopR)));
System.out.println("before: " + Arrays.toString(array));
// for(int k = startL, m = 0, n = startR; k < stopR; ++k) {
System.out.println("StartL: " + startL + " StartR: " + stopR);
for(int k = startL, m = 0, n = startR; ( (k < stopR) ); ++k) {
System.out.println("k: " + k);
System.out.println("Left: " + leftArr[m]);
System.out.println("Right: " + array[n]);
System.out.println("Array[k] before: " + array[k]);
// if(leftArr[m] == Integer.MAX_VALUE){
// System.out.println("YES");
// }
if( (leftArr[m] <= array[n]) || (n >= stopR) ) {
System.out.println("Left is smaller than right");
array[k] = leftArr[m];
m++;
}
else {
System.out.println("Right is smaller than left");
array[k] = array[n];
System.out.println("right: " + array[k]);
n++;
}
System.out.println("Array[k] after: " + array[k]+"\n");
}
System.out.println("after " + Arrays.toString(array));
}
public static void main(String[] args) {
int[] array = new int[] { 5, 2, 4, 12, 2, 10, 13, 1, 7 };
mergeSort(array);
printArr(array);
}
}
Why does System.arraycopy() throw ArrayIndexOutOfBoundsException? I am trying to write mergeSort(it's not final version, firstly I want that current alghorithm work with these data).
package Procedural.Intro;
import java.util.Arrays;
import java.util.Random;
/**
* Created by Сергей on 28.06.2015.
*/
public class MergerSort {
public static void main(String[] args) {
int [] initial;
int [] initial2;
initial = new int [] {1, 4, 5, 6, 7};
initial2 = new int [] {2, 4, 9, 11, 121};
System.out.println("Array1 initial: " + Arrays.toString(initial));
System.out.println("Array2 initial: " + Arrays.toString(initial2));
System.out.println("Array result: " + Arrays.toString(MergerSort.mergerSort(initial, initial2)));
}
private static int [] mergerSort(int[] left, int[] right) {
int [] result = new int[left.length + right.length];
int leftIndex = 0;
int rightIndex = 0;
while( leftIndex + rightIndex < result.length) {
if(left[leftIndex] > right[rightIndex]) {
result[leftIndex + rightIndex] = right[rightIndex++];
}
else {
result[leftIndex + rightIndex] = left[leftIndex++];
}
if(leftIndex == left.length) {
System.arraycopy(right, right[rightIndex], result, leftIndex + rightIndex, result.length - (leftIndex + rightIndex));
break;
}
if(rightIndex == right.length) {
System.arraycopy(left, left[leftIndex], result, leftIndex + rightIndex, result.length - ( leftIndex + rightIndex));
break;
}
}
return result;
}
}
If you have a look at the documentation to System.arrayCopy, it expects as the second argument an index into the array. However, you have there a value from your array. So most probably you wanted to write
System.arraycopy(right, rightIndex, ...
instead of
System.arraycopy(right, right[rightIndex], ...
The same for your second call of System.arraycopy
You're forgetting that the last index is not the array length, it's the array length - 1. You forgot to subtract one from the last parameter in your System.arraycopy
You have result.length - (leftIndex + rightIndex) where it should be
result.length - (leftIndex + rightIndex) - 1