Equal Partitioning with Minimum Sum Difference - java

I'm trying to write this algorithm in Java following the steps below:(I know other solutions, just trying to figure out this one)
int min_diff = LARGE_NUMBER;
int diff;
for (each subset S of size n/2 of A) {
diff = abs(sum(S) – sum(A-S));
if (diff < min_diff) {
min_diff = diff;
TempSet = S;
}
}
print min_diff, TempSet;
I tried to find all subset permutations of size n/2 using the code from this link: https://www.geeksforgeeks.org/print-subsets-given-size-set/
The code in this link print all permutations. I thought first I need to store the arrays in an ArrayList so I can use them in the for loop, but I couldn't get it to work. The code below gives wrong output (every array is 60 60 60 instead of permutations:
static List<int[]> intArrays = new ArrayList<>();
static void combinationUtil(int[]arr, int n, int r, int index, int[] data, int i)
{
if (index == r) {
intArrays.add(data);
return;
}
if (i >= n)
return;
data[index] = arr[i];
combinationUtil(arr, n, r, index + 1, data, i + 1);
combinationUtil(arr, n, r, index, data, i + 1);
}
static void printCombination(int arr[], int n, int r)
{
int data[] = new int[r];
combinationUtil(arr, n, r, 0, data, 0);
for(int[] arr1:intArrays){
System.out.println(Arrays.toString(arr1));
}
}
public static void main(String[] args)
{
int arr[] = { 10, 20, 30, 40,50,60};
int n=arr.length;
int r=n/2;
printCombination(arr, n, r);
}
Can anyone tell me what's wrong with my code? Or how can I solve this problem following the above steps?

Your problem is when you do intArrays.add(data);
intArrays always contains the reference to data array. The array is passed by reference. You gets {60, 60, 60} because is the last state of data array (the last subset).
To fix the problem you must to do intArrays.add(data.Clone()); if exists Clone function or similar in you language or just implement it yourself.
Code in C#. Sorry I don't have any java compiler installed.
static int[] CloneArray(int[] arr)
{
int[] ret = new int[arr.Length];
for (int i = 0; i < arr.Length; ++i) ret[i] = arr[i];
return ret;
}

Related

Merge Sort does not work properly. The numbers in array are not sorted

The following is my code for Merge Sort in JAVA, but the output is not expected.
given input is [49, 1, 3, 200, 2, 4, 70, 5]
The output is :
Merge sort : [2, 4, 49, 1, 3, 70, 5, 200]
Which the number is not sorted. I believe the problem is in the merge method. Can anyone help?
merge_sort method:
private static int[] merge_sort(int[] unsorted_array) {
if (unsorted_array.length < 2) {
return unsorted_array;
}
int mid = unsorted_array.length / 2;
int[] first_array = new int[mid];
int[] second_array = new int[unsorted_array.length - mid];
//Copy element to first and second array.
for (int i = 0; i < mid; i ++) {
first_array[i] = unsorted_array[i];
}
for (int i = 0; i < second_array.length; i++) {
second_array[i] = unsorted_array[mid + i];
}
merge_sort(first_array);
merge_sort(second_array);
int[] sorted_array = merge(first_array, second_array);
return sorted_array;
}
merge method:
private static int[] merge(int[] first_array, int[] second_array) {
int[] result = new int[first_array.length + second_array.length];
int index_result = 0;
int index_first = 0;
int index_second = 0;
while (index_first < first_array.length && index_second < second_array.length) {
if (first_array[index_first] < second_array[index_second]) {
result[index_result] = first_array[index_first];
index_first++;
} else {
result[index_result] = second_array[index_second];
index_second++;
}
index_result++;
}
while (index_first < first_array.length) {
result[index_result] = first_array[index_first];
index_result++;
index_first++;
}
while (index_second < second_array.length) {
result[index_result] = second_array[index_second];
index_result++;
index_second++;
}
return result;
}
You've made a very simple mistake.
Those two following lines are wrong in your code:
merge_sort(first_array);
merge_sort(second_array);
You should write those two lines as follows:
first_array = merge_sort(first_array);
second_array = merge_sort(second_array);
cause, your merge_sort() method returns a sorted array. It does not sort in place the unsorted_array parameter. Rather, it returns the sorted elements in a newly created sorted_array. So, you would get the sorted result from return value of merge_sort() method and then, you should merge them. Rather than doing that, you were just merging two unsorted arrays.
Its not necessary, but you could write as follows for clarification:
int[] sorted_first_array = merge_sort(first_array);
int[] sorted_second_array = merge_sort(second_array);
// and then merge
int[] sorted_array = merge(sorted_first_array, sorted_second_array);
// then return
return sorted_array;
[P.S.]: When you are coding in java, please use java variable and method naming convention. Its easier to read code when you're following convention.
You are not using the sorted intermediate results to merge, instead using the original splitted arrays. Modify your code as below:
first_array = merge_sort(first_array);
second_array = merge_sort(second_array);
int[] sorted_array = merge(first_array, second_array);
Also you don't need to create these intermediate arrays. You just have to pass the low, high pointers to your array to indicate the portions of the array you are sorting and merging.
Like :
private static void merge_sort(int[] unsorted_array, int low, int high) {
if (low == high) return;
int mid = low + ( high - low ) / 2;
merge_sort(unsorted_array, low, mid);
merge_sort(unsorted_array, mid+1, high);
merge(unsorted_array, low, mid, high);
}
where high is inclusive and you call this like : merge_sort(arr, 0, arr.length-1)

