Recursion - Adding the subset of an array - java

I'm trying to decide if the sum of subset is a set num or not)...
I've read through most of the questions so far here on stackoverflow and have come up with nothing. I think the issue I'm finding is that I want to add together the elements in the combitorial subsets created. All together this should be done recursively. With the current code I have, I'm getting a stackoverflow error for recursion. (ironic)
So to clarify:
int[] array = {1,2,3,4,5};
the subset would be the size of say 2 and combinations would be
{1,2},{1,3},{1,4},{1,5},{2,3},{2,4},{2,5},{3,4},{3,5},{4,5}
from this data I want to see if the subset say... equals 6, then the answers would be: {1,5} and {2,4} leaving me with true as a answer. In respect to the signature I would like to keep it the same because it corresponds with another method (outside of the issue because it only sends the array, n, and num to the method)
public static boolean subset(int[] array, int n, int num) {
int count = 0;
int sum = 0;
int[] subarray = new int[n];
int[] temp = new int[array.length - 1];
int[] copy = array;
subarray[count] = array[0];
for (int i = 0; i < n; i++) {
subarray[count] = array[i];
count++;
System.arraycopy(array, i, temp, 0, n);
}
for (int j = 0; j < subarray.length; j++) {
sum += subarray[j];
if (sum == num)
return true;
}
subset(copy, n, goal);
return false;
}

Not an answer but a plausible idea for one?
for (int i = 0; i < array.length; i++) {
// New sublist to store values from 0 to i
int[] list = new int[array.length - 1];
for (int j = 0; j < array.length; j++) {
list[j] = array[j+1];
}
// Here you call this recursively with your Parent list from i+1
// index and working list from 0 to i
subsetSum(list, n, goal);
}
int sum = 0;
for (int i = 0; i < array.length; i++) {
sum += array[i];
}
if (sum == goal) {
return true;
}
return false;

Related

Remove an Element in Array on Leet code. I am getting an error of getting incompatible types and I dont know whats wrong

Here is the question:
Given an integer array nums and an integer val, remove all
occurrences of val in nums in place. The relative order of the
elements may be changed.
Since it is impossible to change the length of the array in some
languages, you must instead have the result be placed in the first
part of the array nums.
More formally, if there are k elements after removing the duplicates,
then the first k elements of nums should hold the final result. It
does not matter what you leave beyond the first k elements.
Return k after placing the final result in the first k slots of
nums.
Do not allocate extra space for another array. You must do this by
modifying the input array in-place with O(1) extra memory.
I've tried to remove the given target val by shifting the value to the end of the array index by iteration of nums.length-1 every time the val is found in the given array. I just want to know what's wrong with my approach.
Below is the code I've tried:
class Solution {
public int removeElement(int[] nums, int val) {
for (int i = 0; i < nums.length; i++) {
if (val == nums[i]) {
for (int j = i; j < nums.length - 1; j++) {
nums[j + 1] = nums[j];
}
break;
}
}
return nums;
}
}
Your algorithm correctly would be the following. The error was returning the array, but that was changed in-situ. You should have returned the new reduced length.
public int removeElement(int[] nums, int val) {
int k = nums.length;
for (int i = 0; i < k; i++) {
if (val == nums[i]) {
--k;
//for (int j = i; i < k; j++) {
// nums[j] = nums[j + 1];
//}
System.arraycopy(nums, i+1, nums, i, k-i);
--i; // Check the new nums[i] too
}
}
return k;
}
The for-j loop can be replaced with System.arraycopy (which handles overlapping of the same array too).
Or:
public int removeElement(int[] nums, int val) {
int k = 0;
for (int i = 0; i < n; i++) {
if (val != nums[i]) {
nums[k] = nums[i];
++k;
}
}
return k;
}
This is my code in leetcode. Hope will help you
class Solution {
public int removeElement(int[] nums, int val) {
ArrayList<Integer> list = new ArrayList<>();
for(int i=0;i<nums.length;i++){
if(nums[i]!=val){
list.add(nums[i]);
}
}
for(int i=0;i<list.size();i++){
nums[i]= list.get(i);
}
return list.size();
}
}

