Complexity of a loop where j shrinks as j = (j - 1) & i - java

What is the time complexity of this code snippet? Why, mathematically, is that?
for (int i = 0; i < n; i++) {
for (int j = i; j > 0; j = (j - 1) & i) {
System.out.println(j);
}
}

The short version:
The runtime of the code is Θ(nlog2 3), which is approximately Θ(n1.585).
The derivation involves counting the number of 1 bits set in ranges of numbers.
Your connection to Pascal's triangle is not a coincidence!
Here's the route that I used to work this out. There's a really nice pattern that plays out in the bits of the numbers as you're doing the subtractions. For example, suppose that our number i is given by 10101001 in binary. Here's the sequence of values we'll see for j:
10101001
10101000
10100001
10100000
10001001
10001000
10000001
10000000
00101001
00101000
00100001
00100000
00001001
00001000
00000001
00000000
To see the pattern, focus on the columns of the number where there were 1 bits in the original number. Then you get this result:
v v v v
10101001 1111
10101000 1110
10100001 1101
10100000 1100
10001001 1011
10001000 1010
10000001 1001
10000000 1000
00101001 0111
00101000 0110
00100001 0101
00100000 0100
00001001 0011
00001000 0010
00000001 0001
00000000 0000
In other words, the sequence of values j takes on is basically counting down from the binary number 1111 all the way down to zero!
More generally, suppose that the number i has b(i) 1 bits in it. Then we're counting down from a number made of b(i) 1 bits down to 0, which requires 2b(i) steps. Therefore, the amount of work the inner loop does is 2b(i).
That gives us the complexity of the inner loop, but to figure out the total complexity of the loop, we need to figure out how much work is done across all n iterations, not just one of them. So the question then becomes: if you count from 0 up to n, and you sum up 2b(i), what do you get? Or, stated differently, what is
2b(0) + 2b(1) + 2b(2) + ... + 2b(n-1)
equal to?
To make this easier, let's assume that n is a perfect power of two. Say, for example, that n = 2k. This will make this easier because that means that the numbers 0, 1, 2, ..., n-1 all have the same number of bits in them. There's a really nice pattern at play here. Look at the numbers from 0 to 7 in binary and work out what 2b(i) is for each:
000 1
001 2
010 2
011 4
100 2
101 4
110 4
111 8
Now look at the numbers from 0 to 15 in binary:
0000 1
0001 2
0010 2
0011 4
0100 2
0101 4
0110 4
0111 8
----
1000 2
1001 4
1010 4
1011 8
1100 4
1101 8
1110 8
1111 16
In writing out the numbers from 8 to 15, we're basically writing out the numbers from 0 to 7, but with a 1 prefixed. This means each of those numbers has the one plus the number of 1 bits set as the previous versions, so 2b(i) is doubled for each of them. So if we know the sum of these terms from 0 to 2k-1, and we want to know the sum of the terms from 0 to 2k+1 - 1, then we basically take the sum we have, then add two more copies of it.
More formally, let's define S(k) = 2b(0) + 2b(1) + ... + 2b(2k - 1). Then we have
S(0) = 1
S(k + 1) = S(k) + 2S(k) = 3S(k)
This recurrence solves to S(k) = 3k. In other words, the sum 2b(0) + 2b(1) + ... + 2b(2k-1) works out to 3k.
Of course, in general, we won't have n = 2k. However, if we write k = log2 n, then we can get an approximation of the number of iterations at roughly
3log2 k
= klog2 3
≈ k1.584...
So we'd expect the runtime of the code to be Θ(nlog2 3). To see if that's the case, I wrote a program that ran the function and counted the number of times the inner loop executed. I then plotted the number of iterations of the inner loop against the function nlog2 3. Here's what it looks like:
]1
As you can see, this fits pretty well!
So how does connect to Pascal's triangle? It turns out that the numbers 2b(i) has another interpretation: it's the number of odd numbers in the ith row of Pascal's triangle! And that might explain why you're seeing combinations pop out of the math.
Thanks for posting this problem - it's super interesting! Where did you find it?