binary partition an array using java

I am a beginner(first year uni student) programmer trying to solve this problem which i'm finding somewhat difficult. If you are to answer this question, don't provide me with a complex daunting algorithm that will leave me scratching my head. I'll really appreciate it if you explain it step my step (both logically/conceptually then through code)
The problem is as follows:image
I have tried to attempt it and my code only works for a certain case that i tested.
package com.company;
import java.lang.Math;
public class Main {
public static int[][] binary_partition(int array[], int k){
int x = (int) Math.pow(2,k);
int[][] partition = new int[((array.length/x)*2)][array.length/x];
int divisor = array.length/x;
if ((array.length % 2) != 0){
return partition;
}
if (divisor >= array.length-1){
return partition;
}
if (k==1){
return partition;
}
int p = 0;
for(int i=0;i<((array.length/x)*2);i++)
{
for (int j = 0; j<array.length/x;j++)
{
partition[i][j] = array[p];
p += 1;
}
}
return partition;
}
public static void main(String[] args){
int[] array = {3, 2, 4, 7, 8, 9, 2, 3};
int[][] result = binary_partition(array,2);
for (int[] x : result){
for (int y : x)
{
System.out.print(y + " ");
}
System.out.println();
}
}
}
Your question is unclear, but this solution creates a function that partitions an array with the right length into 2^k sets.
First, an interesting fact: using the bitshift operator << on an integer increases its value by a power of two. So to find out the size of your partition, you could write
int numPartitions = 1 << k; // Equivalent to getting the integer value of 2^k
With this fact, the function becomes
public static int[][] partition(int[] set, int k) {
if (set == null)
return null; // Don't try to partition a null reference
// If k = 0, the partition of the set is just the set
if (k == 0) {
int[][] partition = new int[1][set.length];
// Copy the original set into the partition
System.arraycopy(set, 0, partition[0], 0, set.length);
return partition;
}
int numPartitions = 1 << k; // The number of sets to partition the array into
int numElements = set.length / numPartitions; // The number of elements per partition
/* Check if the set has enough elements to create a partition and make sure
that the partitions are even */
if (numElements == 0 || set.length % numElements != 0)
return null; // Replace with an error/exception of your choice
int[][] partition = new int[numPartitions][numElements];
int index = 0;
for (int r = 0; r < numPartitions; r++) {
for (int c = 0; c < numElements; c++) {
partition[r][c] = set[index++]; // Assign an element to the partition
}
}
return partition;
}
There are a few lines of your code where the intention is not clear. For example, it is not clear why you are validating divisor >= array.length-1. Checking k==1 is also incorrect because k=1 is a valid input to the method. In fact, all your validation checks are not needed. All you need to validate is that array.length is divisible by x.
The main problem that you have seems to be that you mixed up the lengths of the resulting array.
The resulting array should have a length of array.length / x, and each of the subarrays should have a length of x, hence:
int[][] partition = new int[array.length/x][x];
If you also fix your bounds on the for loops, your code should work.
Your nested for loop can be rewritten as a single for loop:
for(int i = 0 ; i < array.length ; i++)
{
int index = i / x;
int subArrayIndex = i % x;
partition[index][subArrayIndex] = array[i];
}
You just need to figure out which indices a an element array[i] belongs by dividing and getting the remainder.

Coin Change Recursion All Solutions to Distinct Solutions

