Generate Binary strings of given length and with a constraint - java

I am trying to write a logic where I want to generate a list of binary strings of given size n and also the string should have maximum of k bits set to 1.
Example:
If n = 3, k = 1 ==> the number of 1's can be 0 or 1.
Then the output should be 000, 001, 010, 100
Below is the logic I have used with the help of this link as a reference:
Here n is same as arr.length.
static void generateAllBinaryStrings(int n, int arr[], int i, List<String> res, int k) {
if (i == n) {
StringBuilder sb = new StringBuilder();
int count = 0;
for (int j = 0; j < arr.length; j++) {
int val = arr[j];
if (val == 1) {
count++;
}
sb.append(val);
}
if (count <= k) {
res.add(sb.toString());
}
return;
}
arr[i] = 0;
generateAllBinaryStrings(n, arr, i + 1, res, k);
arr[i] = 1;
generateAllBinaryStrings(n, arr, i + 1, res, k);
}
public static void main(String args[]) {
int n = 3;
int[] arr = new int[n];
int k = 1;
int i = 0;
List<String> res = new ArrayList<>();
generateAllBinaryStrings(n, arr, i, res, k);
System.out.println(res);// Prints [000, 001, 010, 100]
}
This code is working fine, but this logic generates all possible binary string then filters based on the number of 1's in the string.
Is there any less time complex algorithm for this problem.

The basic thing that comes into my mind while you are trying to generate the string with having this much data with you why cant you just have one more reference to your recursive call that tell how many 1 are there in you generated string as of the recursion in being called.
The method signature now might look like -
static void generateAllBinaryStrings(int n, int arr[], int i, List<String> res, int k,int currentCountOfOnes){
// Rest logic remains same , each time you don't have to check how many 1's
// are there as of the call made.
}
This might reduce complexity a bit more than what you have.
And one more obvious thing that you can think of is storing your previous called result (memorization -> that leads to a thought of dynamic programming)
Hope thoughts might have helped you.
Note : I could have coded all this but then there is no use of doing so. Try it out if you find it useful do let me know !!

I've come up with this:
static void generateAllBinaryStrings(StringBuilder sb, int n, Set<String> res, int k) {
int len = sb.length();
if (k == 0) {
repeat(sb, '0', n);
res.add(sb.toString());
sb.setLength(len);
} else {
for (int i = 0; i <= n; ++i) {
repeat(sb, '0', i);
if (i < n) {
sb.append('1');
generateAllBinaryStrings(sb, n-i-1, res, k-1);
} else {
res.add(sb.toString());
}
sb.setLength(len);
}
}
}
private static void repeat(StringBuilder sb, char c, int n) {
for (int j = 0; j < n; ++j) {
sb.append('0');
}
}
The idea is that you have k ones to place in a string of length n; so if k == 0, the only possible value is n zeroes. If k > 0, you can add n zeroes, or i zeros, i being anywhere between 0 and n-1, followed by a 1, recurse for the remaining space and k-1.

Related

Solving Project Euler 15 efficiency issue [duplicate]

I have the following programm calculating the binomial coefficient of two integers. But I want to change the programm, that it calculates and saves only the necessary coefficients for the solution.
The problem is that I have really no idea how to it, right now.
The Code
public static long binomialIteration(int n, int k)
{
if(k<0 || n<k)
{
return 0;
}
long[][] h= new long[n+1][n+1];
for(int i=0; i<=n; i++)
{
h[i][0]=h[i][i]=1;
}
for(int i=1;i<=n;i++)
{
for(int j=0; j<=i; j++)
{
h[i][j] = (j==0 ? 0: h[i-1][j-1]) + (i == j ? 0 : h[i-1][j]);
}
}
return h[n][k];
}
Do you want to keep your code afterall?
Because you can also compute the binominal coefficient recursively, which would reduce your function to these 4 lines:
static long binomi(int n, int k) {
if ((n == k) || (k == 0))
return 1;
else
return binomi(n - 1, k) + binomi(n - 1, k - 1);
}
What about this Code from this site
private static long binomial(int n, int k)
{
if (k>n-k)
k=n-k;
long b=1;
for (int i=1, m=n; i<=k; i++, m--)
b=b*m/i;
return b;
}
You don't say which coefficients youi need. If you need C(N,n) for some fixed N, you could translate the C code below, which uses a one dimensional array.
After the call, C[n] will hold the binomial coefficient C(N,n) for 0<=m<=N, as long as N is at most 66 -- if you need bigger N you will need to use an integral type with more bits.
static int64_t* pascals_triangle( int N)
{
int n,k;
int64_t* C = calloc( N+1, sizeof *C);
for( n=0; n<=N; ++n)
{ C[n] = 1;
k = n;
while( --k>0)
{ C[k] += C[k-1];
}
}
return C;
}

