Subset sum but even subset size - java

So, basically it's the same idea as the subset sum problem, but with one restriction: The found subset needs to have an even size.
For example:
numbers {4, 3, 3, 5, 1, 2, 7, 12}
find subset that sums up to 10
=> solution: {4, 3, 1, 2} (or {3, 7} but not {4, 3, 3} )
Is there a simple method to find such a subset? (The method should be "efficient", not just trying all possible subsets...)
Here is my code to find a "normal" subset:
int n = 8;
int m = 11;
boolean[][] S = new boolean[n][m];
int[] N = new int[] {4, 3, 3, 5, 1, 2, 7, 12};
S[0][0] = true;
S[0][S[0]] = true;
for(int i = 1; i < n; i++) {
for(int j = 0; j < m; j++) {
if(N[i] == j) {
S[i][j] = true;
} else if(j - N[i] >= 0) {
S[i][j] = S[i-1][j] || S[i-1][j - N[i]];
} else {
S[i][j] = S[i-1][j];
}
}
}

In your current code S[i][j] is true if you can make value j as a subset of numbers up to i.
Instead, compute S[i][j][k] is true if you can make value j as a subset of numbers up to i with the number of numbers used equal to k modulo 2.
In other words, k is either 0 or 1.
This will require around twice the computations of your existing solution.

Related

Return a version of the given array where each zero value in the array is replaced by the largest odd value to the right of the zero in the array

If there is no odd value to the right of the zero, leave the zero as a zero.
zeroMax([0, 5, 0, 3]) → [5, 5, 3, 3]
zeroMax([0, 4, 0, 3]) → [3, 4, 3, 3]
This is from CodingBat: https://codingbat.com/prob/p187050
There are certainly better implementations than mine, but it would help me tremendously to see where I went wrong.
It is the findAndReplace method that is not doing its job. I don't see a reason as to why it insists that intarray[0] = 0, and that is where I am stuck. I have implemented the method separately from this class, and it works as expected.
Below is my work:
public class ZeroMax {
public static int[] zeroMax(int[] intarray) {
int max = largestOdd(intarray);
System.out.println("largest odd is " + max);
return findAndReplace1(intarray, 0, max);
}
//method returns the largest odd value or returns zero
public static int largestOdd(int[] arr) {
int maxodd = 0;
int n = arr.length;
int temp = 0;
//this is just a bubble sort
for (int i = 0; i < n; i++) {
for (int j = 1; j < (n - i); j++) {
if (arr[j - 1] > arr[j]) {
//swap elements
temp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temp;
}
}
}
//this finds the largest number that is an odd
for (int i = arr.length - 1; i >= 0; i--) {
if (arr[i] % 2 != 0) {
maxodd = arr[i];
break;
} else {
continue;
}
}
return maxodd;
}
//following returns an array where the zeros (int find)
// can be replaced with the largest odd (int replace)
public static int[] findAndReplace1(int[] intarray, int find, int replace) {
for (int i = 0; i < intarray.length; i++) {
//System.out.println(intarray[i]);
if (intarray[i] == find) {
intarray[i] = replace;
}
}
return intarray;
}
}
I believe that the key to your problem is
… to the right of the zero in the array
One given example is zeroMax([0, 5, 0, 3]) → [5, 5, 3, 3]. In your code you are finding the greatest odd value in the entire array. 5 in this case. Then you are replacing every 0 in the array with 5.
Original array: [0, 5, 0, 3]
Expected result: [5, 5, 3, 3]
Your result: [5, 5, 5, 3]
So it seems that you still have a bit of coding to do.
There are certainly better implementations than mine, …
Your implementation, your design and code style, are just fine. Only except for the lamentable fact that it didn’t solve the problem correctly.
An idea how to solve the problem. The following should work in all cases:
Iterate backward from the end array until the first (so the rightmost) odd number.
If there isn’t any odd number in the array, you’re done.
Store the odd number into a variable holding the greatest odd number encountered so far.
Continue iterating backward from the index you came to down to index 0. For each index:
If the number at the index is odd and greater than the hitherto greatest odd number, store the number as the greatest odd number.
If the number is 0, store the greatest odd number until now into the array at this index.
I was reading the question wrong. This is the successful solution that I came up with after more careful reading:
public int[] zeroMax(int[] intarray) {
int maxvalue = 0;
int index = 0;
for (int i = 0; i < intarray.length; i++) {
if (intarray[i] == 0) {
index = i;
//call max value method
maxvalue = maxvalue(intarray, index);
intarray[i] = maxvalue;
}
}
return intarray;
}
public int maxvalue(int[] intarray, int index) {
int maxvalue = 0;
for (int i = index; i < intarray.length; i++) {
if ((intarray[i] % 2 == 1) && (intarray[i] > maxvalue)) {
maxvalue = intarray[i];
}
}
return maxvalue;
}
You can use Arrays.stream(T[],int,int) method to iterate over this array from the current index to the end, then filter odd numbers and get max of them:
public static void main(String[] args) {
int[] arr1 = {0, 5, 0, 3};
int[] arr2 = {0, 4, 0, 3};
int[] arr3 = {0, 3, 0, 4};
replaceZeros(arr1);
replaceZeros(arr2);
replaceZeros(arr3);
System.out.println(Arrays.toString(arr1)); // [5, 5, 3, 3]
System.out.println(Arrays.toString(arr2)); // [3, 4, 3, 3]
System.out.println(Arrays.toString(arr3)); // [3, 3, 0, 4]
}
private static void replaceZeros(int[] arr) {
// iterate over the indices of array
IntStream.range(0, arr.length)
// filter zero elements
.filter(i -> arr[i] == 0)
// for each zero iterate over the elements
// of array from the current index to the end
.forEach(i -> Arrays.stream(arr, i, arr.length)
// filter odd elements
.filter(e -> e % 2 != 0)
// take the max element and
// replace the current one
.max().ifPresent(e -> arr[i] = e));
}