I am new to recursion and backtracking. I know I need to be completely comfortable with these concepts before I move on to dynamic programming. I have written a program below that helps me find all the possible combinations for a given amount n and an unlimited number of coins. However, I wish to have my program give me distinct solutions. I am having a hard time figuring out how to do this.
I have found a resource here: Coin Change that uses a top down approach recursively and then modifies it to give distinct combinations using the following formula: count (s, n, total) = count (s, n, total-s[n]) + count(s, n-1, total)
This says that I recurse using the value and then recurse excluding the value and decreasing the coins by 1.
I can't seem to grasp how this works. Also I can for sure say, it would have been quite hard to even think of such a technique on the spot at an interview per say. It seems like some one at some point would have had to spend a considerable amount of time on such a problem to devise such a technique.
Anyhow any help on how I can convert my program to print distinct solutions and how it works will be really appreciated.
public class Recursive {
static int[] combo = new int[100];
public static void main(String argv[]) {
int n = 8;
int[] amounts = {1, 5, 10};
ways(n, amounts, combo, 0, 0, 0);
}
public static void ways(int n, int[] amounts, int[] combo, int count, int sum, int index) {
if(sum == n) {
printArray(combo, index);
}
if(sum > n) {
return;
}
for(int i=0;i<amounts.length;i++) {
sum = sum + amounts[i];
combo[index] = amounts[i];
ways(n, amounts, combo, 0, sum, index + 1);
sum = sum - amounts[i];
}
}
public static void printArray(int[] combo, int index) {
for(int i=0;i < index; i++) {
System.out.print(combo[i] + " ");
}
System.out.println();
}
}
The actual amount of non distinct valid combinations for amounts {1, 2, 5} and N = 10 is 128, using a pure recursive exhaustive technique (Code below).
My question is can an exhaustive search be improved with memoization/dynamic programming. If so, how can I modify the algorithm below to incorporate such techniques.
Simple modification allow to avoid repeats.
Use sorted amounts array.
Starting value of the loop should exclude previous values from amounts.
I used count argument (seems unused)
for(int i=count;i<amounts.length;i++) {
sum = sum + amounts[i];
combo[index] = amounts[i];
ways(n, amounts, combo, i, sum, index + 1);
sum = sum - amounts[i];
}
static HashMap<Integer, Integer> memo = new HashMap<Integer, Integer>();
public static void main(String argv[]) {
int n = 1000;
System.out.println(getSteps(n, 0,0 ));
}
public static int getSteps(int n, int sum, int count) {
if(n == sum) {
return 1;
}
if(sum > n) {
return 0;
}
if(memo.containsKey(sum)) {
return memo.get(sum);
}
for(int i=1; i<=3;i++) {
sum = sum + i;
count += getSteps(n, sum, 0);
sum = sum - i;
memo.put(sum, count);
}
return count;
}

Using Binary Search to find a value in an Array (Java)

I need to use binary search to locate 45.3 in the array. Here's what I have so far.
public class Bsearch {
public static final int NOT_FOUND = -1;
public static int binarySearch(int[] a, int x) {
int low = 0;
int high = a.length - 1;
int mid;
while (low <= high) {
mid = (low + high) / 2;
if (a[mid].compareTo(x) < 0)
low = mid + 1;
else if (a[mid].compareTo(x) > 0)
high = mid - 1;
else
return mid;
}
return NOT_FOUND;
}
public static void main(String[] args) {
int SIZE = 6;
int[] a = new Integer[SIZE] = { 10, -3, 5, 24, 45.3, 10.5 };
System.out.println("45.3 Found" + binarySearch(a, 45.3));
}
}
All my errors seem to be stemming from this area-
int [] a = new Integer [ SIZE ]={ 10,-3,5,24,45.3,10.5 };
System.out.println("45.3 Found" +binarySearch(a, 45.3));
All this is new to me so sorry for any obvious mistakes.
For binary search Data Array should be sorted, and sorted in the right order, but the array you are passing to binarySearch(int[] a, int x) is not sorted so first sort the array and then apply binary search on it.
Also check your logic for binary search, you are comparing middle element with 0 it should be compared with the element to be searched(key)
while(high >= low) {
int middle = (low + high) / 2;
if(data[middle] == key) {
return true;
}
if(data[middle] < key) {
low = middle + 1;
}
if(data[middle] > key) {
high = middle - 1;
}
}
The problem is indeed in this line:
int[] a = new Integer[SIZE] = { 10, -3, 5, 24, 45.3, 10.5 };
There are a number of issues:
You can't assign an Integer[] to an int[] variable. Change it to new int[]
You can't put a floating point number in an array of integers; change your numbers 45.3 and 10.5 to integers.
You have two options in Java: when you create a new array with the new operator, you either specify size of the array, or the contents.
So either:
int[] a = new int[SIZE];
Or
int[] a = new int[] { 10, -3, 5, 24, 45, 10 };
Both will work.
You have to decide whether you want to use primitive types (int) of class wrappers (Integer) and stick to it.
Your method binarySearch takes an int[] as a parameter, but you are using methods (compareTo) that are only available on Integer.
But actually, comparing is much simpler with primitive types:
if (a[mid] < x)
low = mid + 1;
else if (a[mid] > x)
high = mid - 1;
else
return mid;