Codility PermCheck Solution isn't working on a few data sets

Trying to solve codility lessons for practice and working on this.
Written my code in Java and tested the code on a wide range of inputs, however the code fails for extreme_min_max, single and double in the codility test results.
Assumption given:
N is an integer within the range [1..100,000].
Each element of array A is an integer within the range [1..1,000,000,000].
Explanation of my code:
1. Sort the given array.
2. Iterate over each element in the array to find the difference between every consecutive pair. If the difference is not 1, Then its not a perm hence return 0. In case there is only one element in the array, return 1.
Can anyone please help me find out the bug(s) in my code?
My code:
public int solution(int[] A)
{
if(A.length == 1)
return 1;
Arrays.sort(A);
for (int i = 0; i < A.length-1; i++)
{
long diff = Math.abs(A[i] - A[i+1]);
if(diff!=1)
return 0;
}
return 1;
}
Here is simple and better implementation which runs in O(N) time complexity and takes O(N) space complexity.
public int solution(int[] A)
{
int size = A.length;
int hashArray[] = new int[size+1];
for (int i = 0; i < size; i++)
{
if(A[i]>size)
return 0;
else
hashArray[A[i]]+=1;
}
for(int i=1;i<=size;i++)
if(hashArray[i]!=1)
return 0;
return 1;
}
Try this in C# (Score 100%) :
using System;
using System.Linq;
class Solution {
public int solution(int[] A) {
if (A.Any(x => x == 0)) { return 0; }
var orderSelect = A.OrderBy(x => x).GroupBy(x => x);
if (orderSelect.Any(x => x.Count() > 1)) { return 0; }
var res = Enumerable.Range(1, A.Length).Except(A);
return res.Any() ? 0 : 1;
}
}
Pretty simple:
Your code doesn't check this condition:
A permutation is a sequence containing each element from 1 to N once, and only once.
Ensure that the first element after sorting is 1, and everything should work.
I'm not big on Java syntax, but what you want to do here is:
Create an array temp the length of A - initialized to 0.
Go over A and do temp[A[i]]++.
Go over temp, and if any place in the array is not 1, return false.
If duplicate exists - return 0 I have implemented with 100% pass
https://codility.com/demo/results/trainingWX2E92-ASF/
public static int permCheck(int A[]){
Set<Integer> bucket = new HashSet<Integer>();
int max = 0;
int sum=0;
for(int counter=0; counter<A.length; counter++){
if(max<A[counter]) max=A[counter];
if(bucket.add(A[counter])){
sum=sum+A[counter];
}
else{
return 0;
}
}
System.out.println(max+"->"+sum);
int expectedSum = (max*(max+1))/2;
if(expectedSum==sum)return 1;
return 0;
}
Here's my first 100% code.
I can't say if it's the fastest but it seems all correct -- watch the double OR ( || ) condition.
import java.util.Arrays;
class Solution
{
public int solution(int[] A)
{
int i = 0;
int size = A.length;
if ( size > 0 && size < 100001)
{
// Sort the array ascending:
Arrays.sort(A);
// Check each element:
for(i = 0; i < size; i++)
if ( A[i] > size || A[i] != (i + 1) )
return 0;
return 1;
}
return 0;
}
}
EDIT
Actually, we need not worry about valid first element data (i.e. A[i] > 0) because, after sorting, a valid perm array must have A[0] = 1 and this is already covered by the condition A[i] = i + 1.
The upper limit for array entries (> 1,000,000,000) is restricted further by the limit on the array size itself (100,000) and we must check for conformity here as there will be a Codility test for this. So I have removed the lower limit condition on array entries.
Below code runs and gave me a 100%, the time complexity is O(n):
private static int solution(int[] A) {
int isPermutation = 1; // all permutations start at 1
int n = A.length;
Arrays.sort(A);
if (n == 0) return 0; // takes care of edge case where an empty array is passed
for (int i = 0; i < n; i++) {
if (A[i] != isPermutation) { //if current array item is not equals to permutation, return 0;
return 0;
}
isPermutation++;
}
return 1;
}
100% score with complexity O(N)
public int solution(int[] A) {
int res = 1;
if (A.length == 1 && A[0]!=1)
return 0;
int[] B = new int[A.length];
for (int j : A) {
int p = j - 1;
if (A.length > p)
B[p] = j;
}
for (int i = 0; i < B.length - 1; i++) {
if (B[i] + 1 != B[i + 1]) {
res = 0;
break;
}
}
return res;
}