Swap even odd indices in a java int array

I am trying to swap numbers in int array according to even and odd indices.
So far,
I was able to work out how to target even and odd indices but,
then because of nested for loops I am not able to print all the elements in one array.
Here is my code -
public class SwapIndexes {
public static void main(String []args) {
int temp;
int[] arr = {1, 2, 3, 4, 5, 6};
for (int j = 0; j < arr.length; j += 2) {
for (int k = 1; k < arr.length; k += 2) {
temp = arr[j];
arr[j] = arr[k];
arr[k] = temp;
System.out.print(arr[k]);
}
}
}
}
This code gives 124312531 as output for arr[k] and gives 246124312 as output for arr[j]. I want the output to be
2,1,4,3,6,5
I really don't understand why you have two loops. You only need one since you need to browse the array only once. Here is the code with one loop: j will have all the odd indexes and then you switch j-1 and j.
Since no specification is given about the behavior of an array with an odd number of elements, in that case it doesn't modify the last value. If needed, you can throw an exception.
public static void main(String []args) {
int temp;
int[] arr = {1, 2, 3, 4, 5, 6};
for (int j = 1; j < arr.length; j += 2) {
temp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = temp;
}
System.out.print(Arrays.toString(arr));
}
Well, I don't know why you have use two loop because the idea was there.
Remove the second loop, set k to j + 1 and the logic is here (commented the code that you don't need.
for (int j = 0; j < arr.length; j += 2) {
//for (int k = 1; k < arr.length; k += 2) {
int k = j + 1;
temp = arr[j];
arr[j] = arr[k];
arr[k] = temp;
//System.out.print(arr[k]);
//}
}
System.out.print(Arrays.toString(arr));
Now, you need to prevent exception to occurs for uneven length.
I like to simple use a slightly different loop :
for (int j = 1; j < arr.length; j += 2) {
int k = j - 1;
...
}
System.out.print(Arrays.toString(arr));
All you have to do is check if there is at least 2 cells, which make sense if you want to reverse an array like this
if(arr.length < 2)
return;
Test 1:
{1, 2, 3, 4, 5, 6}
[2, 1, 4, 3, 6, 5]
Test 2:
{1, 2, 3, 4, 5, 6, 7}
[2, 1, 4, 3, 6, 5, 7]

Finding the largest area of equal numbers in matrix java

I have a task.I need to find the biggest area with equal numbers(e.g. neighbours by row or column). The program that i made works fine,but the problem is that if i have the following matrix:
{ 1, 3, 2, 2, 2, 4 }
{ 3, 1, 3, 2, 4, 4 }
{ 4, 3, 1, 2, 3, 3 }
{ 4, 3, 1, 3, 3, 1 }
{ 4, 3, 3, 3, 1, 1 }
The program will print 10.Okay maybe some of you may say that it's because i add 1 to the final result,yeah that's true but if i don't add 1 ,and if the number at position [1][1] was 3 instead of 1 ,i would get 12 witch is wrong,so that`s why i add 1.So my question is do you have any suggestions about optimazing the algorithm..if yes,i would be very thankful to hear them :)..
Here is my code:
protected int counter = 0;
protected int max = 1;
protected enum eState {
Vi,
InPr,
Unvi
};
public void recNodeMatrix(int i, int j, eState st[][],int [][]matr,int n,int k) {
st[i][j] = eState.InPr;
for (int r = 0; r < n; r++) {
for (int c = 0; c < k; c++) {
if ((matr[i][j] == matr[r][c])
&& ((((i+j) - (r + c)) == 1) || (((i+j) - (r + c)) == -1))
&& ((st[r][c] == eState.Unvi))) {
counter++;
recNodeMatrix(r, c, st,matr,n,k);
}
}
}
st[i][j] = eState.Vi;
}
public void Zad17() {
int n=5,k=6;
eState st[][] = new eState[n][k];
int[][] matr = new int[][] {
{ 1, 3, 2, 2, 2, 4 },
{ 3, 1, 3, 2, 4, 4 },
{ 4, 3, 1, 2, 3, 3 },
{ 4, 3, 1, 3, 3, 1 },
{ 4, 3, 3, 3, 1, 1 } };
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
st[i][j] = eState.Unvi;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
if(st[i][j] == eState.Unvi) {
recNodeMatrix(i, j, st,matr,n,k);
if(max<counter)
max=counter;
counter =0;
}
}
}
System.out.print(max+1);
}
Probably the best way to solve this problem is with a union-find data structure: https://en.wikipedia.org/wiki/Disjoint-set_data_structure
Initially, each cell is its own set, and then you merge the sets for every pair of adjacent cells that have equal numbers in them.
When you're done, the answer is the size of the biggest set. Since you have to keep track of the set sizes anyway, use union-by-size instead of union-by-rank.
Applying a bit of cleverness, you can implement the union-find with just an array of N*K integers -- one for each cell. Each integer is either the index of the parent set or -size for roots.
This solves the problem in about linear time, and will probably be faster in practice than flood-fill solutions using a similar amount of memory.

