finding the pattern length in an integer array in java? - java

Suppose I have a Fibonacci sequence of the number x as follows and I want to detect a sequence in an array. Java method should return the length of sequence
x 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610
1)x mod 2 - 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0
2)x mod 3 - 0 1 1 2 0 2 2 1 0 1 1 2 0 2 2 1
Answer 1) 3 (repetitive sequence 011 and length is 3)
2) 8 (repetitive sequence 01120221 and length is 8)

A very simple approach would be to create a copy of the array, and check position 0 of the first array against position 1 of the second array, and if they match, continue checking until the end. If the whole thing matches, then you have a repeating length of 1.
If not, then you compare position 0 of the first array to position 2 of the second array, and follow the same process as above. If this matches, then you have a repeating length of 2.
And you continue this process until you either find a match, or reach the end of the array and can't offset it any further, in which case there is no repeat.

If you are only intending to use this specifically for modulo values of numbers in the Fibonacci sequence, and not for arbitrary data, then the sequence will repeat as soon as you find the second occurrence of a 0 followed by a 1 in the modulo sequence. This is because mod(a + b, n) = mod(mod(a, n) + mod(b, n), n), so the modulo of a number in the Fibonacci sequence (which is the sum of the two previous values) is determined by the previous 2 modulo results. Therefore, once the original pattern of a 0 followed by a 1 reoccurs, the pattern will repeat.

The Following code works:
private static int detectSequence(int[] array) {
int count = 2;
for (int i = 2; i < array.length; i++) {
if(array[i] == 0 && array[i+1] == 1 && i+1 < array.length){
return count;
}
count++;
}
return count;
}

Related

Code doesn't print the correct number of repeated digits

So basically this is a method to print numbers from 0 to n but squared. And to return the number of digits "d" contained in the numbers from 0 to n.
So let's say n=10 and d=1, we will have 0 1 4 9 16 25 36 49 64 81 100 and the method should return 4 since there are 4 ones in this set of numbers.
This works fine, but when n is defined with a bigger integer that's where the method starts to return an incorrect number of digits.
for instance, if we have n=5750 and d=0, the method returns 3012 when it's supposed to return 4700. Where did I do wrong?
public static int numberOfDig(int n, int d) {
String output="";
for(int i=0;i<=n;i++){
output+=(int)Math.pow(i, 2)+" ";
}
String[] numbers=output.split(" ");
String digit= Integer.toString(d);
int count =0;
for(int i=0;i<numbers.length;i++){
if(numbers[i].contains(digit))count++;
}
return count;
}
Please don't hesitate to ask questions if you need further explanations.
Your problem is that you only increment your count by one when a number contains the digit d. You need to increment by the number of times d occurs in each number.
The relevant code is:
if (numbers[i].contains(digit))
count++;
So if d == 5 and numbers[i] == 25, you increment count by 1 which is correct.
However, if d == 0 and numbers[i] == 100 you increment count by 1 which is incorrect. You should increment by 2 (as there are two zeroes).
A simple test would be n=10 and d=1, where output will be 0 1 4 9 16 25 36 49 64 81 100 121. Your method will return 5 as there are five numbers that contain a 1, whereas it should return 6 as 121 contains two instances of 1.

How do i swap element 1 with 0 of an array (consisting of only 1's and 0's) so that all 1's are together

