Single Number II from leetcode - java

The question about Single Number II from leetcode is:
Given an array of integers, every element appears three times except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
Actually, I already found the solution from website, the solution is:
public int singleNumber(int[] A) {
int one = 0, two = 0;
for (int i = 0; i < A.length; i++) {
int one_ = (one ^ A[i]) & ~two;
int two_ = A[i] & one | ~A[i] & two;
one = one_;
two = two_;
}
return one;
}
However, I do not know why this code can work and actually I do not know the way of thinking of this problem when I first saw it? Any help. thx!

So, I was going through some coding problems and stuck with this one for quite some time, and after a ton of research on google, going through different posts and portals, I have understood this problem. Will try to explain it as simple as I can.
The problem has 3 solutions:
Using HashMap: But as we know that will add O(N) space complexity and we don't want that. But for a little bit of understanding, the approach is to iterate the array, get the count of the digits and maintain it in map. Then iterate the map and where the count is 1 that will be your answer.
Using Bitwise operators: The logic for this approach is to think the numbers in bits and then add all the bits of each position. So after adding you will see that the sum is either multiple of 3 or multiple of 3 + 1 (Because the other number is occurring once only). After this, if you do a modulo on this sum you will have the result. You will understand better with the example.
Example: Array - [5, 5, 5, 6]
 5 represented in bits: 101
 6 represented in bits: 110
 [ 101, 101, 101, 110] (Binary Reprenstation of values) After adding to particular positions, we will have
  0th -> 3, 1th -> 1,  2nd -> 4
 and if you mod by 3 it will become
  0th -> 0,  1th -> 1, 2nd -> 1
 which in decimal representation is our answer 6.
Now we need to code the same. I have explained the code using comments.
public class SingleNumberII {
/*
* Because the max integer value will go upto 32 bits
* */
private static final int INT_SIZE = 32;
public int singleNumber(final int[] A) {
int result = 0;
for(int bitIterator = 0; bitIterator < INT_SIZE; bitIterator++) {
int sum = 0, mask = (1 << bitIterator);
/*
* Mask:
* 1 << any number means -> it will add that number of 0 in right of 1
* 1 << 2 -> 100
* Why we need mask? So when we do addition we will only count 1's,
* this mask will help us do that
* */
for(int arrIterator = 0; arrIterator < A.length; arrIterator++) {
/*
* The next line is to do the sum.
* So 1 & 1 -> 0
* 1 & 0 -> 0
* The if statement will add only when there is 1 present at the position
* */
if((A[arrIterator] & mask) != 0) {
sum++;
}
}
/*
* So if there were 3 1's and 1 0's
* the result will become 0
* */
if(sum % 3 == 1) {
result |= mask;
}
}
/*So if we dry run our code with the above example
* bitIterator = 0; result = 0; mask = 1;
* after for loop the sum at position 0 will became 3. The if
* condition will be true for 5 as - (101 & 001 -> 001) and false for 6
* (110 & 001 -> 000)
* result -> 0 | 1 -> 0
*
* bitIterator = 1; result = 0; mask = 10;
* after for loop the sum at position 1 will became 1. The if
* condition will be true for 6 as - (110 & 010 -> 010) and false for 5
* (101 & 010 -> 000)
* result -> 00 | 10 -> 10
*
* bitIterator = 2; result = 10; mask = 100;
* after for loop the sum at position 2 will became 4. The if
* condition will be true for 6 as - (110 & 100 -> 100) and true for 5
* (101 & 100 -> 100)
* result -> 10 | 100 -> 110 (answer)
* */
return result;
}
}
As we can see this is not the best solution, because we are unnecessary iterating it over 32 times and it is also not that generalized. Which makes as to visit our next approach.
Using Bitwise operators (Optimized and Generalized):
So for this approach, I'll try to explain the approach, then code and then how to make it generalize.
We will take 2 flags(one, two) for analogy consider them as sets.
So we the number appears 1st time it will be added in one only if it is not present in two. and we will do the same for two, meaning if the number appears 2nd time we will remove it from 1 and then add it to two(only if it is not present in one) and for the number appearing a third time it will be removed from the set two and will no longer exist in either set.
You might have the question that why 2 sets(or variables) reason is explained in 4th point.
public int singleNumberOptimized(int[] A) {
int one = 0, two = 0;
/*
* Two sets to maintain the count the number has appeared
* one -> 1 time
* two -> 2 time
* three -> not in any set
* */
for(int arrIterator = 0; arrIterator < A.length; arrIterator++){
/*
* IF one has a number already remove it, and it does not have that number
* appeared previously and it is not there in 2 then add it in one.
* */
one = (one ^ A[arrIterator]) & ~two;
/*
* IF two has a number already remove it, and it does not have that number
* appeared previously and it is not there in 1 then add it in two.
* */
two = (two ^ A[arrIterator]) & ~one;
}
/*
* Dry run
* First Appearance : one will have two will not
* Second Appearance : one will remove and two will add
* Third Appearance: one will not able to add as it is there in two
* and two will remove because it was there.
*
* So one will have only which has occurred once and two will not have anything
* */
return one;
}
How to solve these type of questions more generically?
The number of sets you need to create depends on the value of k (Appearance of every other integer).
m >= log(K). (To count the number of 1's in the array such that whenever the counted number of 1 reaches a certain value, say k, the count returns to zero and starts over. To keep track of how many 1's we have encountered so far, we need a counter. Suppose the counter has m bits.) m will be the number of sets we need.
For everything else, we are using the same logic. But wait what should I return, the logic is to do OR operations with all the sets which will eventually the OR operation on the single number with itself and some 0s, which interns to the single number.
For a better understanding of this particular part go through this post here.
I have tried my best to explain to you the solution. Hope you like it. #HappyCoding
For more such content refer: https://thetechnote.web.app/