Number of Groups Consisting of 3 Decreasing values in Integer Array (Below O(n^3) Time) [duplicate]

This question already has answers here:
How to find 3 numbers in increasing order and increasing indices in an array in linear time
(14 answers)
is it possible to find all the triplets in the given array for the O (n) time?
(1 answer)
Closed 6 years ago.
A decreasing triple is defined as a set of 3 values {a, b, c} that decrease in magnitude from left to right such that a > b > c.
How could one find the number of these triples in an array of integers where the indices of the triple {i, j, k} are increasing such that i < j < k.
For example, consider the following examples:
{4, 5, 2, 1}
2 decreasing triples: {4, 2, 1} and {5, 2, 1}
{6, 1, 2, 4, 5, 3}
2 decreasing triples: {6, 5, 3} and {6, 4, 3}
{5, 4, 3, 2, 1}
10 decreasing triples:
{5, 4, 3}, {5, 4, 2}, {5, 4, 1}, {5, 3, 2}, {5, 3, 1},
{5, 2, 1}, {4, 3, 2}, {4, 3, 1}, {4, 2, 1}, {3, 2, 1}
The O(n^3) solution is trivial of course; here is an implementation in java:
*note: the arrays are of longs, but that is a minor implementation detail
public static long countTriples(long[] measurements)
{
// O(n^3)
long count = 0L;
for(int i = 0; i < measurements.length; i++)
{
for(int j = i + 1; j < measurements.length; j++)
{
if ( measurements[j] < measurements[i] )
{
for(int k = j + 1; k < measurements.length; k++)
{
if ( measurements[k] < measurements[j] )
{
count++;
}
}
}
}
}
return count;
}
}
I began an O(n) method to locate decreasing triples; it successfully identified triples, but I couldn't get it to count right when the middle value of a given triple was involved in more than one. Here is what I have of that right now:
public static long countTriples(long[] measurements)
{
ArrayList<Long> greaterOnLeft = new ArrayList<Long>();
ArrayList<Long> lessOnRight = new ArrayList<Long>();
HashSet<Long> min = new HashSet<Long>();
min.add(measurements[measurements.length - 1]);
HashSet<Long> max = new HashSet<Long>();
max.add(measurements[0]);
for(int i = 0; i < measurements.length; i++)
{
min.add(measurements[measurements.length - i - 1]);
max.add(measurements[i]);
System.out.println("max: " + max + ", min: " + min);
for(long n : max)
if (measurements[i] < n) greaterOnLeft.add(measurements[i]);
for(long n : min)
if (measurements[measurements.length - i - 1] > n) lessOnRight.add(measurements[measurements.length - i - 1]);
}
long count = 0;
for(long n : greaterOnLeft)
{
if(lessOnRight.contains(n)) count++;
}
return count;
}
The idea for this approach came from a HashSet method for locating the middle indices of such tripples from this post:
How to find 3 numbers in increasing order and increasing indices in an array in linear time
I believe this can be solved in O(n^2) time rather trivially:
public static long countTriples(long[] measurements)
{
// O(n^2)
long count = 0;
for(int i = 1; i < measurements.length - 1; i++)
{
long right = 0, left = 0;
for(int j = 0; j < measurements.length; j++)
{
if(j < i && measurements[j] > measurements[i]) right++;
else if (j > i && measurements[j] < measurements[i]) left++;
}
count += right * left;
}
return count;
}