Here is a Java Code snippet:
int i,j,n,cnt;
int bit=10;
int[] mp = new int[bit+1];
n=(1<<bit);
for(i=0;i<n;i++){
mp[Integer.bitCount(i)]++;
if((i&i+1) ==0){ // check 2^k -1, all bit are set, max value of k bit num
System.out.printf("\nfor %d\n",i);
for(j=0;j<=bit;j++){
System.out.printf("%d ",mp[j]);
}
}
}
Output:
for 0 // 2^0 - 1
1 0 0 0 0 0 0 0 0 0 0
for 1 // 2^1 - 1
1 1 0 0 0 0 0 0 0 0 0
for 3 // 2^2 - 1
1 2 1 0 0 0 0 0 0 0 0
for 7 // 2^3 - 1
1 3 3 1 0 0 0 0 0 0 0
for 15 // 2^4 - 1
1 4 6 4 1 0 0 0 0 0 0
for 31 // 2^5 - 1
1 5 10 10 5 1 0 0 0 0 0
for 63 // 2^6 - 1
1 6 15 20 15 6 1 0 0 0 0
for 127 // 2^7 - 1
1 7 21 35 35 21 7 1 0 0 0
for 255 // 2^8 - 1
1 8 28 56 70 56 28 8 1 0 0
for 511 // 2^9 - 1
1 9 36 84 126 126 84 36 9 1 0
for 1023 // 2^10 - 1
1 10 45 120 210 252 210 120 45 10 1
So it looks like Pascal triangle…
0C0
1C0 1C1
2C0 2C1 2C2
3C0 3C1 3C2 3C3
4C0 4C1 4C2 4C3 4C4
5C0 5C1 5C2 5C3 5C4 5C5
6C0 6C1 6C2 6C3 6C4 6C5 6C6
7C0 7C1 7C2 7C3 7C4 7C5 7C6 7C7
8C0 8C1 8C2 8C3 8C4 8C5 8C6 8C7 8C8
9C0 9C1 9C2 9C3 9C4 9C5 9C6 9C7 9C8 9C9
10C0 10C1 10C2 10C3 10C4 10C5 10C6 10C7 10C8 10C9 10C10
In the question above inner loop executes exactly 2^(number set bit) -1 times.
So if we observe we can ses that If k=number of bit, then N=2^k;
Then Complexity becomes: (kC02^0+kC12^1+kC22^2+kC32^3+ … … … +kCk*2^k) - N
If k=10 then N=2^k=1024 So the complexity becomes as follows:
(10C0*2^0+10C1*2^1+10C2*2^2+10C3*2^3+ … … … +10C10*2^10) - 1024
=(1*1 +10*2 + 45*4+ 120*8+210*16+252*32+210*64+120*128+45*256+10*512+1*1024) - 1024
=59049 - 1024
=58025
Here is another code snippet that helps to verify the number 58025.
int i,j,n,cnt;
n=1024;
cnt=0;
for(i=0;i<n;i++){
for(j=i; j>0; j = (j-1)&i){
cnt++;
}
}
System.out.println(cnt);
The output of the above code is 58025.

Related

Maximum number of consecutive 1 in a given number