Quicksort (from the book Programming perls)

I am trying to learn all I can about sorting algorithms. On today's agenda is the Quicksort. Heres what I got.
QuickSort Class:
import java.util.*;
public class QuickSort{
public static void swap(int A[], int x ,int y){
int temp = A[x];
A[x] = A[y];
A[y] = temp;
}
public static int[] QSort(int A[], int L, int U){
Random randomGenerator = new Random();
if (L >= U){
System.out.printf("The value of L: %d, U: %d\n",L,U);
return A; // Sorted.
}
if (L < U ){
int randomInt = randomGenerator.nextInt(U);
swap( A, L, randomInt);
int T = A[L];
int M = L;
for (int i = L+1;i < U; i++){
if ( A[i] < T){
M = M+1;
swap(A, M, i);
}
}
swap(A, L, M);
QSort(A, L, M-1 );
QSort(A, M+1, U );
}
//System.out.println(Arrays.toString(A));
return A;
}
}
The Main:
import java.util.*;
public class Main{
public static void main(String [] args){
int[] intArray = {1,3,2,4,56,0,4,2,4,7,80,120,99,9,10,67};
System.out.printf("Original Array was: %s\n\n",Arrays.toString(intArray));
System.out.printf("Size of Array is: %d\n",intArray.length);
QuickSort qs = new QuickSort();
int[] A = qs.QSort(intArray, 5, intArray.length);
System.out.println(Arrays.toString(intArray));
}
}
Well that's all have till now. The code compiles and everything but the sorting algorithm is wrong. I am trying to understand logically whats happening in the QuickSort algorithm and used the book Programming Perls to aid my understanding.
Here's the list of questions I have:
In the QuickSort class in the for loop according to the book, "i's" conditional clause needs to be "i <=U" but if I do that the code gives me an 'Array index out of bounds' error. Why is that happening ? I know what an 'array index out of bounds' error is, I just can't grasp why the array location wont exist?
The first if clause checks to see if the array is sorted. When I compile the code this clause is meet on the first try(which should not happen in the first place). And if it is why isn't the function ended via the return A line?
The book I am using is by John Bentley page 112.
Apart from other anomalies already pointed out,
Your question 1:
As already stated the initial value for U should be intArray.length - 1.
int[] A = qs.QSort(intArray, 5, intArray.length - 1 );
Your question 2:
The first if clause does not check if the array is sorted, it just checks whether the U and L pointers have crossed each other or not.
For quicksort, this means that for the current pivot, all items less than pivot are to its left and all elements greater than pivot are to its right.
This crossing may happen multiple times during the sort depending on the number of pivot changes required to completely sort the array.
For more information on quicksort, following link may be helpful. http://www.cplusplus.com/faq/sequences/sequencing/sort-algorithms/quicksort/
In your invocation of QSort the upper bound is exclusive
QSort(A, L, M-1 );
but here you miss to sort the number at index M-1.
It should be
QSort (A, L, M);
PS. and what #LeeNeverGup said about the random.
Basically, this:
import java.util.*;
public class QSort {
public static void swap(int A[], int x, int y) {
int temp = A[x];
A[x] = A[y];
A[y] = temp;
}
public static void sort (int A[], int L, int U) {
Random randomGenerator = new Random();
if (L + 1 >= U)
return;
int randomInt = L + randomGenerator.nextInt(U - L);
swap(A, L, randomInt);
int T = A[L];
int M = L;
for (int i = L + 1; i < U; i++) {
if (A[i] < T) {
M = M + 1;
swap(A, M, i);
}
}
swap(A, L, M);
sort(A, L, M);
sort(A, M + 1, U);
}
public static void main(String[] args) {
int[] intArray =
{ 1, 3, 2, 4, 56, 0, 4, 2, 4, 7, 80, 120, 99, 9, 10, 67 };
System.out.printf( "Original Array was: %s\n\n",
Arrays.toString(intArray));
System.out.printf("Size of Array is: %d\n", intArray.length);
QSort.sort (intArray, 0, intArray.length);
System.out.println(Arrays.toString(intArray));
}
}
In this line : int randomInt = randomGenerator.nextInt(U);
You should get a random int between L and U, by using:
int randomInt = L + randomGenerator.nextInt(U - L);
Also, if you want U to be the largest index in the array, you shoule pass to it intArray.length - 1

Categories

Resources