Permutations of a string with no duplicates

I read solutions to the problem of generating all the permutations of a string (solution).
Can anyone explain how perm2 is different from perm1? (I feel the only difference is that perm1 tries to put each element in the first position while perm2 in the last one)
// print N! permutation of the characters of the string s (in order)
public static void perm1(String s) { perm1("", s); }
private static void perm1(String prefix, String s) {
int N = s.length();
if (N == 0) System.out.println(prefix);
else {
for (int i = 0; i < N; i++)
perm1(prefix + s.charAt(i), s.substring(0, i) + s.substring(i+1, N));
}
}
// print N! permutation of the elements of array a (not in order)
public static void perm2(String s) {
int N = s.length();
char[] a = new char[N];
for (int i = 0; i < N; i++)
a[i] = s.charAt(i);
perm2(a, N);
}
private static void perm2(char[] a, int n) {
if (n == 1) {
System.out.println(a);
return;
}
for (int i = 0; i < n; i++) {
swap(a, i, n-1);
perm2(a, n-1);
swap(a, i, n-1);
}
}
Also, if some letters are the same in the string, then some permutations will be the same? The only way I can think of to prevent this is to save the result in a hashset so as to keep only one instance of a permutation. Is there a better solution?
I expect that the justification for the second solution is efficiency. It uses character arrays rather than String objects and swaps characters at each step rather than creating a new String via concatenation.
In terms of functionality the only difference between the two solutions is the order in which the results will be output.
You are correct that this does not guarantee unique solutions if there are some duplicate characters in the input. Storing the results and checking uniqueness (by using a Set or directly via contains) would be the easiest way to avoid this if required.
An alternative, in the second solution, would be to check if a character has already been handled. This would avoid the overhead of storing a result set (which could be significant for long strings).
In second perm2 function:
if (n == 1) {
System.out.println(a);
return;
}
for (int i = n; i < a.length; i++) {
if (a[i] == a[n-1])
return;
}
for (int i = 0; i < n; i++) {
boolean duplicate = false;
for (int j = 0; !duplicate && j < i; j++)
duplicate = a[i] == a[j];
if (!duplicate) {
swap(a, i, n-1);
perm2(a, n-1);
swap(a, i, n-1);
}
}

issues with codingbat maxMirror exercise