The idea is to reinterpret the numbers as vectors over GF(3). Each bit of the original number becomes a component of the vector. The important part is that for each vector v in a GF(3) vector space the summation v+v+v yields 0. Thus the sum over all vectors will leave the unique vector and cancel all others. Then the result is interpreted again as a number which is the desired single number.
Each component of a GF(3) vector may have the values 0, 1, 2 with addition being performed mod 3. The "one" captures the low bits and the "two" captures the high bits of the result. So although the algorithm looks complicated all that it does is "digitwise addition modulo 3 without carry".

Here is another solution.
public class Solution {
public int singleNumber(int[] nums) {
int p = 0;
int q = 0;
for(int i = 0; i<nums.length; i++){
p = q & (p ^ nums[i]);
q = p | (q ^ nums[i]);
}
return q;
}
}
Analysis from this blog post.

The code seems tricky and hard to understand at first glance.
However, if you consider the problem in Boolean algebra form, everything becomes clear.
What we need to do is to store the number of 1's of every bit. Since each of the 32 bits follow the same rules, we just need to consider 1 bit. We know a number appears 3 times at most, so we need 2 bits to store that. Now we have 4 state, 00, 01, 10 and 11, but we only need 3 of them.
In your solution, 01 for one and 10 for two are chosen. Let one represents the first bit, two represents the second bit. Then we need to set rules for one_ and two_ so that they act as we hopes. The complete loop is 00->10->01->00(0->1->2->3/0).
It's better to make Karnaugh map a.k.a. K-map. For Karnaugh Map Ref.
3-state counter
Respective values of A[i], two, one and two_, one_ after
0 0 0 | 0 0
0 0 1 | 0 1
0 1 0 | 1 0
0 1 1 | X X
1 0 0 | 0 1
1 0 1 | 1 0
1 1 0 | 0 0
1 1 1 | X X
Here X denotes we don't care for that case or simply in the final value of two and one, wherever their output is 1, that can also be considered, the result will be same and 4th and 8th case won't exist for it as two and one can't be one at the same time.
If you're thinking how I came up with the above table. I'm going to explain one of them. Considering 7th case, when A[i] is 1, two is 1 i.e. there already exists A[i] which repeats two times. Finally there is 3 A[i]'s. As, there's 3 of them, then two_ and one_ both should reset to 0.
Considering for one_
It's value is 1 for two cases i.e. 2nd and 5th case. Taking 1 is same as considering minterms in K-map.
one_ = (~A[i] & ~two & one) | (A[i] & ~two & ~one)
If ~two is taken common, then
(~A[i] & one) | (A[i] & ~one) will be same as (A[i]^one)
Then,
one_ = (one ^ A[i]) & ~two
Considering for two_
It's value is 1 for two cases i.e. 3rd and 6th case. Taking 1 is same as considering minterms in K-map.
two_ = (~A[i] & two & ~one) | (A[i] & ~two & one)
Bit manipulation for the calculated two_ will work for the problem. But, As you've mentioned
two_ = (A[i] & one) | (~A[i] & two)
The above expression can be easily be obtained using K-map considering don't cares i.e. X for all cases mentioned above as considering X won't affect our solution.
Considering for two_ and considering X
It's value is 1 for two cases i.e. 3rd and 6th case and X for two cases i.e. 4th and 8th case. Now, considering minterms.
two_ = (~A[i] & two & ~one) | (A[i] & ~two & one) | (~A[i] & two & one) | (A[i] & two & one)
Now, taking common (A & one) and (~A & two) in the above expression, you'll be left with (two|~two) and (one|~one) which is 1. So, we'll be left with
two_ = (A[i] & one) | (~A[i] & two)
For more insights!

There are three status: 0, 1, 2
So cannot use single bit, have to use high/low bit to present them as: 00, 01, 10
Here's the logic:
high/low 00 01 10
x=0 00 01 10
x=1 01 10 00
high is a function of both high and low.
If low == 1 then high = x, else high = high & ~x
We have
high = low & x | high & ~x
This equals to your: "int two_ = A[i] & one | ~A[i] & two;"
Similarly we have low as the function of both high and low:
If high == 1 then low = ~x, else low = low XOR x

I have a solution more straightforward:
int singleNumber(int A[], int n) {
int one = 0, two = 0, three = ~0;
for(int i = 0; i < n; ++i) {
int cur = A[i];
int one_next = (one & (~cur)) | (cur & three);
int two_next = (two & (~cur)) | (cur & one);
int three_next = (three & (~cur)) | (cur & two);
one = one_next;
two = two_next;
three = three_next;
}
return one;
}