JAVA - Compare two arrays and create a new array with only the unique values from the first

I have to solve an exercise with the following criteria:
Compare two arrays:
int[] a1 = {1, 3, 7, 8, 2, 7, 9, 11};
int[] a2 = {3, 8, 7, 5, 13, 5, 12};
Create a new array int[] with only unique values from the first array. Result should look like this: int[] result = {1,2,9,11};
NOTE: I am not allowed to use ArrayList or Arrays class to solve this task.
I'm working with the following code, but the logic for the population loop is incorrect because it throws an out of bounds exception.
public static int[] removeDups(int[] a1, int[] a2) {
//count the number of duplicate values found in the first array
int dups = 0;
for (int i = 0; i < a1.length; i++) {
for (int j = 0; j < a2.length; j++) {
if (a1[i] == a2[j]) {
dups++;
}
}
}
//to find the size of the new array subtract the counter from the length of the first array
int size = a1.length - dups;
//create the size of the new array
int[] result = new int[size];
//populate the new array with the unique values
for (int i = 0; i < a1.length; i++) {
int count = 0;
for (int j = 0; j < a2.length; j++) {
if (a1[i] != a2[j]) {
count++;
if (count < 2) {
result[i] = a1[i];
}
}
}
}
return result;
}
I would also love how to solve this with potentially one loop (learning purposes).
I offer following soulution.
Iterate over first array, and find out min and max it's value.
Create temporary array with length max-min+1 (you could use max + 1 as a length, but it could follow overhead when you have values e.g. starting from 100k).
Iterate over first array and mark existed values in temorary array.
Iterate over second array and unmark existed values in temporary array.
Place all marked values from temporary array into result array.
Code:
public static int[] getUnique(int[] one, int[] two) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int i = 0; i < one.length; i++) {
min = one[i] < min ? one[i] : min;
max = one[i] > max ? one[i] : max;
}
int totalUnique = 0;
boolean[] tmp = new boolean[max - min + 1];
for (int i = 0; i < one.length; i++) {
int offs = one[i] - min;
totalUnique += tmp[offs] ? 0 : 1;
tmp[offs] = true;
}
for (int i = 0; i < two.length; i++) {
int offs = two[i] - min;
if (offs < 0 || offs >= tmp.length)
continue;
if (tmp[offs])
totalUnique--;
tmp[offs] = false;
}
int[] res = new int[totalUnique];
for (int i = 0, j = 0; i < tmp.length; i++)
if (tmp[i])
res[j++] = i + min;
return res;
}
For learning purposes, we won't be adding new tools.
Let's follow the same train of thought you had before and just correct the second part:
// populate the new array with the unique values
for (int i = 0; i < a1.length; i++) {
int count = 0;
for (int j = 0; j < a2.length; j++) {
if (a1[i] != a2[j]) {
count++;
if (count < 2) {
result[i] = a1[i];
}
}
}
}
To this:
//populate the new array with the unique values
int position = 0;
for (int i = 0; i < a1.length; i++) {
boolean unique = true;
for (int j = 0; j < a2.length; j++) {
if (a1[i] == a2[j]) {
unique = false;
break;
}
}
if (unique == true) {
result[position] = a1[i];
position++;
}
}
I am assuming the "count" that you implemented was in attempt to prevent false-positive added to your result array (which would go over). When a human determines whether or not an array contains dups, he doesn't do "count", he simply compares the first number with the second array by going down the list and then if he sees a dup (a1[i] == a2[j]), he would say "oh it's not unique" (unique = false) and then stop going through the loop (break). Then he will add the number to the second array (result[i] = a1[i]).
So to combine the two loops as much as possible:
// Create a temp Array to keep the data for the loop
int[] temp = new int[a1.length];
int position = 0;
for (int i = 0; i < a1.length; i++) {
boolean unique = true;
for (int j = 0; j < a2.length; j++) {
if (a1[i] == a2[j]) {
unique = false;
break;
}
}
if (unique == true) {
temp[position] = a1[i];
position++;
}
}
// This part merely copies the temp array of the previous size into the proper sized smaller array
int[] result = new int[position];
for (int k = 0; k < result.length; k++) {
result[k] = temp[k];
}
Making your code work
Your code works fine if you correct the second loop. Look at the modifications I did:
//populate the new array with the unique values
int counter = 0;
for (int i = 0; i < a1.length; i++) {
for (int j = 0; j < a2.length; j++) {
if (a1[i] == a2[j]) {
result[counter] = a1[i];
counter++;
}
}
}
The way I would do it
Now, here is how I would create a method like this without the need to check for the duplicates more than once. Look below:
public static int[] removeDups(int[] a1, int[] a2) {
int[] result = null;
int size = 0;
OUTERMOST: for(int e1: a1) {
for(int e2: a2) {
if(e1 == e2)
continue OUTERMOST;
}
int[] temp = new int[++size];
if(result != null) {
for(int i = 0; i < result.length; i++) {
temp[i] = result[i];
}
}
temp[temp.length - 1] = e1;
result = temp;
}
return result;
}
Instead of creating the result array with a fixed size, it creates a new array with the appropriate size everytime a new duplicate is found. Note that it returns null if a1 is equal a2.
You can make another method to see if an element is contained in a list :
public static boolean contains(int element, int array[]) {
for (int iterator : array) {
if (element == iterator) {
return true;
}
}
return false;
}
Your main method will iterate each element and check if it is contained in the second:
int[] uniqueElements = new int[a1.length];
int index = 0;
for (int it : a1) {
if (!contains(it, a2)) {
uniqueElements[index] = it;
index++;
}
}