So basically, I've been going through these codingBat problems, and when I get really stuck, I usually check out the solution and trace the logic and that has helped me not get stuck on later problems which used similar ideas.
This max mirror problem is not like the others for me personally; I have no idea how to actually write the code to solve it, even forming the algorithm is kind of tricky for me
We'll say that a "mirror" section in an array is a group of contiguous elements such that somewhere in the array, the same group appears in reverse order. For example, the largest mirror section in {1, 2, 3, 8, 9, 3, 2, 1} is length 3 (the {1, 2, 3} part). Return the size of the largest mirror section found in the given array.
maxMirror({1, 2, 3, 8, 9, 3, 2, 1}) → 3
maxMirror({1, 2, 1, 4}) → 3
maxMirror({7, 1, 2, 9, 7, 2, 1}) → 2
Now, in terms of the algorithm, I sort of want to say something like, if we start by checking if the whole array is a mirror and then decrease the checked area size by 1 if it's not. But in terms of the pseudocode and the real code I have no idea.
My go to solution in cases like this where what your code should be doing is always doing it manually, then figuring out the essence of how it is that I am tackling the solution.
For this problem I found myself looking at possible subsets of the original array, then looking backwards through the original array to see if I can find that same subset again.
Next, I translated that into pseudocode,
for each segment in nums
check if nums contains segment backwards
Repeated, but this time with more implementation details worked out.
for each segment in nums, starting with the largest
reverse the segment
check if nums contains reversed segment
if it does, return the size of that segment
Next, find some likely candidates for methods in the pseudocode and write them. I chose to do this for "reverse" and "contains":
private int[] reverse(int[] nums) {
int[] rtn = new int[nums.length];
for (int pos = 0; pos < nums.length; pos++) {
rtn[nums.length - pos - 1] = nums[pos];
}
return rtn;
}
private boolean contains(int[] nums, int[] segment) {
for (int i = 0; i <= nums.length - segment.length; i++) {
boolean matches = true;
for (int j = 0; j < segment.length; j++) {
if (nums[i + j] != segment[j]) {
matches = false;
break;
}
}
if (matches) return true;
}
return false;
}
Finally, implement the rest:
public int maxMirror(int[] nums) {
for (int window = nums.length; window > 0; window--) {
for (int pos = 0; pos <= nums.length - window; pos++) {
int[] segment = new int[window];
for (int innerpos = 0; innerpos < window; innerpos++) {
segment[innerpos] = nums[pos + innerpos];
}
segment = reverse(segment);
if (contains(nums, segment)) {
return window;
}
}
}
return 0;
}
My irrelevant two cents....
public int maxMirror(int[] nums) {
// maximum mirror length found so far
int maxlen= 0;
// iterate through all possible mirror start indexes
for (int front = 0; front < nums.length; front++) {
// iterate through all possible mirror end indexes
for (int back = nums.length - 1; back >= front; back--) {
// this inner for-loop determines the mirror length given a fixed
// start and end index
int matchlen = 0;
Boolean match = (nums[front] == nums[back]);
// while there is a match
// 1. increment matchlen
// 2. keep on checking the proceeding indexes
while (match) {
matchlen++;
int front_index = front + matchlen;
int back_index = back - matchlen;
// A match requires
// 1. Thee indexes are in bounds
// 2. The values in num at the specified indexes are equal
match =
(front_index < nums.length) &&
(back_index >= 0) &&
(nums[front_index] == nums[back_index]);
}
// Replace the max mirror length with the new max if needed
if (matchlen > maxlen) maxlen = matchlen;
}
}
return maxlen;
}
Alternative solution designed to confuse you
public int maxMirror(int[] nums) {
return maxlen_all_f(nums, 0);
}
int maxlen_all_f(int [] nums, int f) {
return (f >= nums.length)
? 0
: max(
maxlen_for_start_f(nums, f, nums.length - 1),
maxlen_all_f(nums, f + 1)
);
}
int max(int a, int b){
return (a > b)
? a
: b;
}
int maxlen_for_start_f(int [] nums, int f, int b) {
return (b < f)
? 0
: max(
matchlen_f(nums, f, b),
maxlen_for_start_f(nums, f, b - 1)
);
}
int matchlen_f(int[] nums, int f, int b) {
return match_f(nums, f, b)
? 1 + matchlen_f(nums, f + 1, b - 1)
: 0;
}
Boolean match_f(int [] nums, int a, int b) {
return (a < nums.length && b >= 0) && (nums[a] == nums[b]);
}
The solution is simple rather than making it complex:
public static int maxMirror(int[] nums) {
final int len=nums.length;
int max=0;
if(len==0)
return max;
for(int i=0;i<len;i++)
{
int counter=0;
for(int j=(len-1);j>i;j--)
{
if(nums[i+counter]!=nums[j])
{
break;
}
counter++;
}
max=Math.max(max, counter);
}
if(max==1)
max=0;
return max;
}
This is definitely not the best solution in terms of performance. Any further improvements are invited.
public int maxMirror(int[] nums) {
int maxMirror=0;
for(int i=0;i<nums.length;i++)
{
int mirror=0;
int index=lastIndexOf(nums,nums[i]);
if(index!=-1){
mirror++;
for(int j=i+1;j<nums.length;j++)
{
if(index>=0&&existsInReverse(nums,index,nums[j]))
{
mirror++;
index--;
continue;
}
else
break;
}
if(mirror>maxMirror)
maxMirror=mirror;
}
}
return maxMirror;
}
int lastIndexOf(int[] nums,int num){
for(int i=nums.length-1;i>=0;i--)
{
if(nums[i]==num)
return i;
}
return -1;
}
boolean existsInReverse(int nums[],int startIndex,int num){
if(startIndex!=0&&(nums[startIndex-1]==num))
return true;
return false;
}
Here is my answer , Hope the comments explain it well :)
public int maxMirror(int[] nums) {
int max = 0;
// our largest mirror section found stored in max
//iterating array
for(int i=0;i<nums.length;i++){
int iterator = i; // iterator pointing at one element of array
int counter = 0;//counter to count the mirror elements
//Looping through for the iterator element
for(int j=nums.length-1;j>=i;j--){
//found match i.e mirror element
if(nums[iterator] == nums[j]){
iterator++; // match them until the match ends
counter++; // counting the matched ones
}
else{
//matching ended
if(counter >= max){//checking if previous count was lower than we got now
max = counter; // store the count of matched elements
}
counter = 0; // reset the counter
iterator = i; // reset the iterator for matching again
}
}
if(counter >= max){//checking if previous count was lower than we got now
max = counter;// store the count of matched elements at end of iteration
}
}
return max;//return count
}

