Compute sets of size n given an array - java

I'm not sure if my question title makes sense or even if I completely know what I'm trying to get at, but say you are given some letters in an array, and a number n:
char[] arr = ['a','b'], n = 4
How can you compute all the permutations of size n?
aaaa
bbbb
abab
bbaa
aabb
... (and so on)
I can't figure out how to do this and would really appreciate some help. I guess why I'm confused is because the size you want to make (4) is greater than the number of elements in your array and I haven't seen that before.

One solution to your problem could be to create a recursive method that makes all permutations in the set (in this case a and b) and call it n times to form a string.

In pseudo code...
Recursive function that accepts a String parameter:
if the length is 4, add string to results
otherwise, loop over chars:
recursively call function with param + char
Start by calling function with a blank.

Try to see the question in a different way, say you are given n boxes, in every box you need to put a letter selected from array arr, since every letter in the array can be used more than once, so for every box you have as many choices as arr.length, to group all the boxes together, you'll have a total of arr.length ^ n permutations, a simple working example in java using recursion:
public class Test {
static List<String> res;
public static void main(String[] args){
char[] arr = {'a','b'};
int n = 4;
res = new ArrayList<>();
permutate(arr, new char[n], n, 0);
System.out.println("size = " + res.size());
System.out.println("permutations = " + Arrays.toString(res.toArray()));
}
static void permutate(char[] arr, char[] permutation, int n ,int idx){
if(idx == n){
res.add(new String(permutation));
return;
}
for(int i = 0; i < arr.length; i++){
permutation[idx] = arr[i];
permutate(arr, permutation, n, idx + 1);
}
}
}

Related

Finding an element in an array such that the index is equal to its value using binary search

I have an array in ascending order, consisting of positive integers and with condition duplicates are not allowed.In the array i must find m such that array[m]=m using binary search
I have used below code:
public class Main {
public static void main(String[] args) {
Scanner a = new Scanner(System.in);
int n = a.nextInt();
int arr[] = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = a.nextInt();
}
int result = binarysearch(arr,n);
if(result!=-1)
System.out.println(result);
else
System.out.println("NOT_FOUND");
}
public static int binarysearch(int[] array,int n){
int start=1,end=n;
while(start<=end){
int mid = (start+end)/2;
if(mid==array[mid-1])
return mid;
else if(mid<array[mid-1])
end=mid-1;
else
start=mid+1;
}
return -1;
}
Please note that the array is 1-indexed and not 0-indexed
The problem I am facing is when i try the following case : array={1,2,3,4,5}
the expected output is 1
but due to binary search the method returns 3 as Output.
Is there any workaround to bypass this type of cases?
Looking at the conditions: "I have an array in ascending order, consisting of positive integers and with condition duplicates are not allowed"
ascending order
positive integers
no duplicates
This problem has a trivial solution.
public static int binarysearch(int[] array,int n){
If(a[0] == 1) return 1;
else return -1;
}
Because if the first number in the array is not 1, the rest of the array would not have any value that is equal to its index.
Explanation:
Suppose the array has terms a1, a2, a3 ... an, where non of the terms are equal and aj < ak if j < k
The problem is essentially finding a term ai where ai = i
If a1 is not 1, it has to be greater than 1 according to condition #2.
By condition 1 and 3, a2 has to be greater than 2. Then, a3 has to be greater than 3, and so on. Term an has to be greater than n. Yielding no solution.
On the other hand, if a1 is 1, you have the term and you can return it.
Your code looks mostly correct, but you should not assume the array is already sorted when the user inputs it.
I think the real problem lies in understanding how binary search works. Binary search always starts in the middle of an array. Thus, if you provide the input {1, 2, 3, 4, 5}, you will always get 3 because the algorithm starts by searching in the middle and notices that the number 3 equals its index.
If your goal is to find the smallest integer m such that a[m] is equal to m, then you should not use binary search. Instead, you should start from the beginning of the array (since we assume it is sorted in ascending order) and use linear search:
for (int i = 0; i < n; ++i) {
if (a[i] == i) {
return i;
}
}
return -1;
Something like the above should give the intended result. (Note that the above uses 0-based index logic, but you should be able to tweak it as needed. Also, arrays in Java are always 0-indexed, so you may want to double-check that you understand the problem correctly.)

How to know the fewest numbers we should add to get a full array

