Recursion - Combination with in array with no repetition in Java - 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

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();
}
}

How to return an array with the indexes of a certain int from another array

I'm a beginner Java student and I have been trying to write a method that lists all indexes of a certain int within an array. What I've done so far is store the value of that int at its corresponding index within another array but the best I can do is set the values of all other indexes that are not equal to the original int to -1.
I think I need to store the value i within the array and delete all the -1s but I don't know how to do this. By the way, these values are -1 because all my arrays in this program contain ints that are between 0-100. What would I do if possible ints within this array could be any number?
Also surely there is an easier or more efficient way of doing this.
public static int[] maxValueIndex(int[] arr, int targetValue, int x) {
int[] maxValue = new int[x];
for (int i = 0; i < arr.length; i++) {
if (arr[i] == targetValue) {
maxValue[i] = arr[i];
} else {
maxValue[i] = -1;
}
}
return maxValue;
}
If I understood your query correctly then you want an array with all the indices i such that arr[i]==targetValue. We can achieve this efficiently using any dynamic data structure. Like, use an ArrayList and keep adding all the desired indices one by one then convert the List to an array and return it.
Something like this:
List<Integer> index = new ArrayList<Integer>();
for (int i = 0; i < arr.length; i++)
{
if (arr[i] == targetValue)
index.add( i );
}
int[] maxValue = index.stream().mapToInt(Integer::intValue).toArray();
return maxValue;
If it is required to use arrays only to resolve this task, it may take two passes to create a compacted array containing only valid indexes:
Find the number of matches, and then create and fill a compact array
public static int[] getTargetIndexes(int targetValue, int ... arr) {
int n = arr.length;
int targetCount = 0;
for (int i = 0; i < n; i++) {
if (arr[i] == targetValue) {
targetCount++;
}
}
int[] indexes = new int[targetCount];
for (int i = 0, j = 0; j <targetCount && i < n; i++) {
if (arr[i] == targetValue) {
indexes[j++] = i;
}
}
return indexes;
}
Create an array of the same length, fill it and then compact by using Arrays.copyOf:
public static int[] getTargetIndexes(int targetValue, int ... arr) {
int n = arr.length;
int[] indexes = new int[n];
int targetCount = 0;
for (int i = 0; i < n; i++) {
if (arr[i] == targetValue) {
indexes[i] = i;
targetCount++;
} else {
indexes[i] = -1;
}
}
for (int i = 0, j = 0; j < targetCount && i < n; i++) {
if (indexes[i] > -1) {
indexes[j++] = i;
}
}
return Arrays.copyOf(indexes, targetCount); // truncate bad indexes
}
Also, the signature of the method uses vararg to pass the input array as a sequence of int -- the vararg argument int ... arr should be the last one then.
If Stream API can be used, the task may be resolved conveniently in a declarative way:
public static int[] getTargetIndexes(int targetValue, int ... arr) {
return IntStream.range(0, arr.length) // get stream of indexes
.filter(i -> arr[i] == targetValue) // keep only matching indexes
.toArray(); // build output array
}

Remove duplicates in array, zero padding at end