How to solve the following programming question.
There is an array consisting of only 0s and 1s in random order. The position of 1 can be switched with any position of 0. What is the minimum number of swaps required so that all 1s are together.
What is the best approach to solve this problem. I cant even come up with brute force approach.
For example,consider the following array(index starting from 0)
Array size 14 1 0 0 0 1 0 1 0 1 0 0 0 0 1
After 1st pass 0 0 0 0 1 1 1 0 1 0 0 0 0 1 (index 0 swapped with index 5)
After 2nd pass 0 0 0 0 1 1 1 1 1 0 0 0 0 0 (index 7 swapped with index 13)
Two swaps are required to get all 1s together
First, count the number of 1s (let's call it k). This can be done in O(n).
Next, walk through the array, and compute the sum of trailing k elements for each index i between k and n. This can be done in O(n) as well, by using a sum for the prior element plus the current value minus the value at position i-k.
The number of swaps is equal to k-max(sum).
In your example, k is 5. k-sums are as follows:
1 0 0 0 1 0 1 0 1 0 0 0 0 1
- - - - 2 1 2 2 3 2 2 1 1 1
The highest sum is 3, hence the number of swaps is 5-3=2.
Note: The intuitive rationale for the algorithm is simple: the position with the highest sum is the place where the run of 1s grouped together is going to end, because it has the highest "concentration" of ones in a block of k indexes. This is the place into which you will be copying 1s, and you need k-max remaining 1s to be copied.
no swaps,
size = count the size
n = count the one's
print n '1's
print (size - n) '0's

Maximum sub-sum

Here is example of my input data:
5 // Number of 1D arrays, in this case we'll have array[5][3]
1 2 3 // Values of array[i][0..2]
1 1 1
1 0 0
1 1 0
2 1 0
And output is:
12 // Maximum sum ({1 2 3} + {1 1 1} + {2 1 0} = {4 4 4} = 12) - END SUM VALUES MUST BE EQUAL(4 4 4).
3 // Number of arrays used to get this sum
The problem is to find maximum sum using n arrays, and secod condition is to use minimum number of arrays. Also if sum > 300 we stop algorithm. (300 is maximum). Here is my code, it's I get good answers but it's time complexity is O(2^n-1). I'm thinking that it's possible to save results in some way and don't calculate same things many times, but I don't know how yet.
public static int[] fuel(int start, int[] sum, int counter) {
int[] val = { sum[0] + crystal[start][0], sum[1] + crystal[start][1], sum[2] + crystal[start][2] };
int newSum = val[0] + val[1] + val[2];
if(newSum > 300)
return null;
if(val[0] == val[1] && val[1] == val[2]) { // All 3 values have to be equal!
if(newSum > result[0]) {
result[0] = newSum;
result[1] = counter;
} else if(newSum == result[0] && result[1] > counter) {
result[1] = counter;
}
}
if(start + 1 < crystalNumber) {
fuel(start + 1, val, counter + 1);
fuel(start + 1, sum, counter);
}
return result;
}
This may not be the best algorithm to solve this but it should be quicker than O(2^N).
The idea is to record all reachable sums as you loop through the input array. You can use a dictionary whose key is a unique hash of the possible sums, for the sake of simplicity let's just assume the key is a string which concatenates the three sums, for example, the sums [3,5,4] we'll use the key "003005004" , the value of the dictionary will be the minimum numbers of arrays to reach that sum.
So in your case:
1 2 3 => [001002003] =1
1 1 1 => [001001001] =1, [002003004]=2 (itself and use [001002003] from above)
1 0 0 => [001000000] =1, [002002003] =2, [002001001] =2, [003003004] =3
1 1 0 ...
2 1 0 ...
In the end, you will find [004004004] =3 and that's your answer.
This may seems going through all combinations as well so why it's quicker, it's because the maximum sum is 300 for each number, so in the very worst case, we may have 301^3 keys filled and have to update their values for each new input array. This is however still O(n) and despite of the large constant, it should still run much faster than O(2^n). (If you solve 300^3*n = 2^n, n is around 30-ish)
A simple hash function would be a*301*301+b*301+c
I think the problem is given m 1-D arrays and a number n, find the maximum sum using n arrays from m;
The solution looks straight forward. keep sum of each 1-D array in a separate array, say sum[]
1 2 3 = 6
1 1 1 = 3
1 0 0 = 1
1 1 0 = 2
2 1 0 = 3
Sort this array sum
6,3,3,2,1
and return the sum of first n elements of this array.

Find the greatest odd number with a limited number of bits

I was trying to solve this question but the automated judge is returning "time limit exceeded" (TLE).
On the occasion of Valentine Day , Adam and Eve went on to take part in a competition.They cleared all rounds and got into the finals. In the final round, Adam is given a even number N and an integer K and he has to find the greatest odd number M less than N such that the sum of digits in binary representation of M is atmost K.
Input format:
For each test case you are given an even number N and an integer K
Output format:
For each test case, output the integer M if it exists, else print -1
Constraints:
1 &leq; T &leq; 104
2 &leq; N &leq; 109
0 &leq; K &leq; 30
Sample input:
2
10 2
6 1
Sample output:
9
1
This is what I have done so far.
static long play(long n, int k){
if(k==0) return -1;
if(k==1) return 1;
long m=n-1;
while(m>0){
long value=Long.bitCount(m); //built in function to count bits
if(value<=k ){
return m;
}
m=m-2;
}
return -1;
}
public void solve(InputReader in, OutputWriter out) {
long start=System.currentTimeMillis();
int t=in.readInt();
while(t-->0){
long n=in.readLong();
int k=in.readInt();
long result=play(n,k);
out.printLine(result);
}
long end=System.currentTimeMillis();
out.printLine((end-start)/1000d+"ms");
}
}
According to updated question N can be between 2 and 10^9. You're starting with N-1 and looping down by 2, so you get up to about 10^9 / 2 iterations of the loop. Not good.
Starting with M = N - 1 is good. And using bitCount(M) is good, to get started. If the initial bitcount is <= K you're done.
But if it's not, do not loop with step -2.
See the number in your mind as binary, e.g. 110101011. Bit count is 6. Let's say K is 4, that means you have to remove 2 bits. Right-most bit must stay on, and you want largest number, so clear the two second-last 1-bits. Result: 110100001.
Now, you figure out how to write that. And do it without converting to text.
Note: With N <= 10^9, it will fit in an int. No need for long.
You'll have to perform bitwise operations to compute the answer quickly. Let me give you a few hints.
The number 1 is the same in binary and decimal notation: 12 = 110
To make the number 102 = 210, shift 1 to the left by one position. In Java and many other languages, we can write this:
(1 << 1) == 2
To make the binary number 1002 = 410, shift 1 to the left by two positions:
(1 << 2) == 4
To make the binary number 10002 = 810 shift 1 to the left by three positions:
(1 << 3) == 8
You get the idea.
To see if a bit at a certain position is 1 or 0, use &, the bitwise AND operator. For example, we can determine that 510 = 1012 has a 1 at the third most significant bit, a 0 at the second most significant bit, and a 1 at the least significant bit:
5 & (1 << 2) != 0
5 & (1 << 1) == 0
5 & (1 << 0) != 0
To set a bit to 0, use ^, the bitwise XOR operator. For example, we can set the second most significant bit of 710 = 1112 to 0 and thus obtain 510 = 1012:
7 ^ (1 << 1) == 5
As the answer is odd,
let ans = 1, here we use 1 bit so k = k - 1;
Now binary representation of ans is
ans(binary) = 00000000000000000000000000000001
while(k > 0):
make 30th position set
ans(binary) = 01000000000000000000000000000001
if(ans(decimal) < N):
k -= 1
else:
reset 30th position
ans(binary) = 00000000000000000000000000000001
Do the same from 29th to 1st position

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 6