Find the first occurrence of an odd and count them

import java.util.*;
public class FirstOddOccurrence {
public static void main(String[] args) {
int[] x = {2, 4, 6, 7, 4, 3, 2, 7, 6, 7, 7};
int i;
display(x);
System.out.printf("# Occurrences of first odd = %3d\n", firstOddCount(x));
}
private static void display(int[] x) {
int i;
System.out.print("Array: ");
for (i = 0; i < x.length; i++) {
if (i < x.length - 1)
System.out.printf("%3d, ", x[i]);
else
System.out.printf("%3d\n", x[i]);
}
}
public static int odd(int[] x) {
int i;
int y;
for (i = 0; i < x.length; i++) {
y = x[i] % 2;
if (y == 1) {
return x[i];
} else {
return 0;
}
}
return x[i];
}
public static int firstOddCount(int x[]) {
int i;
int c = 0;
for (i = 0; i < x.length; i++) {
if (x[i] == odd(x))
c++;
}
return c;
}
}
I'm trying to find the first occurrence of an odd number in the array that has been provided. What is wrong with my program? I can't seem to get the program to count the first odd occurrences.
Your code here:
if (y == 1) {
return x[i];
} else {
return 0;
}
does not work - if a tested number is even, you immediately return 0. Instead you want to skip these even numbers and wait until an odd number comes up. In the end, if you don't find any odd number, you return 0. Here is the corrected version of odd():
int i;
int y;
for (i = 0; i < x.length; i++) {
y = x[i] % 2;
if (y == 1) {
return x[i];
}
}
return 0;
Andr's solution fixes your issue; odd(x) will return 0 if x[0] is even, and x[0] if it is odd.
You could also improve firstOddCount like so: odd(x) will always return the same value, so only calculate it once.
public static int firstOddCount(int x[]) {
int firstOdd = odd(x);
int c=0;
for(int i=0; i < x.length; i++) {
if (x[i]==firstOdd)
c++;
}
return c;
}
Your particular problem is that you return 0 if you find an even number. That means that the list {2, 4, 6, 8, 1} will give you 0, rather than 1, as the first odd number.
What you should do is ignore leading even numbers and continue to process the list.
However, the way you've organised your program, you're processing the first all-even part of the list twice, once in odd() to find the first odd number, then again in firstOddCount() to count how many of that number there are - that's totally unnecessary.
Once you find the first odd number, I think you can be reasonably certain that number (or any other odd number for that matter) does not exist in the space you've already searched. Otherwise it would have been the first odd number. Hence it makes little sense to go back and look at that initial part of the list again.
A way in which you can easily just process the list once is as follows:
public static int firstOddCount (int numbers[]) {
// Find first odd number or end of list.
int idx = 0, len = numbers.length;
while ((idx < len) && ((numbers[idx] % 2) == 0)
idx++;
// If at end of list, everything is even => count(first(odd)) is 0.
if (idx == len)
return 0;
// Otherwise, start counting from current position.
int count = 1, oddnum = numbers[idx];
while (++idx < len)
if (numbers[idx] == oddnum)
count++;
return count;
}
If you are trying to get one element from group you should use 'break' when your condition matched first time else it will give all...

Categories

Resources