I have a task, to remove duplicates in array, what by "remove" means to shift elements down by 1, and making the last element equal to 0,
so if I have int[] array = {1, 1, 2, 2, 3, 2}; output should be like:
1, 2, 3, 0, 0, 0
I tried this logic:
public class ArrayDuplicates {
public static void main(String[] args) {
int[] array = {1, 1, 2, 2, 3, 2};
System.out.println(Arrays.toString(deleteArrayDuplicates(array)));
}
public static int[] deleteArrayDuplicates(int[] array) {
for (int i = 0; i < array.length; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[i] == array[j]) { //this is for comparing elements
for (; i > 0; i--) {
array[j + 1] = array[j]; //this is for shifting
}
array[array.length - 1] = 0; //making last element equal to "0"
}
}
}
return array;
}
}
But it doesn't work.. Is anyone familiar with a right solution?
I appreciate your assistance and attention very much.
Your Code:
In short, the approach you have chosen calls for a third loop variable, k, to represent the index that is currently being shifted left by 1 position.
i - the current unique item's position
j - the current position being tested for equality with unique item at i
k - the current position being shifted left due to erasure at j
Suggestion:
A more efficient approach would be to eliminate the repetitive left shifting which occurs each time a duplicate is found and instead keep track of an offset based on the number of duplicates found:
private static int[] deleteArrayDuplicates(int[] array) {
int dupes = 0; // total duplicates
// i - the current unique item's position
for (int i = 0; i < array.length - 1 - dupes; i++) {
int idupes = 0; // duplicates for current value of i
// j - the current position being tested for equality with unique item at i
for (int j = i + 1; j < array.length - dupes; j++) {
if (array[i] == array[j]) {
idupes++;
dupes++;
} else if(idupes > 0){
array[j-idupes] = array[j];
}
}
}
if(dupes > 0) {
Arrays.fill(array, array.length-dupes, array.length, 0);
}
return array;
}
This has similar complexity to the answer posted by dbl, although it should be slightly faster due to eliminating some extra loops at the end. Another advantage is that this code doesn't rely on any assumptions that the input should not contain zeroes, unlike that answer.
#artshakhov:
Here is my approach, which is pretty much close enough to what you've found but using a bit fewer operations...
private static int[] deleteArrayDuplicates(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
if (array[i] == NEUTRAL) continue; //if zero is a valid input value then don't waste time with it
int idx = i + 1; //no need for third cycle, just use memorization for current shifting index.
for (int j = i + 1; j < array.length; j++) {
if (array[i] == array[j]) {
array[j] = NEUTRAL;
} else {
array[idx++] = array[j];
}
}
}
return array;
}
I just wrote the following code to answer your question. I tested it and I am getting the output you expected. If there are any special cases I may have missed, I apologize but it seemed to work for a variety of inputs including yours.
The idea behind is that we will be using a hash map to keep track if we have already seen a particular element in our array as we are looping through the array. If the map already contains that element- meaning we have already seen that element in our array- we just keep looping. However, if it is our first time seeing that element, we will update the element at the index where j is pointing to the element at the index where i is pointing to and then increment j.
So basically through the j pointer, we are able to move all the distinct elements to the front of the array while also making sure it is in the same order as it is in our input array.
Now after the first loop, our j pointer points to the first repeating element in our array. We can just set i to j and loop through the rest of the array, making them zero.
The time complexity for this algorithm is O(N). The space complexity is O(N) because of the hash table. There is probably a way to do this in O(N) time, O(1) space.
public static int[] deleteArrayDuplicates(int[] array) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
int j = 0;
for (int i = 0; i < array.length; i++) {
if (map.containsKey(array[i])) {
continue;
}
else {
map.put(array[i],1);
array[j] = array[i];
j++;
}
}
for (int i = j; i < array.length; i++) {
array[i] = 0;
}
return array;
}
Let me know if you have additional questions.
Spent a couple of hours trying to find a solution for my own, and created something like this:
public static int[] deleteArrayDuplicates(int[] array) {
for (int i = 0; i < array.length; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[j] == array[i]) { //this is for comparing elements
int tempIndex = j;
while (tempIndex + 1 < array.length) {
array[tempIndex] = array[tempIndex + 1]; //this is for shifting elements down/left by "1"
array[array.length - 1] = 0; //making last element equal to "0"
tempIndex++;
}
}
}
}
return array;
}
Code is without any API-helpers, but seems like is working now.
Try this:
public static void main(String[] args)
{
int a[]={1,1,1,2,3,4,5};
int b[]=new int[a.length];
int top=0;
for( int i : a )
{
int count=0;
for(int j=0;j<top;j++)
{
if(i == b[j])
count+=1;
}
if(count==0)
{
b[top]=i;
top+=1;
}
}
for(int i=0 ; i < b.length ; i++ )
System.out.println( b[i] );
}
Explanation:
Create an another array ( b ) of same size of the given array.Now just include only the unique elements in the array b. Add the elements of array a to array b only if that element is not present in b.
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class StackOverFlow {
public static void main(String[] args) {
int[] array = {1, 1, 2, 2, 3, 2};
Set<Integer> set=new HashSet<>();
for (int anArray : array) {
set.add(anArray);
}
int[] a=new int[array.length];
int i=0;
for (Integer s:set) {
a[i]=s;
i++;
}
System.out.println(Arrays.toString(a));
}
}
Hope this simple one may help you.
Make use of Set which doesn't allow duplicates.
We can use ARRAYLIST and Java-8 Streams features to get the output.
public static int[] deleteArrayDuplicates(int[] array) {
List<Integer> list = new ArrayList(Arrays.stream(array).boxed().distinct().collect(Collectors.toList()));
for (int i = 0; i < array.length; i++) {
if (i < list.size()) {
array[i] = list.get(i);
} else {
array[i] = 0;
}
}
return array;
}
OUTPUT
[1, 2, 3, 0, 0, 0]