Using an array of arrays (int[][]), create a method to find all cycles within a given permutation [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
So I can just use standard arrays for this, nothing else. I have to find a way to make a method that finds all the cycles in the given permutation and returns them as an array object of arrays. Then I have to place the lowest of each array as the first entry of the array. Then sort them by lowest.
I can't use arraylists or sets or anything.
EDIT: By cycles I mean take the integer value of the initial object and locate the index value that it corresponds to. Take that integer value at that index and do the same. Continue doing this until it points back to an object that's already been referenced.
An example: [0, 4, 2, 8, 7, 9, 1, 6, 5, 3]
would be these cycles : [0] [4, 8, 5, 7, 6, 9, 3, 2] [1]
and return this: [0], [1], [2, 4, 8, 5, 7, 6, 9, 3]
or
This array: [2, 4, 8, 1, 5, 3, 9, 0, 7, 6]
would be these cycles : [2, 8, 7, 0] [4, 5, 3, 1] [9, 6]
and return this : [0, 2, 8, 7], [1, 4, 5, 3], [6, 9]
I am so lost, any help would be wonderful. thanks ahead of time!
Don't ask why I took the time to do this.
EDIT: Totally working now
public class Main {
public Main()
{
}
public static void main(String[] args)
{
int array[] = {0, 4, 2, 8, 7, 9, 1, 6, 5, 3};
Main m = new Main();
int[][] cycles = m.getCycles(array);
for (int i = 0; i < cycles.length; i++)
{
System.out.print("[");
for (int j = 0; j < cycles[i].length; j++)
{
System.out.print(cycles[i][j]);
if (j < cycles[i].length - 1)
System.out.print(", ");
}
System.out.println("]");
}
System.out.println("end debug");
}
public int[][] getCycles(int[] array)
{
int[][] cycles = new int[array.length][array.length];
// initialize the cycles to all -1s, cuz they'll never be in the array
for (int i = 0; i < cycles.length; i++)
{
for (int j = 0; j < cycles[i].length; j++)
{
cycles[i][j] = -1;
}
}
int i = 0;
do {
int nextElement = array[i];
int j = 0;
do {
cycles[i][j] = nextElement;
nextElement = array[nextElement];
j++;
} while (!elementInArray(cycles[i], nextElement) && j < array.length);
i++;
} while (!arrayHasCycled(array, cycles) && i < array.length);
cycles = removeNegativeOnes(cycles, i);
for (i = 0; i < cycles.length; i++)
{
pushForward(cycles[i]);
}
return cycles;
}
public boolean elementInArray(int[] array, int element)
{
for (int i = 0; i < array.length; i++)
{
if( array[i] == element)
return true;
}
return false;
}
public int[][] removeNegativeOnes(int[][] cycles, int numCycles)
{
int [][] newCycles = new int[numCycles][];
for (int i = 0; i < numCycles; i++)
{
int realLenOfCycle = indexOf(-1, cycles[i]);
newCycles[i] = new int[realLenOfCycle];
for (int j = 0; j < newCycles[i].length; j++)
{
newCycles[i][j] = cycles[i][j];
}
}
return newCycles;
}
public int indexOf(int element, int[] array)
{
int index = -1;
for (int i = 0; i < array.length; i++)
{
if (array[i] == element)
return i;
}
return index;
}
public boolean arrayHasCycled(int[] array, int[][] cycles)
{
for (int i = 0; i < array.length; i++)
{
boolean cycleHasValue = false;
for (int j = 0; j < cycles.length; j++)
{
for (int k = 0; k < cycles[j].length; k++)
{
if (cycles[j][k] == array[i])
cycleHasValue = true;
}
}
if (!cycleHasValue)
return false;
}
return true;
}
public void pushForward(int [] array)
{
int lastElement = array[array.length - 1];
for (int i = array.length - 1; i > 0; i--)
{
array[i] = array[i - 1];
}
array[0] = lastElement;
}
}
Output:
[0]
[1, 4, 7, 6]
[2]
[3, 8, 5, 9]
From what I understand, you're asked us to create a code which executes the following algorithm:
Create a one-dimensional array of integers, array
For each element in that array, nextElement do the following:
Create a new one-dimensional array, currCycle that will be added to a two-dimensional array, cycles.
Set the first element of that array to nextElement.
nextElement then becomes array[nextElement]
If nextElement is already in currCycle, continue onto the next element of array
Check if all the elements of array are in cycles, and if so, stop executing this algorithm.
Finally, return the cycles as a two-dimensional array with the index that was being used instead of the element at that index, which is what the current array consists of. To accomplish this, just cyclically (in the normal sense) push each element of the array forward one index.
This doesn't follow your examples exactly, but I think you may have malformed your examples, for instance:
An example: [0, 4, 2, 8, 7, 9, 1, 6, 5, 3]
would be these cycles : [0] [4, 8, 5, 7, 6, 9, 3, 2] [1]
and return this: [0], [1], [2, 4, 8, 5, 7, 6, 9, 3]
The first element 0 is 0, so when you get 0, it's already in the current cycle, so go to the next element, the element at index 1, which is 4. Once you're at 4 go to the fourth element, which is 7 not 8!
0 1 2 3 4
[0, 4, 2, 8, 7...

Categories

Resources