I'm working on a problem that asks me to "Write a method that returns all of the subsets of the set formed by the integers 1 to N where N is passed to the method." If I pass N = 3 to the method my output should look like [[0], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]]. My current output is [[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]. Is there a way for me to print out the desired range like doing Arrays.copyOfRange() for the ArrayList? or is there another way of getting the subset with my desired output?;
import java.util.ArrayList;
import java.util.HashSet;
public class HW3 {
public static void main(String[] args) {
System.out.println(powerset(3));
}
public static ArrayList<HashSet<Integer>> powerset(int N) {
ArrayList<HashSet<Integer>> arrayList = new ArrayList<HashSet<Integer>>();
HashSet<Integer> arrayListNew = new HashSet<Integer>();
for (int i = 0; i <= N; i++)
arrayListNew.add(i);
for (int i = 0; i < (int) Math.pow(2, N); i++)
arrayList.add(arrayListNew);
return arrayList;
}
}
"Is there a way for me to print out the desired range like doing Arrays.copyOfRange() for the ArrayList?"
yes, use sublist() read more here
However, you don't need that for your question. The algorithm you are looking for should look sth like this
//1st for loop iterate through all the possible sizes for the hash set
for(){
//2nd for loop generate all possible combinations given the size
for(){
}
}
//might need to add the [0] urself at the end
public class HW3 {
static void printSubsets(int set[]) {
int n = set.length;
for (int i = 0; i < (1 << n); i++) {
System.out.print("{ ");
for (int j = 0; j < n; j++)
if ((i & (1 << j)) > 0)
System.out.print(set[j] + " ");
System.out.println("}");
}
}
public static void main(String[] args) {
int n = 3;
int[] set = new int[n+1];
for(int i = 0; i<=n; i++){
set[i]=i;
}
printSubsets(set);
}}
The total number of subsets of any given set is equal to 2^ (no. of elements in the set). If we carefully notice it is nothing but binary numbers from 0 to 7 which can be shown as below:
000
001
010
011
100
101
110
111
Starting from right, 1 at ith position shows that the ith element of the set is present as 0 shows that the element is absent. Therefore, what we have to do is just generate the binary numbers from 0 to 2^n – 1, where n is the length of the set or the numbers of elements in the set.
Time complexity: O(n * (2^n)) as the outer loop runs for O(2^n) and the inner loop runs for O(n).
The more suitable way to do this is Backtracking
public class BacktrackTest {
public static void main(String[] args) {
powerset(3);
}
public static void powerset(int num) {
if (num >= 10 || num < 1) {
throw new IllegalArgumentException();
}
int[] chs = new int[num];
for (int i = 1; i <= num; i++) {
chs[i - 1] = i;
}
List<List<Integer>> resultList = new ArrayList<>();
backtrack(0, chs, new ArrayList<>(), resultList);
Collections.sort(resultList, (a, b) -> {
int len1 = a.size();
int len2 = b.size();
return len1 - len2;
});
System.out.println(resultList);
}
public static void backtrack(int index, int[] chs, List<Integer> tempList, List<List<Integer>> resultList) {
for (int i = index; i < chs.length; i++) {
tempList.add(chs[i]);
resultList.add(new ArrayList<>(tempList));
backtrack(i + 1, chs, tempList, resultList);
tempList.remove(tempList.size() - 1);
}
}
}
Java Fiddle Demo
Output result:
Related
I have two arrays array a = [1, 2, 3, 4, 5] and array b = [6, 5, 4, 3, 2] and i am returning a array list which contains a count where i taking elements of array b and checking what elements of array a are greater than or equal to the each element of array b, and i am storing this in count varible and later adding each count to the list so the output will be list = [0, 1, 2, 3, 4], but the code i've written is lacking in the performance for larger sets of input and not giving supposed answer's in the expected way any idea of how can i improve my code to improve the performance
static List<Integer> giantArmy(int a[],int b[]){
List<Integer> list = new ArrayList<Integer>();
if (a.length == 1 && a[0] == 0) {
list.add(0);
return list;
}
int count = 0;
for (int i = 0; i < b.length; i++) {
for (int j = 0; j < a.length; j++) {
if (a[j] >= b[i]) {
count++;
}
}
list.add(count);
count = 0;
}
return list;
}
An implementation of Basil Bourque's comment.
This is O(n log n). (Sort is O(n log n) and binary search O(log n) repeated n times)
static List<Integer> giantArmy(int a[],int b[]){
int aLength = a.length;
List<Integer> result = new ArrayList<>();
Arrays.sort(a);
for (int i : b) {
int index = Arrays.binarySearch(a, i);
if (index < 0)
index = -index - 1;
result.add(aLength - index);
}
return result;
}
public static void main(String[] args) {
System.out.println(giantArmy(new int[] {1, 2, 3, 4, 5}, new int[] {6, 5, 4, 3, 2}));
}
output:
[0, 1, 2, 3, 4]
A binary search of n for the sorted a yields the number of elements of a whose number of elements to the right of the position found is greater than or equal to n.
[1 2 3 4 5]
(number of elements >= 6) = 0
x (number of elements >= 5) = 1
x x (number of elements >= 4) = 2
x x x (number of elements >= 3) = 3
x x x x (number of elements >= 2) = 4
x x x x x (number of elements >= 1) = 5
x x x x x (number of elements >= 0) = 5
static List<Integer> giantArmy(Integer a[],Integer b[]){
TreeSet<Integer> ts = new TreeSet<>();
List<Integer> aList = Arrays.asList(a);
ts.addAll(aList);
Integer[] count = new Integer[b.length];
for (int i = 0; i < b.length; i++) {
Set<Integer> tail_set = ts.tailSet(b[i]);
count[i] = tail_set.size();
}
return Arrays.asList(count);
}
OUTPUT:
[0, 1, 2, 3, 4]
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));
}
I have the following input
int combinationCount = 3;
int arr[] = {1, 1, 2, 2, 3};
combinationCount is {1,2,3}, combinationCount defines the number of sequence of number. For Eg: combinationCount = 3 means {1,2,3} and combinationCount = 2 means {1,2}
Array is always sorted, I want to print the output as the number of combinations as follow
[1,2,3], [1,2,3], [1,2,3], [1,2,3] //I have to iterate the whole array as it is just logic for a problem
Output Explanation (I want to print values, not index):
This is just an explanation of output which shows the index position of the value printed.
Index position of each value
[0, 2, 4], [0, 3, 4], [1, 2, 4], [1, 3, 4]
Example 2
int combinationCount = 2; // means combination is {1,2}
int arr[] = {1, 2, 2};
Print: [1,2], [1,2]
Example 3
int combinationCount = 3; // means combination is {1,2,3}
int arr[] = {1, 1, 3};
Print nothing
The program which I written is as follow:
int combinationCount = 3;
int arr[] = {1, 1, 2, 2, 3};
List<Integer> list = new ArrayList<>();
int prev = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 1) {
prev = 1;
list = new ArrayList<>();
list.add(1);
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] == prev + 1) {
prev = arr[j];
list.add(arr[j]);
} else if (arr[j] > (prev + 1)) {
break;
}
}
if (list.size() == combinationCount) {
System.out.print(list + ",");
}
} else {
break;
}
}
Output coming as
[1,2,3],[1,2,3]
which is not correct
Somewhere I am missing loop and how optimized code we can write? Any suggestions pls. Kindly let me know for any concern.
You can use Cartesian Product. I have used this answer as reference.
public class Test {
public static List<List<Integer>> product(List<List<Integer>> lists) {
List<List<Integer>> result = new ArrayList<>();
int solutions = lists.stream().mapToInt(List::size).reduce(1, (a, b) -> a * b);
for (int i = 0; i < solutions; i++) {
int j = 1;
List<Integer> tempList = new ArrayList<>();
for (List list : lists) {
tempList.add((Integer) list.get((i / j) % list.size()));
j *= list.size();
}
result.add(tempList);
}
return result;
}
public static void main(String[] args) {
int combinationCount = 2, count = 0;
int arr[] = {1, 1, 3};
Map<Integer, List<Integer>> map = new HashMap<>();
List<List<Integer>> combinations = new ArrayList<>();
for (Integer idx = 0; idx < arr.length; idx++) {
map.computeIfAbsent(arr[idx], k -> new ArrayList<>()).add(idx);
}
for (int i = 1; i <= combinationCount; i++) {
if (map.getOrDefault(i, null) != null)
count += 1;
}
if (count == combinationCount) {
List result = product(new ArrayList(map.values()));
System.out.println(result);
} else {
System.out.println("No combination found");
}
}
}
Output:
No combination found
I have the following code:
public static void nextPermutationArray(int[] v) {
int x = 1;
int y;
Random r = new Random();
while (x < v.length) {
y = x + r.nextInt(v.length - x);
int temp = v[x];
v[x] = v[y];
v[y] = temp;
x++;
}
}
public static void main(String[] args) {
int[] a = new int[]{0, 1, 2, 3};
nextPermutationArray(a);
System.out.println(Arrays.toString(a));
nextPermutationArray(a);
System.out.println(Arrays.toString(a));
nextPermutationArray(a);
System.out.println(Arrays.toString(a));
nextPermutationArray(a);
System.out.println(Arrays.toString(a));
}
The program returns me:
0321
0231
0231
0132
My question is: is there any way to edit the method nextPermutationArray to avoid random permutations like 0231. In other words, the method should return 4 unrepeatable elements.
You can store each permutation that has already been returned in a static variable of type int[][]. If you get a result that is already in the array, you can make another permutation. Repeat until you have a new permutation. But be careful, this can make an endless loop if you want to produce more permutations than possible!
This should print out all the permutation without storing them in a HashMap or a List
public static boolean nextPermutationArray(int[] a) {
int i = a.length - 2;
while (i >= 0 && a[i] >= a[i + 1]) {
i--;
}
if (i < 0) {
return false;
}
int j = a.length - 1;
while (a[i] >= a[j]) {
j--;
}
int t = a[i];
a[i] = a[j];
a[j] = t;
Collections.reverse(Arrays.asList(Arrays.copyOfRange(a, i + 1, a.length)));
return true;
}
it will return true until there is a premutation to use it run this code
public static void main(String[] args) {
int[] a = new int[]{0, 1, 2, 3};
do {
System.out.println(Arrays.toString(a));
} while (nextPermutationArray(a));
}
output is
[0, 1, 2, 3]
[0, 1, 3, 2]
[0, 2, 3, 1]
[0, 3, 2, 1]
[1, 3, 2, 0]
[2, 3, 1, 0]
[3, 2, 1, 0]
I have input stream of numbers coming like
1 3 5 6 5 6 7 43 54 3 2 ....
At any point of given time how to find the last five number ?
Or you could use a circular buffer:
private class CircularBuffer {
private int[] items;
private int index = 0;
private int size = 0;
public CircularBuffer(int size) {
items = new int[size];
}
public void add(int item) {
items[index] = item;
index = (index + 1) % items.length;
size = Math.min(size + 1, items.length);
}
public int get(int i) {
if (i < 0 || i >= size)
throw new IndexOutOfBoundsException();
return items[(index - size + i + items.length) % items.length];
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder("[");
for (int i = 0; i < size; ++i) {
builder.append(get(i));
builder.append(i < size - 1 ? ", " : "]");
}
return builder.toString();
}
}
Test code:
CircularBuffer b = new CircularBuffer(5);
for (int i = 1; i < 10; ++i) {
b.add(i);
System.out.println(b);
}
Output:
[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[2, 3, 4, 5, 6]
[3, 4, 5, 6, 7]
[4, 5, 6, 7, 8]
[5, 6, 7, 8, 9]
You could save them in a Stack which would be the easiest and 'best' way to do it inmho.
If you (for whatever reason) can't or don't want to use an Stack I would suggest you to implement the "push" method for Arrays:
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int[] numbers = new int[5];
while(true){ // as long as you expect numbers from your stream
push(numbers, sc.nextInt());
}
}
public static void push(int[] arr, int value){
for(int i = 1; i < arr.length; i++){
arr[i - 1] = arr[i];
}
arr[arr.length - 1] = value;
}
Assuming your Stream provides with you with Integers only, via STDIN, one per line - the numbers array now holds the last 5 inputs for you (or 0 as a default value in case less than 5 values arrived so far).
Greetings Tim