After counting sort the result array has one more element (0) than the original one

So I have a problem, this method is supposed to sort an array of integers by using counting sort. The problem is that the resulting array has one extra element, zero. If the original array had a zero element (or several) it's fine, but if the original array didn't have any zero elements the result starts from zero anyway.
e.g. int input[] = { 2, 1, 4 }; result -> Sorted Array : [0, 1, 2, 4]
Why would this be happening?
public class CauntingSort {
public static int max(int[] A)
{
int maxValue = A[0];
for(int i = 0; i < A.length; i++)
if(maxValue < A[i])
maxValue = A[i];
return maxValue;
}
public static int[] createCountersArray(int[] A)
{
int maxValue = max(A) + 1;
int[] Result = new int[A.length + 1];
int[] Count = new int[maxValue];
for (int i = 0; i < A.length; i++) {
int x = Count[A[i]];
x++;
Count[A[i]] = x;
}
for (int i = 1; i < Count.length; i++) {
Count[i] = Count[i] + Count[i - 1];
}
for (int i = A.length -1; i >= 0; i--) {
int x = Count[A[i]];
Result[x] = A[i];
x--;
Count[A[i]] = x;
}
return Result;
}
}
You are using int[] Result = new int[A.length + 1]; which makes the array one position larger. But if you avoid it, you'll have an IndexOutOfBounds exception because you're supposed to do x-- before using x to access the array, so your code should change to something like:
public static int[] createCountersArray(int[] A)
{
int maxValue = max(A) + 1;
int[] Result = new int[A.length];
int[] Count = new int[maxValue];
for (int i = 0; i < A.length; i++) {
int x = Count[A[i]];
x++;
Count[A[i]] = x;
}
for (int i = 1; i < Count.length; i++) {
Count[i] = Count[i] + Count[i - 1];
}
for (int i = A.length -1; i >= 0; i--) {
int x = Count[A[i]];
x--;
Result[x] = A[i];
Count[A[i]] = x;
}
return Result;
}
Here you go: tio.run
int maxValue = max(A) + 1;
Returns the highest value of A + 1, so your new array with new int[maxValue] will be of size = 5;
The array Result is of the lenght A.lenght + 1, that is 4 + 1 = 5;
The first 0 is a predefinied value of int if it is a ? extends Object it would be null.
The leading 0 in your result is the initial value assigned to that element when the array is instantiated. That initial value is never modified because your loop that fills the result writes only to elements that correspond to a positive number of cumulative counts.
For example, consider sorting a one-element array. The Count for that element will be 1, so you will write the element's value at index 1 of the result array, leaving index 0 untouched.
Basically, then, this is an off-by-one error. You could fix it by changing
Result[x] = A[i];
to
Result[x - 1] = A[i];
HOWEVER, part of the problem here is that the buggy part of the routine is difficult to follow or analyze (for a human). No doubt it is comparatively efficient; nevertheless, fast, broken code is not better than slow, working code. Here's an alternative that is easier to reason about:
int nextResult = 0;
for (int i = 0; i < Count.length; i++) {
for (int j = 0; j < Count[i]; j++) {
Result[nextResult] = i;
nextResult++;
}
}
Of course, you'll also want to avoid declaring the Result array larger than array A.