public int tobinary(int x)
{
int count = 0;
while(x!=0)
{
x=(x&(x<<1)); //how this stuff is working
count++;
}
return count;
}
the above code is working fine but actually i did copy and paste.so i just want to know how that line of code which i mentioned above is working.it would be a great help for me.
for example i am giving i/p as 7 the binary format for this is 0111 so our answer will be 3 but how ?
As we know, the << operator shifts all bits in its operand to the left, here by 1. Also, the & operator performs a bitwise-and on all bits of both its operands.
When will x not be 0? When the bitwise-and operation finds 2 bits that are both set in both operands. The only time that this will be true is when there are 2 or more consecutive 1 bits in x and x << 1.
x : 0000 0111
x << 1: 0000 1110
-----------------
&: 0000 0110
count = 1
If it's not 0, then there are at least 2 consecutive 1 bits in the number, and the (maximum) number of consecutive 1 bits in the number has been reduced by 1. Because we entered the loop in the first place, count it and try again. Eventually there won't be any more consecutive 1 bits, so we exit the loop with the correct count.
x : 0000 0110
x << 1: 0000 1100
-----------------
&: 0000 0100
count = 2
x : 0000 0100
x << 1: 0000 1000
-----------------
&: 0000 0000
count = 3, exit loop and return.
x = (x & (x << 1)) is performed enough times to eliminate the longest consecutive groups of 1 bits. Each loop iteration reduces each consecutive group of 1s by one because the number is logically ANDed with itself shifted left by one bit. This continues until no consecutive group of 1s remains.
To illustrate it for number 110111101:
110111101 // initial x, longest sequence 4
1101111010 // x << 1, count 1
100111000 // new x, longest sequence 3
1001110000 // x << 1, count 2
110000 // new x, longest sequence 2
1100000 // x << 1, count 3
100000 // new x, longest sequence 1
1000000 // x << 1, count 4
0 // new x, end of loop
Do note that since Java 7 it's handy to declare binary literals with int input = 0b110111101.
<< (left shift) : Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand.
i.e. x<<1 shifts the value bit from right to left by 1 and in the unit position add 0. So, lets say for x=7, bit representation will be 111. Performing x << 1 will return 110 i.e. discarded the head element, shifted the bits to left and added 0 in the end.
This while loop can be broken down into below iteration for initial value of x=7
iteration 1) 111 & 110 =110
iteration 2) 110 & 100 =100
iteration 3) 100 & 000 =000
As value of x is 0, no more iteration
Hope this explains the behaviour of this code. You can put System.out.println(Integer.toBinaryString(x)); to see the change in bit value of x yourself
So what happens is, for each iteration in the while loop,
x = x (AND operator) (2 * x).
For example, when x = 7
count = 0
Iteration 1:
//x = 7 & 14 which results in 6 ie
0111
1110 (AND)
-------
0110 => 6
-------
count = 1
Iteration 2:
//x = 6 & 12 results in 4
0110
1100 AND
-------
0100 => 4
-------
count = 2
Iteration 3:
// x = 4 & 8 results in 0
0100
1000 AND
-----
0000
-----
count = 3
That's how you get 3 for 7

finding the pattern length in an integer array in 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;
}

How do I calculate negation(~) of -5

public class UnaryOperator {
public static void main(String[] args) {
byte a= -5;
System.out.println(~a); // prints 4
}
}
When I do it manually, I get the answer as 6.
Here is how I did it:
128 64 32 16 8 4 2 1
0 0 0 0 0 1 0 1
As it is a negation I inverted it to the following:
128 64 32 16 8 4 2 1
0 0 0 0 0 1 0 1
sign -1 1 1 1 1 0 1 0
-----------------------------
0 0 0 0 1 0 1
add one--> 0 0 0 0 0 1 1
------------------------------
0 0 0 0 1 1 0 = 6
------------------------------
I know there's something wrong with what I am doing but I am not able to figure it out.
5 is 00000101
-5 is 11111010+00000001 = 11111011
~(-5) is 00000100
so you get 4.
You're starting out with -5, which is in two's complement. Thus:
-128 64 32 16 8 4 2 1
1 1 1 1 1 0 1 1 (= -5)
flip: 0 0 0 0 0 1 0 0 (= +4)
I haven't done much bitwise stuff, but after reading wikipedia for a few seconds it seems like NOT -5 = 4, on wikipedia they used NOT x = -x - 1. So the program is correct.
Edit: For unsigned integers, you use NOT x = y - x were y is the maximum number that integer can hold.