public class IntegerSet {
int dMax;
boolean[] set;
public IntegerSet(int domainMax) {
dMax = domainMax + 1;
set = new boolean[dMax];
}
...some methods...
public static IntegerSet union(IntegerSet s1, IntegerSet s2) {
IntegerSet union = new IntegerSet(Math.max(s1.dMax, s2.dMax));
for (int i = 0; i < (Math.max(s1.dMax, s2.dMax)); i++) {
union.set[i] = (s1.set[i] || s2.set[i]);
}
return union;
}
Can anyone tell me whats wrong with this?
I can't understand why I'm getting the error message after hours: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 6
As the two sets supplied as arguments may have different domain max; the resulting union should have whichever of these two domain max is larger hence why I am using Math.max.
Any help would be appreciated.
The problem arises when s1 and s2 have different lengths. These lines are flawed:
IntegerSet union = new IntegerSet(Math.max(s1.dMax, s2.dMax));
for (int i = 0; i < (Math.max(s1.dMax, s2.dMax)); i++) {
Think about what two sets of unequal length look like:
(using 1 and 0 in place of true and false)
s1: {0 1 0 0 1 1} length = 6
s2: {1 1 1 0 0 0 1 0 1 1 0 1} length = 12
You've programmed your loop to iterate from 0 up to the maximum length of the two sets, which in the above example is 12 (meaning that the last value your loop will use is 11). But s1 is only 6 elements long--its last valid index is 5! As the loop erroneously attempts to access elements 7 through 12 (indices 6 through 11) of s1, it throws an ArrayIndexOutOfBoundsException.
To fix this, you should use the minimum length of the two sets in both of the lines where you use the maximum. This way, you will be taking the union:
s1: {0 1 0 0 1 1} length = 6
s2: {1 1 1 0 0 0 1 0 1 1 0 1} length = 12
union: {1 1 1 0 1 1} length = min(6, 12) = 6
Instead of
s1: {0 1 0 0 1 1}! ! ! ! ! ! length = 6; no elements 7 through 12!
s2: {1 1 1 0 0 0 1 0 1 1 0 1} length = 12
union: {1 1 1 0 1 1 ! ! ! ! ! !} length = max(6, 12) = 12 -> errors
This leaves the later section of s2 out of the union, as there are no corresponding elements in s1 to perform a boolean || with. However, you could also do something like this:
IntegerSet union = new IntegerSet(Math.max(s1.dMax, s2.dMax));
for (int i = 0; i < (Math.max(s1.dMax, s2.dMax)); i++) {
if (s2.set.length > s1.set.length)
{
union.set[i] = s2.set[i] || (i < s1.set.length ? s1.set[i] : false);
}
else
{
union.set[i] = s1.set[i] || (i < s2.set.length ? s2.set[i] : false);
}
}
This will use false's for every missing element in the shorter set, resulting in the union being:
s1: {0 1 0 0 1 1} length = 6
s2: {1 1 1 0 0 0 1 0 1 1 0 1} length = 12
union: {1 1 1 0 1 1 1 0 1 1 0 1} length = max(6, 12) = 12
All entries are simply copied from the longer set, since anything || false is itself.
This:
dMax = domainMax + 1;
should be:
dMax = domainMax;
Or just use set.length.
Your for-loop goes from 0 to the max size of s1 and s2. But because (in the situation that throws errors), one of your IntegerSets is smaller, the for-loop goes past the size of the smaller IntegerSet when retrieving all of the booleans from the larger IntegerSet
for (int i = 0; i < (Math.max(s1.dMax, s2.dMax)); i++) {
union.set[i] = (s1.set[i] || s2.set[i]);
}
If the size of one set is smaller than the max, then you are going to get an IndexOutOfBoundsException.
Example:
Say you have the following conditions:
s1 = {0, 1, 1, 0, 1}
s2 = {0, 0, 0}
s1.dMax = 5, so s1.set has a size of 5
s2.dMax = 3, so s2.set has a size of 3
In your for-loop, you are going to iterate from 0 to 4. When the following occurs:
i = 3
s1.set[i] = s1.set[3] //IndexOutOfBoundsException because the size of s1.set is 3.
You have a couple options of how you can fix this:
You can add a check in your for-loop to ensure that you aren't
going to get an IndexOutOfBoundsException for your smaller
IntegerSet and just set the index in union to the boolean value of your larger set.
You can pad to your smaller IntegerSet depending on what you want the
union to be for the blank indicies.
Use the min size of the two IntegerSets if you want to ignore the
extra booleans (Judging from the fact that you made the union set
the size of the max, I am guess that is not the case)
Side Note: You also do not need to add the +1 to the dMax variable when you create your union IntegerSet. That is going to result in your having an extra index that you don't need and could cause problems later.
You are using dMax as the number of boolean array elements in one place, and as the domain maximum (wrong) when you create the new union set. (That causes you to make union 1 element too large.)
Several things to consider when you rewrite your code:
Assuming domainMax implies a set of integers from [0, domainMax], do define a boolean array with domainMax+1 elements (don't bother with a dMax variable, you can get that info by checking set.length
In the "union" function, be sure to handle the case where one or both of the input IntegerSets is null
Use protected set to make sure the internal representation of the IntegerSet is not known or accessed outside your class
When you perform the union of two non-null IntegerSets, only perform the or operation (||) for the case where both sets have values; then for the "bigger" set, simply copy over the remaining items.

Categories

Resources