How do I remove duplicates from two arrays?

I need to have an algorithm that changes values in one array if it is in the second array. The result is that the first array should not have any values that are in the second array.
The arrays are of random length (on average ranging from 0 to 15 integers each), and the content of each array is a list of sorted numbers, ranging from 0 to 90.
public void clearDuplicates(int[] A, int[] B){
for(int i = 0; i < A.length; i++){
for(int j = 0; j < B.length; j++)
if(A[i] == B[j])
A[i]++;
}
}
My current code does not clear all of the duplicates. On top of that it might be possible it will creat an index out of bounds, or the content can get above 90.
Although your question is not very clear, this might do the job. Assumptions:
The number of integers in A and B is smaller than 90.
The array A is not sorted afterwards (use Arrays.sort() if you wish to
fix that).
The array A might contain duplicates within itself afterwards.
public void clearDuplicates(int[] A, int[] B) {
// Initialize a set of numbers which are not in B to all numbers 0--90
final Set<Integer> notInB = new HashSet<>();
for (int i = 0; i <= 90; i++) {
notInB.add(i);
}
// Create a set of numbers which are in B. Since lookups in hash set are
// O(1), this will be much more efficient than manually searching over B
// each time. At the same time, remove elements which are in B from the
// set of elements not in B.
final Set<Integer> bSet = new HashSet<>();
for (final int b : B) {
bSet.add(b);
notInB.remove(b);
}
// Search and remove duplicates
for (int i = 0; i < A.length; i++) {
if (bSet.contains(A[i])) {
// Try to replace the duplicate by a number not in B
if (!notInB.isEmpty()) {
A[i] = notInB.iterator().next();
// Remove the added value from notInB
notInB.remove(A[i]);
}
// If not possible, return - there is no way to remove the
// duplicates with the given constraints
else {
return;
}
}
}
}
You can do it just by using int[ ] although it's a bit cumbersome. The only constraint is that there may not be duplicates within B itself.
public void clearDuplicates(int[] A, int[] B) {
//Number of duplicates
int duplicate = 0;
//First you need to find the number of duplicates
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < B.length; j++)
if (A[i] == B[j])
duplicate++;
}
//New A without duplicates
int[] newA = new int[A.length-duplicate];
//For indexing elements in the new A
int notDuplicate = 0;
//For knowing if it is or isn't a duplicate
boolean check;
//Filling the new A (without duplicates)
for (int i = 0; i < A.length; i++) {
check = true;
for (int j = 0; j < B.length; j++) {
if (A[i] == B[j]) {
check = false;
notDuplicate--;//Adjusting the index
}
}
//Put this element in the new array
if(check)
newA[notDuplicate] = A[i];
notDuplicate++;//Adjusting the index
}
}
public class DuplicateRemove {
public static void main(String[] args) {
int[] A = { 1, 8, 3, 4, 5, 6 };
int[] B = { 1, 4 };
print(clear(A, B));
}
public static int[] clear(int[] A, int[] B) {
int a = 0;
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < B.length; j++) {
if (A[i] == B[j]) {
a++;
for (int k = i; k < A.length - a; k++) {
A[k] = A[k + 1];
}
}
}
}
int[] C = new int[A.length - a];
for (int p = 0; p < C.length; p++)
C[p] = A[p];
return C;
}
public static void print(int[] A) {
for (int i = 0; i < A.length; i++)
System.out.println("Element: " + A[i]);
}
}
Here is an example.. I compiled and its working. For any question just let me know :)
maybe you should try the following code:
public void clear (int[] A, int[] B)
{
for (int i=0; i<A.length;i++)
{
for (int j=0; j<B.length; j++)
if(A[i]==B[j])
{
for (int k=i; k<A.length;k++)
A[k]=A[k+1];
j=B.length-1; //so that the cycle for will not be executed
}
}
}