recently I met a question like this:
Assume you have an int N, and you also have an int[] and each element in this array can only be used once time. And we need to design an algorithm to get 1 to N by adding those numbers and finally return the least numbers we need to add.
For example:
N = 6, array is [1,3]
1 : we already have.
2 : we need to add it to the array.
3 : we can get it by doing 1 + 2.
4: 1 + 3.
5 : 2 + 3.
6 : 1 + 2 + 3.
So we just need to add 2 to our array and finally we return 1.
I am thinking of solving this by using DFS.
Do you have some better solutions? Thanks!
Here's an explanation for why the solution the OP posted works (the algorithm, briefly, is to traverse the sorted existing elements, keep an accumulating sum of the preceding existing elements and add an element to the array and sum if it does not exist and exceeds the current sum):
The loop tests in order each element that must be formed and sums the preceding elements. It alerts us if there is an element needed that's greater than the current sum. If you think about it, it's really simple! How could we make the element when we've already used all the preceding elements, which is what the sum represents!
In contrast, how do we know that all the intermediate elements will be able to be formed when the sum is larger than the current element? For example, consider n = 7, a = {}:
The function adds {1,2,4...}
So we are up to 4 and we know 1,2,3,4 are covered,
each can be formed from equal or lower numbers in the array.
At any point, m, in the traversal, we know for sure that
X0 + X1 ... + Xm make the largest number we can make, call it Y.
But we also know that we can make 1,2,3...Xm
Therefore, we can make Y-1, Y-2, Y-3...Y-Xm
(In this example: Xm = 4; Y = 1+2+4 = 7; Y-1 = 6; Y-2 = 5)
Q.E.D.
I don't know if this is a good solution or not:
I would create a second array (boolean array) remembering all numbers I can calculate.
Then I would write a method simulating the adding of a number to the array. (In your example the 1, 3 and 2 are added to the array).
The boolean array will be updated to always remember which values (numbers) can be calculated with the added numbers.
After calling the add method on the initial array values, you test for every Number x ( 1 <= x <= N ) if x can be calculated. If not call the add method for x.
since my explanation is no good I will add (untested) Java code:
static int[] arr = {3,5};
static int N = 20;
//An Array remembering which values can be calculated so far
static boolean[] canCalculate = new boolean[N];
//Calculate how many numbers must be added to the array ( Runtime O(N^2) )
public static int method(){
//Preperation (adding every given Number in the array)
for(int i=0; i<arr.length; i++){
addNumber(arr[i]);
}
//The number of elements added to the initial array
int result = 0;
//Adding (and counting) the missing numbers (Runtime O(N^2) )
for(int i=1; i<=N; i++){
if( !canCalculate[i-1] ){
addNumber(i);
result++;
}
}
return result;
}
//This Method is called whenever a new number is added to your array
//runtime O(N)
public static void addNumber( int number ){
System.out.println("Add Number: "+(number));
boolean[] newarray = new boolean[N];
newarray[number-1] = true;
//Test which values can be calculated after adding this number
//And update the array
for(int i=1; i<=N; i++){
if( canCalculate[i-1] ){
newarray[i-1] = true;
if( i + number <= N ){
newarray[i+number-1] = true;
}
}
}
canCalculate = newarray;
}
Edit: Tested the code and changed some errors (but rachel's solution seems to be better anyway)
It is a famous problem from dynamic programming. You can refer to complete solution here https://www.youtube.com/watch?v=s6FhG--P7z0
I just found a possible solution like this
public static int getNum(int n, int[] a) {
ArrayList<Integer> output = new ArrayList<Integer>();
Arrays.sort(a);
int sum = 0;
int i = 0;
while(true) {
if (i >= a.length || a[i] > sum + 1) {
output.add(sum + 1);
sum += sum + 1;
} else {
sum += a[i];
i++;
}
if (sum >= n) {
break;
}
}
return output.size();
};
And I test some cases and it looks correct.
But the one who write this didn't give us any hints and I am really confused with this one. Can anybody come up with some explanations ? Thanks!

Java Recursion on an ArrayList

I have an ArrayList of int.
The main program - calls a method to get a list of the sum of all (n member) combination of the members of the list. Where n can be anywhere between 2 - 6. E.g. Original List is {1,2,3,4,5}; Then the output should be {6, 7, 8, 8, 9, 10, 9, 10, 11, 12} where n = 3;
I am looking for the optimum way to do this. Right now, the way I have written the program (which is working) is without recursion. I have methods for all numbers i.e.
MyMethod2 -- gives me all the sum of 2 member combinations of MyArrayList
MyMethod3 -- gives me all the sum of 3 member combinations of MyArrayList
MyMethod4 -- gives me all the sum of 4 member combinations of MyArrayList
......
So, you can see that there is a lot of duplicate set of codes.
Also the way the program has currently been written (e.g. My Method3):
MyMethod3
ArrayList<Integer> sum = new ArrayList<Integer>();
for (i = 0; i < MyArrayList.size(); i++){
for (j = i + 1; j < MyArrayList.size(); j++){
for (k = j + 1; k < MyArrayList.size(); k++){
int total = MyArrayList.get(i) + MyArrayList.get(j) + MyArrayList.get(k);
sum.add(total);
}
}
}
return sum;
The MyMethod for n = 6, can become pretty long. Also "n" can change in the future.
Is there a better way to do this using recursion to minimize duplicate code, and using the number n as a variablefor the method call. Is there a standard package in Java that can help with recursion.
Adding the Code based on #Maertin suggestion - which worked for me
ArrayList<Integer> myArray = new ArrayList<Integer>();
myArray.add(5);
myArray.add(6);
myArray.add(4);
myArray.add(2);
myArray.add(1);
ArrayList<Integer> finalSumArray = combineTwoArrayList(3, myArray, myArray);
public static ArrayList<Integer> combineTwoArrayList(int n, ArrayList<Integer> origArray, ArrayList<Integer> finalSumArray) {
if (n == 1) return finalSumArray;
ArrayList<Integer> finalSumArray = new ArrayList<Integer>();
for (int i = 0; i < sumArray.size() - 1; i++){
for (int j = i + 1; j < origArray.size(); j++){
finalSumArray.add(sumArray.get(i) + origArray.get(j));
}
}
--n;
return combineTwoArrayList(n, origArray, finalSumArray);
}
You are correct in wanting to do this via recursion, because now, instead of having three separate methods, you could have one method with a parameter n for n-member combinations.
public int nCombinationSum( int n, int i, ArrayList<Integer> arr, ArrayList<Integer> sumArr) {
/* Gets n-combination sums and puts into sumArr
Input: n consecutive element combination, current index i in arr, and output ArrayList
Output: Gets n consecutive element combinations in arr from index i to index (i + n) and puts into sumArr
*/
//**BASE CASE**
//if index out of arr bounds
if( i + n > arr.size() )
return 0;
//**RECURSIVE CASE**
else {
//sum of values in arr from i to (i + n)
int currComboSum = 0;
for( int j = 0; j < n; j++ )
currComboSum += arr.get(j);
//adding sum to next element in resultant array
sumArr.add( currComboSum );
return nCombinationSum( n, i + 1, arr, sumArr );
}
}
USAGE
In your main method, you can call nCombinationSum and provide it with the kind of combination (n), starting index (in your case, 0), and arrayList (arr), and the arrayList you want to append the sums in (sumArr).
This also has the potential added benefit of allowing you to add any n-combination sum starting from a certain index. If you would like, you could add an end index as well, but this is fairly extended as it is.
EDIT: Please edit your question to reflect that you want the result to be an arrayList of sums, rather than the total sum. It is not clear right now.
Basically, what you want to do with recursion, in general, is to set a base case and a recursive case.
Your base case would be if your index is out of bounds, because you're going to call all elements from index i to i + n.
For the recursive case, use the algorithm below to account for each element in arr, then just keep returning the function with the next index value, and the function will continue running until it is out of bounds.
Algorithm
Getting sum of n-combination elements
Appending that sum into resultant array sumArr
Feel free to refer to the code above for reference.
You can use recursion. Basically, you should have only two for loops. (which is the code for two member combinations). When you compute 'total', pass each 'total' value to an ArrayList MyArrayList2. Now for MyMethod3, you use the elements of MyArrayList2 and the original ArrayList and find new 'total' values again and pass that to MyArrayList3. For MyMethod4, you use the elements of MyArrayList3 and the original ArrayList and find new 'total' values again and pass that to MyArrayList4.... ....

(Java) Method to find number divisible by a number and add to array to be print out

I want to make a method to find a number divisible by a number and add those numbers to an array to be printed out later when I call the method.
I made it to this point:
int [] divider(int n) {
int [] result = new int[20];
for (int i = 0; i <= n; i++) {
if (n%i == 0)
result = result[i];
}
return result;
}
I know it's wrong at many points, but I tried. This is the two thing I know I need to do, but I don't know how:
I know that I have the calculate how many numbers that divisible by a number first to know how big of an array to create. The problem is I know how to find how many number there are, but I don't know how to use that number to create an array by itself in the method.
After that I need to find what is those numbers in which it can divide by another number. This one I could do it, but I don't know how to add these result into an array to print out later.
These are what I know up until now. Please help. Thank you.
Here is the test:
public static void main(String[] args) {
Integer [] arr = divider(60);
for (Integer integer : arr) {
System.out.println(integer);
}
}
You should finish your loop with "n/2" because second max divider of "n" must be "n/2": i.e: second max divider of 60 is 30. and "i" must start with "1" because you can not divide a number with "0". After loop finihed we should add "n" into the list because max divider of "n" is "n".
static Integer [] divider(int n) {
List<Integer> resultList = new ArrayList<Integer>();
Integer [] result;
for (int i = 1; i <= n/2; i++) {
if (n%i == 0)
resultList.add(i);
}
resultList.add(n);
result = resultList.toArray(new Integer[resultList.size()]);
return result;
}
This can be done without a List since you can bound the number of numbers that divide your input n. The most trivial way to do it is to say that n cannot have more than n dividers. A more clever bound is sqrt(n). You wanted a size for your array ? Here it is : sqrt(n) + 1 (+1 for a perfect square).
At the end of the method, you can count the actual number of dividers and copy them into a new array. This method may be less efficient than using a List, but if you are limited to arrays this is the way to go.
you can try to add them to a ArrayList instead, for ArrayList you don't need to know the size before hand, you can just add them as you go along, also for your look you don't have to look at all 1 to n-1 numbers.
if you can't change the definition of your method, then as below you can just add them to a new array. if you can change the definition then you can simply return the result.
int[] divider(int n) {
ArrayList<Integer> result=new ArrayList<Integer>();
for (int i = 1; i <= n/2; i++) { //only check for half of the numbers
if (n%i == 0)
result = result[i];
}
int[] a=new int[result.size()];
for(int i=0;i<a.length;i++){
a[i]=results.get(i);
}
return a;
}

recursive method for flipping card

in java - if i have an index card with the letter C written on side, and S on the other. how do i write a recursive method that print each sessoin of dropping the cards with C's and S's. for example: if i drop it 4 times,all possible ways to drop it ara as follows in this specific order:
SCSC
SCSS
SSCC
SSCS
SSSC
SSSS
It's actually rather simple:
public void flip(List<String> items, int length, String prefix)
{
if (prefix.length() == length) {
items.add(prefix);
return;
}
increments(items, length, prefix + 'C');
increments(items, length, prefix + 'S');
}
As you can see, there are two recursive calls, one for the 'C' character and one for the 'S' character, and the recursion base case is when the prefix length is the length specified (4, in your case)
Call like so:
List<String> inc = new LinkedList<>();
increments(inc, 4, "");
for (String s : inc)
System.out.println(s);
Which outputs:
CCCC
CCCS
CCSC
CCSS
CSCC
CSCS
CSSC
CSSS
SCCC
SCCS
SCSC
SCSS
SSCC
SSCS
SSSC
SSSS
This method can easily be generalised for any array of characters:
public void increments(List<String> items, int length,
String prefix, char[] chars)
{
if (prefix.length() == length) {
items.add(prefix);
return;
}
for (char c : chars)
increments(items, length, prefix + c, chars);
}
List<String> inc = new LinkedList<>();
increments(inc, 4, "", new char[] {'C', 'S'});
for (String s : inc)
System.out.println(s);
This yields the same output.
Note: this method has a high complexity, O(pow(chars.length, length)), so attempting to run it with a large input size will take a (very) long time to complete.
Integer.toBinaryString(int) Approach
As requested:
public void increments_ibs(List<String> items, int n, int i)
{
if (i >= Math.pow(2, n))
return;
String bs = Integer.toBinaryString(i);
while (bs.length() < n)
bs = "0" + bs;
items.add(bs.replaceAll("0", "C").replaceAll("1", "S"));
increments_ibs(items, n, i+1);
}
This is essentially an iterative algorithm written recursively.
So this problem is actually a lot simpler if you realize that the card flipping is actually just counting upwards by one in binary.
With that in mind, you can just keep track of an X bit long number (where X is the number of cards you want to keep track of) and then print the cards by checking to see where there are 1's (S) or 0's (C).
After you do that, check to see if all of the positions have 1's. If they do, exit recursion. If they don't, add one to the number and run the function again.
Edit
If you know the number of bits in the number beforehand (something easy enough to calculate) you could use bit shifting (>> will be the best here). So for instance, you could have a quick for loop to go through the number and check each position.
int cardTracker = 0b0110; //this is 6 in decimal
char[] toPrint = new char[4];
//The 4 here is the length of the binary number
for(int i = 0; i < 4; i++)
{
//This if statement checks if the last number is 0 or 1
if((cardTracker >> ((4 - 1) - i) % 2 == 0)
{
toPrint[i] = 'C';
}
else
{
toPrint[i] = 'S';
}
}
The above will print the following if you were to print the contents of toPrint.
CSSC
Hopefully you can use the above and adapt it to your code for the recursive problem.

Categories