Recursion - Adding the subset of an array

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;

Efficient way to count unique pairs in int array

This is my first post, hope it complies with posting guidelines of the site.
First of all a generic thanks to all the community: reading you from some months and learned a lot :o)
Premise: I'm a first years student of IT.
Here's the question: I'm looking for an efficient way to count the number of unique pairs (numbers that appear exactly twice) in a given positive int array (that's all I know), e.g. if:
int[] arr = {1,4,7,1,5,7,4,1,5};
the number of unique pairs in arr is 3 (4,5,7).
I have some difficulties in... evaluating the efficiency of my proposals let's say.
Here's the first code I did:
int numCouples( int[] v ) {
int res = 0;
int count = 0;
for (int i = 0 ; i < v.length; i++){
count = 0;
for (int j = 0; j < v.length; j++){
if (i != j && v[i] == v[j]){
count++;
}
}
if (count == 1){
res++;
}
}
return res/2;
}
This shoudn't be good cause it checks the whole given array as many times as the number of elements in the given array... correct me if I'm wrong.
This is my second code:
int numCouples( int[] v) {
int n = 0;
int res = 0;
for (int i = 0; i < v.length; i++){
if (v[i] > n){
n = v[i];
}
}
int[] a = new int [n];
for (int i = 0; i < v.length; i++){
a[v[i]-1]++;
}
for (int i = 0; i < a.length; i++){
if (a[i] == 2){
res++;
}
}
return res;
}
I guess this should be better than the first one since it checks only 2 times the given array and 1 time the n array, when n is the max value of the given array. May be not so good if n is quite big I guess...
Well, 2 questions:
am I understanding good how to "measure" the efficiency of the code?
there's a better way to count the number of unique pairs in a given array?
EDIT:
Damn I've just posted and I'm already swamped by answers! Thanks! I'll study each one with care, for the time being I say I don't get those involving HashMap: out of my knowledge yet (hence thanks again for the insight:o) )
public static void main(String[] args) {
int[] arr = { 1, 4, 7, 1, 5, 7, 4, 1, 5 };
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < arr.length; i++) {
Integer count = map.get(arr[i]);
if (count == null)
map.put(arr[i], 1);
else
map.put(arr[i], count + 1);
}
int uniqueCount = 0;
for (Integer i : map.values())
if (i == 2)
uniqueCount++;
System.out.println(uniqueCount);
}
Well, here's another answer to your's 2 questions:
am I understanding good how to "measure" the efficiency of the code?
There are various ways to measure efficiency of the code. First of all, people distinguish between memory efficiency and time efficiency. The usual way to count all these values is to know, how efficient are the building blocks of your algorithm. Have a look at the wiki.
For instance, sorting using quicksort would need n*log(n) operations. Iterating through the array would need just n operations, where n is number of elements in the input.
there's a better way to count the number of unique pairs in a given array?
Here's another solution for you. The complixity of this one would be: O(n*log(n)+n), where O(...) is Big O notation.
import java.util.Arrays;
public class Ctest {
public static void main(String[] args) {
int[] a = new int[] { 1, 4, 7, 1, 7, 4, 1, 5, 5, 8 };
System.out.println("RES: " + uniquePairs(a));
}
public static int uniquePairs(int[] a) {
Arrays.sort(a);
// now we have: [1, 1, 1, 4, 4, 5, 5, 7, 7]
int res = 0;
int len = a.length;
int i = 0;
while (i < len) {
// take first number
int num = a[i];
int c = 1;
i++;
// count all duplicates
while(i < len && a[i] == num) {
c++;
i++;
}
System.out.println("Number: " + num + "\tCount: "+c);
// if we spotted number just 2 times, increment result
if (c == 2) {
res++;
}
}
return res;
}
}
public static void main(String[] args) {
int[] arr = {1,4,7,1,7,4,1,5};
Map<Integer, Integer> counts = new HashMap<Integer,Integer>();
int count = 0;
for(Integer num:arr){
Integer entry = counts.get(num);
if(entry == null){
counts.put(num, 1);
}else if(counts.get(num) == 1){
count++;
counts.put(num, counts.get(num) + 1);
}
}
System.out.println(count);
}
int [] a = new int [] {1, 4, 7, 1, 7, 4, 1, 5, 1, 1, 1, 1, 1, 1};
Arrays.sort (a);
int res = 0;
for (int l = a.length, i = 0; i < l - 1; i++)
{
int v = a [i];
int j = i + 1;
while (j < l && a [j] == v) j += 1;
if (j == i + 2) res += 1;
i = j - 1;
}
return res;
you can use HashMap for easy grouping. here is my code.
int[] arr = {1,1,1,1,1,1,4,7,1,7,4,1,5};
HashMap<Integer,Integer> asd = new HashMap<Integer, Integer>();
for(int i=0;i<arr.length;i++)
{
if(asd.get(arr[i]) == null)
{
asd.put(arr[i], 1);
}
else
{
asd.put(arr[i], asd.get(arr[i])+1);
}
}
//print out
for(int key:asd.keySet())
{
//get pair
int temp = asd.get(key)/2;
System.out.println(key+" have : "+temp+" pair");
}
added for checking the unique pair, you can delete the print out one
//unique pair
for(int key:asd.keySet())
{
if(asd.get(key) == 2)
{
System.out.println(key+" are a unique pair");
}
}
after some time another solution, which should work great.
public getCouplesCount(int [] arr) {
int i = 0, i2;
int len = arr.length;
int num = 0;
int curr;
int lastchecked = -1;
while (i < len-1) {
curr = arr[i];
i2 = i + 1;
while (i2 < len) {
if (curr == arr[i2] && arr[i2] != lastchecked) {
num++; // add 1 to number of pairs
lastchecked = curr;
i2++; // iterate to next
} else if (arr[i2] == lastchecked) {
// more than twice - swap last and update counter
if (curr == lastchecked) {
num--;
}
// swap with last
arr[i2] = arr[len-1];
len--;
} else {
i2++;
}
i++;
}
return num;
}
i am not shure if it works, but it is more effective than sorting the array first, or using hashmaps....
A Java8 parallel streamy version which uses a ConcurrentHashMap
int[] arr = {1,4,7,1,5,7,4,1,5};
Map<Integer,Long> map=Arrays.stream(arr).parallel().boxed().collect(Collectors.groupingBy(Function.identity(),
ConcurrentHashMap::new,Collectors.counting()));
map.values().removeIf(v->v!=2);
System.out.println(map.keySet().size());
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int arr[9] = {1,4,7,1,5,7,4,1,5}; // given array
int length=9; // this should be given
int count=0;
map<int,int> m;
for(int i=0;i<length;i++)
m[arr[i]]++;
cout<<"List of unique pairs : ";
for(auto it=m.begin();it!=m.end();it++)
if(it->second==2)
{
count++;
cout<<it->first<<" ";
}
cout<<"\nCount of unique pairs(appears exactly twice) : "<<count;
return 0;
}
OUTPUT :
List of unique pairs : 4 5 7
Count of unique pairs(appears exactly twice) : 3
Time Complexity : O(N) where N is the number of elements in array
Space Complexity : O(N) total no. of unique elements in array always <=N
var sampleArray = ['A','B','C','D','e','f','g'];
var count = 0;
for(var i=0; i<=sampleArray.length; i++) {
for(var j=i+1; j<sampleArray.length; j++) {
count++;
console.log(sampleArray[i] , sampleArray[j]);
}
}
console.log(count);
This is the simple way I tried.

Categories

Resources