Recursion - Combination with in array with no repetition in Java

So I know how to get the size of a combination - factorial of the size of the array (in my case) over the size of the subset of that array wanted. The issue I'm having is getting the combinations. I've read through most of the questions so far here on stackoverflow and have come up with nothing. I think the issue I'm finding is that I want to add together the elements in the combitorial subsets created. All together this should be done recursively
So to clarify:
int[] array = {1,2,3,4,5};
the subset would be the size of say 2 and combinations would be
{1,2},{1,3},{1,4},{1,5},{2,3},{2,4},{2,5},{3,4},{3,5},{4,5}
from this data I want to see if the subset say... equals 6, then the answers would be:
{1,5} and {2,4} leaving me with an array of {1,5,2,4}
so far I have this:
public static int[] subset(int[] array, int n, int sum){
// n = size of subsets
// sum = what the sum of the ints in the subsets should be
int count = 0; // used to count values in array later
int[] temp = new temp[array.length]; // will be array returned
if(array.length < n){
return false;
}
for (int i = 1; i < array.length; i++) {
for (int j = 0; j < n; j++) {
int[] subset = new int[n];
System.arraycopy(array, 1, temp, 0, array.length - 1); // should be array moved forward to get new combinations
**// unable to figure how how to compute subsets of the size using recursion so far have something along these lines**
subset[i] = array[i];
subset[i+1] = array[i+1];
for (int k = 0; k < n; k++ ) {
count += subset[k];
}
**end of what I had **
if (j == n && count == sum) {
temp[i] = array[i];
temp[i+1] = array[i+1];
}
}
} subset(temp, n, goal);
return temp;
}
How should I go about computing the possible combinations of subsets available?
I hope you will love me. Only thing you have to do is to merge results in one array, but it checks all possibilities (try to run the program and look at output) :) :
public static void main(String[] args) {
int[] array = {1, 2, 3, 4, 5};
int n = 2;
subset(array, n, 6, 0, new int[n], 0);
}
public static int[] subset(int[] array, int n, int sum, int count, int[] subarray, int pos) {
subarray[count] = array[pos];
count++;
//If I have enough numbers in my subarray, I can check, if it is equal to my sum
if (count == n) {
//If it is equal, I found subarray I was looking for
if (addArrayInt(subarray) == sum) {
return subarray;
} else {
return null;
}
}
for (int i = pos + 1; i < array.length; i++) {
int[] res = subset(array, n, sum, count, subarray.clone(), i);
if (res != null) {
//Good result returned, so I print it, here you should merge it
System.out.println(Arrays.toString(res));
}
}
if ((count == 1) && (pos < array.length - 1)) {
subset(array, n, sum, 0, new int[n], pos + 1);
}
//Here you should return your merged result, if you find any or null, if you do not
return null;
}
public static int addArrayInt(int[] array) {
int res = 0;
for (int i = 0; i < array.length; i++) {
res += array[i];
}
return res;
}
You should think about how this problem would be done with loops.
for (int i = 0; i < array.length - 1; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[i] + array[j] == sum) {
//Add the values to the array
}
}
}
Simply convert this to a recursive code.
The best way I can think to do this would be to have each recursive call run on a subset of the original array. Note that you don't need to create a new array to do this as you are doing in your code example. Just have a reference in each call to the new index in the array. So your constructor might look like this:
public static int[] subset(int[] array, int ind, int sum)
where array is the array, ind is the new starting index and sum is the sum you are trying to find

Categories

Resources