First that came to my head, it's bigger but more simple to understand. Just implement addition mod by 3.
*
class Solution {
public:
int sum3[34], bit[33];
int singleNumber(int A[], int n) {
int ans(0);
for(int i=0;i<33;i++){
bit[i + 1] = 1<<i;
}
int aj;
for(int i=0;i<n;i++){
for(int j=1;j<33;j++){
aj = abs(A[i]);
if(bit[j] & aj) sum3[j]++;
}
}
for(int i=0;i<33;i++){
sum3[i] %= 3;
if(sum3[i] == 1) ans += bit[i];
}
int positve(0);
for(int i=0;i<n;i++){
if(A[i] == ans){
positve++;
}
}
if(positve%3 == 1)
return ans;
else return -ans;
}
};
*

Related

Getting negative integer values while using Random class to generate random positive integers [duplicate]

In java when you do
a % b
If a is negative, it will return a negative result, instead of wrapping around to b like it should. What's the best way to fix this? Only way I can think is
a < 0 ? b + a : a % b
It behaves as it should a % b = a - a / b * b; i.e. it's the remainder.
You can do (a % b + b) % b
This expression works as the result of (a % b) is necessarily lower than b, no matter if a is positive or negative. Adding b takes care of the negative values of a, since (a % b) is a negative value between -b and 0, (a % b + b) is necessarily lower than b and positive. The last modulo is there in case a was positive to begin with, since if a is positive (a % b + b) would become larger than b. Therefore, (a % b + b) % b turns it into smaller than b again (and doesn't affect negative a values).
As of Java 8, you can use Math.floorMod(int x, int y) and Math.floorMod(long x, long y). Both of these methods return the same results as Peter's answer.
Math.floorMod( 2, 3) = 2
Math.floorMod(-2, 3) = 1
Math.floorMod( 2, -3) = -1
Math.floorMod(-2, -3) = -2
For those not using (or not able to use) Java 8 yet, Guava came to the rescue with IntMath.mod(), available since Guava 11.0.
IntMath.mod( 2, 3) = 2
IntMath.mod(-2, 3) = 1
One caveat: unlike Java 8's Math.floorMod(), the divisor (the second parameter) cannot be negative.
In number theory, the result is always positive. I would guess that this is not always the case in computer languages because not all programmers are mathematicians. My two cents, I would consider it a design defect of the language, but you can't change it now.
=MOD(-4,180) = 176
=MOD(176, 180) = 176
because 180 * (-1) + 176 = -4 the same as 180 * 0 + 176 = 176
Using the clock example here, http://mathworld.wolfram.com/Congruence.html
you would not say duration_of_time mod cycle_length is -45 minutes, you would say 15 minutes, even though both answers satisfy the base equation.
Java 8 has Math.floorMod, but it is very slow (its implementation has multiple divisions, multiplications, and a conditional). Its possible that the JVM has an intrinsic optimized stub for it, however, which would speed it up significantly.
The fastest way to do this without floorMod is like some other answers here, but with no conditional branches and only one slow % op.
Assuming n is positive, and x may be anything:
int remainder = (x % n); // may be negative if x is negative
//if remainder is negative, adds n, otherwise adds 0
return ((remainder >> 31) & n) + remainder;
The results when n = 3:
x | result
----------
-4| 2
-3| 0
-2| 1
-1| 2
0| 0
1| 1
2| 2
3| 0
4| 1
If you only need a uniform distribution between 0 and n-1 and not the exact mod operator, and your x's do not cluster near 0, the following will be even faster, as there is more instruction level parallelism and the slow % computation will occur in parallel with the other parts as they do not depend on its result.
return ((x >> 31) & (n - 1)) + (x % n)
The results for the above with n = 3:
x | result
----------
-5| 0
-4| 1
-3| 2
-2| 0
-1| 1
0| 0
1| 1
2| 2
3| 0
4| 1
5| 2
If the input is random in the full range of an int, the distribution of both two solutions will be the same. If the input clusters near zero, there will be too few results at n - 1 in the latter solution.
Here is an alternative:
a < 0 ? b-1 - (-a-1) % b : a % b
This might or might not be faster than that other formula [(a % b + b) % b]. Unlike the other formula, it contains a branch, but uses one less modulo operation. Probably a win if the computer can predict a < 0 correctly.
(Edit: Fixed the formula.)

How is maximum key compare in binary search (1+log(n)) not log(n)?

I was re going through a more versatile explanation of BS. Which has a preposition that maximum number of key compare in a binary search is (1+log(n)). I tried to form an intuition as to how is that possible. I understand the ruining time of BS is (log(n)). Also i speculate that the worse time/maximum key lookups will happen in scenario when we search for a element which is not present in the array. But each time i go over a hypothetical array doing a BS i end up with (log(n)) compares/steps never more than that. Here is the code which was used to form that preposition.
public static int binarySearch(int[] a, int key){
int lo = 0, hi = a.length-1;
while (lo <= hi){
int mid = lo + (hi - lo) / 2;
if (key < a[mid])
hi = mid - 1;
else if (key > a[mid])
lo = mid + 1;
else
return mid;
}
return -1;
}
Probably my speculation is wrong or i am missing some point. If you could explain how maximum possible key compares would be (1+log(n)) it would be great thanks.
Don't forget that even when you have only 1 element, you still have to guess it, because it is possible that the target is not in the array. So we need to add on the +1 for the last guess when we are down to the final remaining element.
It may be clearer if you think about when n=1. We still need 1 guess, but log_2(1) = 0. So we need to add a +1 to fix up the formula.
When n is not a power of 2, we can just go up to the next higher power of 2. For an array whose length is 1000, the next higher power of 2 is 1024, which is 10. Therefore, for a 1000-element array, binary search would require at most 11 (10 + 1) guesses.
Why?
In the worst case, binary search would need 10 steps to separate the remaining numbers and 1 final step to check whether the only one number left is what you want, or it's not in the array.
Here's a different way to think about what you're doing. Rather than thinking of binary search as searching over the elements of the array, think of binary search as searching over the separators between the elements in the array. Specifically, imagine numbering the array like this:
+-----+-----+-----+-----+-----+
| 0 | 1 | 2 | ... | n-1 |
+-----+-----+-----+-----+-----+
Now, number the separators:
+-----+-----+-----+-----+-----+
| 0 | 1 | 2 | ... | n-1 |
+-----+-----+-----+-----+-----+
0 1 2 3 .. n-1 n
Notice that there are n+1 total separators, one before each element and one after the very last element.
Whenever you do a binary search, you're probing the index of the middle separator (do you see why?) and throwing half of the separators away. You can only throw half of a collection of k items away log2 k times before you're down to a single remaining element. This means that the number of probes needed will be ⌈log2 (n+1)⌉, and it happens to be the case that
log2 n < ⌈log2 (n+1)⌉ ≤ log2 n + 1,
so the "1 + log n" bit ends up arising more from "throw away half the separators" than from other sources.
Hope this helps!
Imagine an array of size 8.
l=0, h = 7, mid = 0 + (7-0)/2 = 3 go right
l=4, h = 7, mid = 4 + (7-4)/2 = 5 go right
l=6, h = 7, mid = 6 + (7-6)/2 = 6 go right
l=7, h = 7, mid = 7 + (7-7)/2 = 7 go left
l=7, h=6 ====> terminates
Total comparisons = 1 + Log 8 = 4
EDIT1: Imagine this array and use a pen and paper and trace out the above steps. Search for value 13.
index: 0 1 2 3 4 5 6 7
------------------------------
element: 1 3 5 6 7 9 11 15

Programming: Minimum steps required to convert a binary number to zero

I was working on a programming exercise and was stuck on figuring out the correct algorithm. Here is the problem:
Given a decimal number, how many minimum possible steps are required to convert this to zero provided:
Change the bit i if the next bit i+1 is '1' and all the other bits i+2 and later are 0
Change the last bit without restriction
For example:
if input is (8)Base10 = (1000)Base2, then the steps taken are:
1000→1001→1011→1010→1110→1111→1101→1100→0100→0101→0111→0110→0010→0011→0001→0000
total 15 steps are required.
Complete the following definition:
int minStepsRequired(long number)
It's ok to get a pseudo code or just the algorithm. This is not a homework or assignment.
This is a wonderful problem for a recursive algorithm.
If the length of the binary representation is 0, you can already tell the answer. Or if length 0 is not allowed, then if the length is 1 you tell the answer depending on whether that one bit is 0 or 1.
If the length is longer than 1:
If the first bit is 0, the answer is the same as it would be without that 0 bit. Remove it and call recursively to get the answer.
If the first bit is 1, divide into three subproblems and find the step count for each:
Establish a situation where you are allowed to change the leading 1 to 0. This means it should be followed by a 1 and then all 0s. Write a recursive auxiliary algorithm for this. It is going to be quite similar to the main algorithm, and likely they can share some logic.
Flip the 1 to 0 (1 step)
Convert the remaining bits bits to 0. Another recursive call.
The algorithm may take a long time. It is actually counting the steps, so takes time proportional to the number of steps, which I think is roughly proportional to the input number. Your method takes a long argument, but with my algorithm for large long values it may not terminate witin the lifetime of the computer it is running on. Also the number of steps may overflow an int and even a long (if the input is a negative long value).
The fast way
The following solution doesn’t require recursion and runs in constant time. I can’t explain properly how it works, which is a serious problem if we want to use it for something. I played with some examples, saw a pattern and generalized it. By contrast IMHO some of the beauty of the recursive solution above is that it is straightforward to understand (if you understand recursion).
Example: Input 8 or 1000 binary. Result 15 or 1111 binary. The pattern is: each bit of the result is the XOR of the previous bit of the result and the bit in the same position in the input. So from 1000 just copy the front bit, 1. The following bit is 1 XOR 0 = 1, where 1 is the front bit of the result and 0 is taken from the input. The remaining two bits are calculated the same way.
A longer example so you can check if you understood:
Input: 115 = 1110011
Result: 1011101 = 93
Or in code:
static BigInteger calculateStepsRequired(long number) {
// Take sign bit
int bit = number < 0 ? 1 : 0;
BigInteger result = BigInteger.valueOf(bit);
for (int i = 0; i < 63; i++) {
number = number << 1;
int sign = number < 0 ? 1 : 0;
bit = (bit + sign) % 2;
result = result.shiftLeft(1).add(BigInteger.valueOf(bit));
}
return result;
}
I have checked this method against my own implementation of the first algorithm above using various inputs up to 100 000 000, and they always agree, so I believe that the fast method is correct too. I still suggest that you should code, run and test it to verify that I got it right.
At first, I tried to solve it with a recursive depth-first function (in NodeJS) but it just worked for small numbers - an input value such as 10^5 would generate a runtime error due to the number of recursive calls in the stack.
So then I tried to see how I could reduce the problem to the sum of smaller problems and found out that the number of steps for N, being N a power of 2, was
Rule #1
N * 2 - 1
(e.g.: number of steps for 2 is 3, for 32 is 63, for 256 is 511, and so on).
Then I had find what to do with any other number (that is not a power of 2) and since any integer is the sum of different powers of 2 (hence the binary representation), I only had to see if the number of steps would add up as well ... but it was not the case. However, I did find that I had to not just add the number of steps from every power of two, but to
Rule #2
subtract and add the steps in an alternate fashion, starting from the highest order digit
Demonstration
Given number 42 (101010 in binary)
Let's first apply Rule #1
1 0 1 0 1 0
^ ^ ^ ^ ^ ^
| | | | | |_ 0 steps
| | | | |___ 2*2-1 = 3 steps
| | | |_____ 0 steps
| | |_______ 2*8-1 = 15 steps
| |_________ 0 steps
|___________ 2*32-1 = 63 steps
And secondly, applying Rule #2:
63 - 15 + 3 = 51
The total number of steps is 51
Implementation (JavaScript)
function minOperations(n) {
const bin = n.toString(2);
const digitCount = bin.length;
let accumulator = 0;
let sign = 1;
for (let i = 0; i < digitCount; ++i) {
const digit = Number.parseInt(bin.charAt(i));
const power = digit > 0 ? Math.pow(2, digitCount - (i + 1)) : 0;
const steps = digit * (power * 2 - 1);
accumulator += steps * sign;
sign = sign * (digit == 0 ? 1 : -1);
}
return accumulator;
}
Here is a recursive PHP function for computing the number of steps required. It operates by noting there are two possible requirements:
convert a string to 0s (the overall requirement); and
convert a string to a 1 followed by a string of 0s (to allow flipping the preceding digit)
The second requirement is obviously an extension of the first, and so it's possible to write a recursive function which does both. It has a special case for the single digit length string, just checking if it needs to be flipped or not.
function reduce($bits, $value = '0') {
if (strlen($bits) == 1) {
// a single bit can be flipped as needed
return ($bits[0] == $value) ? 0 : 1;
}
if ($bits[0] == $value) {
// nothing to do with this bit, flip the remainder
return reduce(substr($bits, 1));
}
// need to convert balance of string to 1 followed by 0's
// then we can flip this bit, and then reduce the new string to 0
return reduce(substr($bits, 1), '1') + 1 + reduce(str_pad('1', strlen($bits) - 1, '0'));
}
Demo on 3v4l.org
This function can be adapted to store the actual steps taken, then the number of steps is just the count of that array (-1, since we put the original value in the array too). To store the steps we need to keep track of the first part of the string ($prefix in the below code) as well as the part we are reducing:
function reduce($bits, $prefix, $value = '0') {
if (strlen($bits) == 1) {
// a single bit can be flipped as needed
return array($prefix . ($bits[0] == '0' ? '1' : '0'));
}
if ($bits[0] == $value) {
// nothing to do with this bit, flip the remainder
$prefix .= $bits[0];
return reduce(substr($bits, 1), $prefix);
}
// need to convert balance of string to 1 followed by 0's
$prefix .= $bits[0];
$steps = reduce(substr($bits, 1), $prefix, '1');
// now we can flip this bit
$prefix = substr($prefix, 0, -1) . ($bits[0] == '0' ? '1' : '0');
$steps[] = $prefix . str_pad('1', strlen($bits) - 1, '0');
// now reduce the new string to 0
$steps = array_merge($steps, reduce(str_pad('1', strlen($bits) - 1, '0'), $prefix));
return $steps;
}
You can run this like so:
$bin = decbin($i);
$steps = array_merge(array($bin), reduce($bin, ''));
echo "$i ($bin) takes " . (count($steps) - 1) . " steps\n";
print_r($steps);
Output for an input of 8:
8 (1000) takes 15 steps
Array
(
[0] => 1000
[1] => 1001
[2] => 1011
[3] => 1010
[4] => 1110
[5] => 1111
[6] => 1101
[7] => 1100
[8] => 0100
[9] => 0101
[10] => 0111
[11] => 0110
[12] => 0010
[13] => 0011
[14] => 0001
[15] => 0000
)
Demo on 3v4l.org
Gray code
Looking at the steps we can see that this is actually a Gray code (Reflected Binary Code) counting from the original value down to 0. So if we generate a list of sufficient codes to cover the starting value, we can simply look for the binary representation of the starting value in that list, and that will give us the number of steps required to get back to 0:
function gray_code($bits) {
if ($bits == 1) {
return array('0', '1');
}
else {
$codes = gray_code($bits - 1);
return array_merge(array_map(function ($v) { return '0' . $v; }, $codes),
array_map(function ($v) { return '1' . $v; }, array_reverse($codes))
);
}
}
$value = 8;
$bin = decbin($value);
// get sufficient gray codes to cover the input
$gray_codes = gray_code(strlen($bin));
$codes = array_flip($gray_codes);
echo "$bin takes {$codes[$bin]} steps to reduce to 0\n";
// echo the steps
for ($i = $codes[$bin]; $i >= 0; $i--) {
echo $gray_codes[$i] . PHP_EOL;
}
Demo on 3v4l.org
If you don't need the individual steps you can just use a Gray code to binary converter to find the number of steps. This is super fast:
function gray_to_binary($value) {
$dec = $value;
for ($i = 1; $i < strlen($value); $i++) {
$dec[$i] = (int)$dec[$i-1] ^ (int)$value[$i];
}
return $dec;
}
echo bindec(gray_to_binary(decbin(115)));
Output:
93
Demo on 3v4l.org
A Gray Code Generator
We can use an iterative Gray code generator to count down the steps from our original code. The advantage of this is that it doesn't consume any memory to store the codes so it can work for very large numbers. This version uses a Gray code to binary converter that works with integers rather than strings as did the one above:
function gray_to_binary($value) {
$dec = 0;
$bits = floor(log($value, 2));
for ($i = $bits; $i >= 0; $i--) {
$dec = $dec | (((($dec >> ($i + 1)) ^ ($value >> $i)) & 1) << $i);
}
return $dec;
}
function iterate_gray($value) {
// get the equivalent starting binary value
$code = decbin($value);
yield $code;
$len = strlen($code);
$count = gray_to_binary($value);
while ($count > 0) {
// flip the bit which corresponds to the least significant 1 bit in $count
$xor = 1;
while (($count & $xor) == 0) $xor <<= 1;
$value ^= $xor;
yield sprintf("%0{$len}b", $value);
$count--;
}
}
foreach (iterate_gray(8) as $code) {
echo $code . PHP_EOL;
}
Output:
1000
1001
1011
1010
1110
1111
1101
1100
0100
0101
0111
0110
0010
0011
0001
0000
Demo on 3v4l.org
Here is a PHP implementation of Ole's "fast way" algorithm. The idea is the same:
Initialize the result with the first bit of the number (starting from the left)
For every following bit of the number, XOR it with the previous bit of the result, which gives a new bit for the result
function getBit($number, $i)
{
// Extracts bit i from number
return ($number & (1<<$i)) == 0 ? 0 : 1;
}
function minStepsRequired($number)
{
$i = 30; // Enough to handle all positive 32-bit integers
$bit = getBit($number, $i); // First bit
$res = $bit;
do
{
$i--;
$bit ^= getBit($number, $i); // Computes XOR between previous bit of the result and current bit of the number
$res = ($res<<1) + $bit; // Shifts the result to the left by 1 position and adds the new bit
}
while($i>0);
return $res;
}
var_dump(minStepsRequired(8)); // Outputs 15
var_dump(minStepsRequired(115)); // Outputs 93
It is important to notice that the first k bits, which are zeroes can be left as they are and you only start with the (k + 1)'th bit and we ignore all the starting bits, having a value of zero and always aim to increase their number. This is our primary goal and thus, we always reduce the problem-space to a similar, but smaller problem-space. Now, assuming that your number looks like
1b1b2b3...bn
you need to make sure that b1 is 1 and b2, b3, ..., bn is 0 in order to be able to modify the bit prior to b1 to 0. After that happened, you know that b2 is 1 and all the subsequent bits are 0, then the new goal is to change b2 to 0, knowing that all the subsequent bits are 0.
You can keep track of your progress with a stack which can have as much elements as many bits you are working with, always its top will represent your current goal.
So, when you want to zero your first bit, then achieving the right sequence of subsequent bits represent subtasks for you before you can change your bit and once you succeeded doing so, you need to proceed similarly, but ignoring the first bit. You can number the steps.
Assuming that a number of
1...0000000
can be zeroed in 2^n - 1 steps, the total number of steps to do equals with 2^n - 1 + the number of steps needed to achieve the combination we see above. I didn't check whether it's 2^n - 1 though
private static int reduce(String s) {
int count = 0;
char[] ch = s.toCharArray();
for (int i = ch.length - 1; i >= 0; i--) {
if (i == 0 && ch[i] == '0') {
return count - 1;
}
if (i == 0 && ch[i] == '1') {
return count + 1;
}
if (ch[i] == '0') {
count++;
} else {
count++;
ch[i] = '0';
i++;
}
}
return count;
}
def minOperations(n):
number = []
while n>0:
number.append(n%2)
n = n // 2
ans = 0
sign = 1
for i in range(len(number)):
if number[i] == 1:
ans = (2**(i+1) - 1) - ans
return ans

Trouble with ProjectEuler #15 [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Here's the problem: https://projecteuler.net/problem=15
I've come up with a pattern which I thought would work for this and I've looked at what other people have done and they've done the same thing, such as here: http://code.jasonbhill.com/python/project-euler-problem-15/ But I always get a different answer. Here's my code.
import java.util.*;
public class Problem15 {
public static void main(String[] args) {
ArrayList<Long> list = new ArrayList<Long>();
list.add((long)1);
int size;
for (int x = 1;x<20;x++){
size = list.size();
for(int y = 1;y<size;y++){
long sum = list.get(y-1)+list.get(y);
list.set(y, sum);
}
list.add(list.get(size-1)*2);
System.out.println(list);
}
}
}
edit:
In response to Edward, I think my method is currently what you said before your edit in that this isn't about brute force but I'm just summing the possible ways from each point in the grid. However, I don't need a 2d array to do this because I'm only looking at possible moves from only the side. Here's something I drew up to hopefully explain my process.
So for a 1x1. Like you said, once you reach the limit of one direction, you can only travel in the limit of the other, so there's 2 ways. This isn't particularly helpful for a 1x1 but it is for larger ones. For a 2x2, you know that the top corner, being the limit of right, only has 1 possible path from that point. The same logic applies to the bottom corner. And, because you have a square which you have already solved for, a 1x1, you know that the middle point has 2 paths from there. Now, if you look at the sides, you see that the point for instance that has 2 beneath it and 1 to the right has the sum of the number of paths in those adjacent points so then that point must have 3 paths. Same for the other side, giving the top left corner the sum of 3 and 3, or 2 times 3.
Now if you look at my code, that's what it's trying to do. The element with index 0 is always 1, and for the rest of the array, it adds together the previous term and itself and replaces the current term. Lastly, to find the total number of paths, it just doubles the last number. So if the program were to try and solve for a 4x4, the array would currently look like {1, 4, 10, 20}. So the program would change it to {1, 5, 10, 20}, then {1, 5, 15, 20}, then {1, 5, 15, 35}, and finally, adds the total number of paths, {1, 5, 15, 35, 70}. I think this is what you were trying to explain to me in your answer however my answer always comes out incorrect.
Realize that it's more about mathematical complexity than brute force searching.
You have a two dimensional array of points, where you can chose to only travel away from the origin in the x or the y direction. As such, you can represent your travel like so:
(0, 0), (1, 0), (1, 1), (2, 1), (2, 2)
some things become immediately obvious. The first one is that any path through the mess is going to require x + y steps, travelling through x + y + 1 locations. It is a feature of a Manhattan distance style path.
The second is that at any one point until you hit the maximum x or y, you can select either of the two options (x or y); but, as soon as one or the other is at it's limit, the only option left is to chose the non-maximum value repeatedly until it also becomes a maximum.
With this you might have enough of a hint to solve the math problem. Then you won't even need to search through the different paths to get an algorithm that can solve the problem.
--- edited to give a bit more of a hint ---
Each two dimensional array of paths can be broken down into smaller two dimensional arrays of paths. So the solution to f(3, 5) where the function f yields the number of paths is equal to f(2, 5) + f(3, 4). Note that f(0, 5) directly equals 1, as does f(3, 0) because you no longer have "choices" when the paths are forced to be linear.
Once you model the function, you don't even need the array to walk the paths....
f(1, 1) = f(0, 1) + f(1, 0)
f(0, 1) = 1
f(1, 0) = 1
f(1, 1) = 1 + 1
f(1, 1) = 2
and for a set of 3 x 3 verticies (like the example cited has)
f(2, 2) = f(1, 2) + f(2, 1)
f(1, 2) = f(0, 1) + f(1, 1)
(from before)
f(1, 1) = 2
f(0, 2) = 1
f(1, 2) = 2 + 1 = 3
likewise (because it's the mirror image)
f(2, 1) = 1 + 2 = 3
so
f(2, 2) = 3 + 3 = 6
--- last edit (I hope!) ---
Ok, so now you may get the idea that you have really two choices (go down) or (go right). Consider a bag containing four "commands", 2 of "go down" and 2 of "go right". How many different ways can you select the commands from the bag?
Such a "selection" is a permutation, but since we are selecting all of them, it is a special type of permutation called an "order" or "ordering".
The number of binomial (one or the other) orderings is ruled by the mathematical formula
number of orderings = (A + B)!/(A! * B!)
where A is the "count" of items of type A, and B is the "count" of items of type B
3x3 vertices, 2 down choices, 2 right choices
number of orderings = (2+2)!/2!*2!
4!/1*2*1*2
1*2*3*4/1*2*1*2
(1*2)*3*4/(1*2)*1*2
3*4/2
12/2
6
You could probably do a 20*20 by hand if you needed, but the factorial formula is simple enough to do by computer (although keep an eye you don't ruin the answer with an integer overflow).
Another implementation:
public static void main(String[] args) {
int n = 20;
long matrix[][] = new long[n][n];
for (int i = 0; i < n; i++) {
matrix[i][0] = i + 2;
matrix[0][i] = i + 2;
}
for (int i = 1; i < n; i++) {
for (int j = i; j < n; j++) { // j>=i
matrix[i][j] = matrix[i - 1][j] + matrix[i][j - 1];
matrix[j][i] = matrix[i][j]; // avoids double computation (difference)
}
}
System.out.println(matrix[n - 1][n - 1]);
}
Time: 43 microseconds (without printing)
It is based on the following matrix:
| 1 2 3 4 ...
---------------------
1 | 2 3 4 5 ...
2 | 3 6 10 15
3 | 4 10 20 35
4 | 5 15 35 70
. | .
. | .
. | .
where
6 = 3 + 3
10 = 6 + 4
15 = 10 + 5
...
70 = 35 + 35
Notice that I used i + 2 instead of i + 1 in the implementation because the first index is 0.
Of course, the fastest solution is to use a mathematical formula (see Edwin's post) and the code for it:
public static void main(String[] args) {
int n = 20;
long result = 1;
for ( int i = 1 ; i <= n ; i++ ) {
result *= (i+n);
result /= i;
}
System.out.println(result);
}
takes only 5 microseconds (without printing).
If you are afraid about the loss of precision, notice that the product of n consecutive numbers is divisible by n!.
To have a better understanding why the formula is:
(d+r)!
F = --------- , where |D| = d and |R| = r
d!*r!
instead of F = (d+r)!, imagine that every "down" and "right" has an index:
down1,right1,right2,down2,down3,right3
The second formula counts all possible permutations for the "commands" above, but in our case there is no difference between down1, down2 and down3. So, the second formula will count 6 (3!) times the same thing:
down1,down2,down3
down1,down3,down2
down2,down1,down3
down2,down3,down1
down3,down1,down2
down3,down2,down1
This is why we divide the (d+r)! by d!. Analogue for r!.

A mathematical function that gets us the number of leaves of a specific type of k-ary?

I am trying to figure out a function f(x) that would calculate the number of leaves in a k-ary tree. For example, assume we created a tree that began with root 4 with 3 children, each of -1,-2,-3 respectively. Our leaves would only be 0 values, not null values. I have spent the past day trying to figure out a function and it seems like nothing I do goes in the correct direction.
EX:
4
/ | \
3 2 1
/ |\ /| /
2 1 0 1 0 0
/| / /
1 0 0 0
/
0
7 Leaves.
Any help would be very much appreciated! Thanks!
To clarify, I need a mathematical equation that derives the same answer as code would if I recursively transversed the tree.
More examples:
{4,7}{5,13}{6,24}{7,44}{8,81}{9,149}{10,274}{11,504}{12,927}{13,1705}{14,3136}{15,5768}{16,10609}{17,19513}{18,35890}{19,66012}{20,121415}
public int numleaves(TreeNode node) {
if (node == null)
return 0;
else if (node.getLeft() == null && node.getMiddle() == null && node.getRight() == null)
return 1;
else
return numleaves(node.getLeft()) + numleaves(node.getMiddle()) + numleaves(node.getRight());
}
I cannot answer your question, but it has a solution. I can only outline the case for the number of children k being equal to 2. The case k=3 leads to a cubic polynomial with two complex and one real solution, I lack the tools here to derive them in a non-numerical way.
But let's have a look at the case k=2. Interestingly, this problem is very closely related to the Fibonacci numbers, except for having different boundary conditions.
Writing down the recursive formula is easy:
a(n) = a(n-1) + a(n-2)
with boundary conditions a(1)=1 and a(0)=1. The characteristic polynomial of this is
x^2 = x + 1
with the solutions x1 = 1/2 + sqrt(5)/2 and x2 = 1/2 - sqrt(5)/2. It means that
a(n) = u*x1^n + v*x2^n
for some u and v is the explicit formula for the sequence we're looking for. Putting in the boundary conditions we get
u = (sqrt(5)+1)/(2*sqrt(5))
v = (sqrt(5)-1)/(2*sqrt(5))
i.e.
a(n) = (sqrt(5)+1)/(2*sqrt(5))*(1/2 + sqrt(5)/2)^n + (sqrt(5)-1)/(2*sqrt(5))*(1/2 - sqrt(5)/2)^n
for k=2.
Your code seems to be computing a Tribonacci sequence with starting values 1, 1 and 2. This is sequence A000073 from the On-Line Encyclopedia of Integer Sequences, starting from the third entry of that sequence rather than the first. The comments section of the encyclopedia page gives an explicit formula: since this is a linear recurrence relation with a degree 3 characteristic polynomial, there's a closed form solution in terms of the roots of that polynomial. Here's a short piece of Python 2 code based on the given formula that produces the first few values. (See the edit below for a simplification.)
from math import sqrt
c = (1 + (19 - 3 * sqrt(33))**(1/3.) + (19 + 3 * sqrt(33))**(1/3.)) / 3.
m = (1 - c) / 2
p = sqrt(((3*c - 5)*(c+1)/4))
j = 1/((c-m)**2 + p**2)
b = (c - m) / (2 * p*((c - m)**2 + p**2))
k = complex(-j / 2, b)
r1 = complex(m, p)
def f(n):
return int(round(j*c**(n+2) + (2*k*r1**(n+2)).real))
for n in range(0, 21):
print n, f(n)
And the output:
0 1
1 1
2 2
3 4
4 7
5 13
6 24
7 44
8 81
9 149
10 274
11 504
12 927
13 1705
14 3136
15 5768
16 10609
17 19513
18 35890
19 66012
20 121415
EDIT: the above code is needlessly complicated. With the round operation, the second term in f(n) can be omitted (it converges to zero as n increases), and the formula for the first term can be simplified. Here's some simpler code that generates the same output.
s = (19 + 297**0.5)**(1/3.)
c = (1 + s + 4/s)/3
j = 3 - (2 + 1/c)/c
for n in range(0, 32):
print n, int(round(c**n / j))
I can't help it, but I see Binomial tree in it. http://en.wikipedia.org/wiki/Binomial_heap
I think that good approximation could be sum of k-th row of pascal triangle, where k stands for the number of the root node.
Isn't this easier to understand:
We set the starting values for the tribonacci sequence into a list called result. Then we put these values into 3 variables. We change the variable content based on the tribonacci formula (new a is a+b+c, new b is old a, new c is old b). Then we calculate to whatever tribonacci number we want to go up to and store each result into our result list. At the end, we read out the indexed list.
result=[1,1,2]
a,b,c=result[-1],result[-2],result[-3]
for i in range(40):
a,b,c=a+b+c,a,b
result.append(a)
for e,f in enumerate(result):
print e,f

Categories

Resources