building combination table out of classic order [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I would like to built a combination table for example 4 number of 5 samples(0 -4), but not in the right order. The table should start with the combinations of 0 and 1; than 0,1 2; than 0,1,2,3; than 0,1,2,3,4. Of course the table should not have repetition. I need an algorithm to do it but I can not find any until now. After that I have to write a java code. At the end the table should look like this:
0 0 0 1
0 0 1 0
0 1 0 0
1 0 0 0
0 0 1 1
0 1 0 1
0 1 1 0
1 0 1 0
1 1 0 0
0 1 1 1
.... ... ... ...
1 1 1 1
0 0 0 2
.... ... ... ...
2 0 0 0
... ... ... ...
0 0 1 2
.... ... ... ...
2 2 2 2
0 0 0 3
.... ... ... ...
3 0 0 0
0 0 1 3
.... ... ... ...
3 2 2 2
... ... ... ...
3 3 3 3
.... .... ...... ...
4 4 4 4
You could start with 0000 and increment by 1 (in base 2,3,4,5) until you overflow. E.g.
Base 2:
0000 + 1 => 0001
0001 + 1 => 0010
0010 + 1 => 0011
...
1110 + 1 => 1111
Base 3:
0000 + 1 => 0001
0001 + 1 => 0002
0002 + 1 => 0010
...
2221 + 1 => 2222
And similar for bases 4 and 5.
If you care about repeats (e.g. 0001 is repeated in base 2 and 3) then you can just increment until: for base 2 you have at least a single 1, for base 3 you have at least a single 2, etc...
Java Example:
public static void main(String... args){
int n = 4;
// for base 1, 2, 3, 4, 5 (base 1 gives 0000)
for(int base = 1; base < n + 2; base++)
// for every combination: base^n
for(int j = 0; j < Math.pow(base, n); j++)
// if num contains a (base-1) digit, it's not a dup
if(Integer.toString(j, base).contains(Integer.toString(base-1)))
System.out.println(String.format("%04d",
Integer.parseInt(Integer.toString(j, base))));
}

java bit operators

I came across this piece of code in java and will be delighted if someone can explain the logic to me.
public boolean name(int n) {
return ((n >> n) & 1L) > 0;
}
this is a kind of check operation I guess but what boolean value will this code return. And is there an alternative to this code. I am trying my best to understand bit manipulation in java.
That's a bizarre piece of code. It checks whether the number n, having been shifted right n % 32 bits, is odd.
The first non-negative values which pass are 37 (100101 in binary), 70 (1000110 in binary), and 101 (1100101 in binary).
I doubt that it actually works as the original coder intended it to - it doesn't obviously signify anything useful (and the method name of name is pretty unhelpful...)
Perhaps the point of this puzzle was to see if you would consider shifting outside 0 to 31 bits and what would happen.
It gets more bizarre for negative numbers.
for(int n=-70;n<=200;n++)
if (((n >> n) & 1L) > 0)
System.out.print(n + " ");
prints
-70 -69 -68 -67 -66 -65 -58 -57 -56 -55 -54 -53 -52 -51 -50 -49 -48 -47 -46 -45 -44 -43 -42 -41 -40 -39 -38 -37 -36 -35 -34 -33 -27 -26 -25 -24 -23 -22 -21 -20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 37 70 101 102 135 165 167 198 199
A similar formula when n is an int
n & (1 << (n & 31)) != 0
if n was a long
n & (1L << (n & 63)) != 0
More negative numbers have a 1 set after shifting because they get sign extended.
A similar puzzle
http://vanillajava.blogspot.co.uk/2012/01/another-shifty-challenge.html
http://vanillajava.blogspot.co.uk/2012/01/shifting-challenge.html
For positive numbers, it seems that the function returns true iff a number is of the form:
sum_k (alpha_k * 2^k + d(k)), where
alpha_k = 0 or 1
k >= 5
d(k) = k for exactly one of the k where alpha_k = 1 and 0 otherwise
Example:
alpha_k = 1 for k = 5, 0 otherwise => 32 + 5 = 37
alpha_k = 1 for k = 6, 0 otherwise => 64 + 6 = 70
alpha_k = 1 for k = 5 and 6, 0 otherwise => 32 + 5 + 64 = 101
or 32 + 64 + 6 = 102
etc.
All those numbers will work:
shifting that number by itself % 32 shifts it by d(k) for the k that is not null.
the bit that goes to position 1 is in position k which is 1 by definition (alpha_k = 1)
Proving that only those numbers work is a bit more challenging...
Next question is obviously: what's the point?!
>> is signed right shift operator, left operand is integer to be shifted and the right one is the number of bit positions to shift the integer by. Final & 1L operation tests the zeroth bit: the function returns true if the zeroth bit is 1. True purpose of this is unknown to me, but the resulting set for which this function returns true is dependent on the operand size, e.g. for 32bit int the piece (n >> n) returns non-zero result for multiples of 32 and then ...
32: (n>>n): 32 (n>>n)&1L: 0
33: (n>>n): 16 (n>>n)&1L: 0
34: (n>>n): 8 (n>>n)&1L: 0
35: (n>>n): 4 (n>>n)&1L: 0
36: (n>>n): 2 (n>>n)&1L: 0
37: (n>>n): 1 (n>>n)&1L: 1
or
192: (n>>n): 192 (n>>n)&1L: 0
193: (n>>n): 96 (n>>n)&1L: 0
194: (n>>n): 48 (n>>n)&1L: 0
195: (n>>n): 24 (n>>n)&1L: 0
196: (n>>n): 12 (n>>n)&1L: 0
197: (n>>n): 6 (n>>n)&1L: 0
198: (n>>n): 3 (n>>n)&1L: 1
199: (n>>n): 1 (n>>n)&1L: 1

Categories

Resources