Why HashMap insert new Node on index (n - 1) & hash? - java

Why HashMap insert new Node on the index:
tab[(n - 1) & hash]
Where hash = key.hashCode() ^ key.hashCode() >>> 16
And n = tab.length of array of Node<K,V>.
Why HashMap not put the Node just like that: tab[hash] ? Is it just another hashing function, like multiplication by 31 in most of hashCode() methods ?
Thanks in advance for explanation!

A good description by harold but I feel it is inadequate without an example. So heres one -
Whenever a new Hasmap is created the array size of internal Node[] table is always power of 2 and following method guarantees it -
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
So lets say you provide initial capacity as 5
cap = 5
n = cap - 1 = 4 = 0 1 0 0
n |= n >>> 1; 0 1 0 0 | 0 0 1 0 = 0 1 1 0 = 6
n |= n >>> 2; 0 0 1 1 | 0 1 1 0 = 0 1 1 1 = 7
n |= n >>> 4; 0 0 0 0 | 0 1 1 1 = 0 1 1 1 = 7
n |= n >>> 8; 0 0 0 0 | 0 1 1 1 = 0 1 1 1 = 7
n |= n >>> 16; 0 0 0 0 | 0 1 1 1 = 0 1 1 1 = 7
return n + 1 7 + 1 = 8
So table size is 8 = 2^3
Now possible index values you can put your element in map are 0-7 since table size is 8. Now lets look at put method. It looks for bucket index as follows -
Node<K,V> p = tab[i = (n - 1) & hash];
where n is the array size. So n = 8. It is same as saying
Node<K,V> p = tab[i = hash % n];
So all we need to see now is how
hash % n == (n - 1) & hash
Lets again take an example. Lets say hash of a value is 10.
hash = 10
hash % n = 10 % 8 = 2
(n - 1) & hash = 7 & 10 = 0 1 1 1 & 1 0 1 0 = 0 0 1 0 = 2
Hope this helps. More details
PS: Above link goes to my blog that has a more details example explanation on this.

Because hash may be out of range.
The "canonical solution" is to take the (positive) modulo of the hash with the length of the array, this code uses the fact that the array has a power-of-two length to replace an expensive modulo by a variable (modulo a constant is optimized pretty well) with a cheap bitwise AND.

Related

Java - Bit manipulation (count number of 1s in number)

Can someone explain to my why this method works, I've worked through what it does, but why does this work. Is there a pattern that binary numbers have? Like for example at i = 3, why does it do res[1] + 1 to get 2. How does res[3 >> 1] + (3&1) help to count the number of ones in the binary number of 3?
What the code should do: It works so don't worry about that. It is supposed to return a list that contains the number of ones in the binary representation of each number until num+1. And num is always >= 0. So for num = 5, you would get [0, 1, 1, 2, 1, 2], where the last index represents the number of 1s in the binary representation of 5, and the first index is number of ones in binary rep of 0.
Code:
public int[] countBits(int num) {
int[] res = new int[num+1];
for (int i = 0; i<num+1; i++){
res[i] = res[i >> 1] + (i & 1);
}
return res;
}
This is the part I can't wrap my head around:
res[i] = res[i >> 1] + (i & 1);
EDIT - This is not homework, so please fully explain your answer. This is to help with interviews.
int[] res = new int[num+1];
for (int i = 0; i<num+1; i++){
res[i] = res[i >> 1] + (i & 1);
}
return res;
rewritten as
int[] res = new int[num+1];
for (int i = 0; i<num+1; i++){
x = res[i >> 1];
y = (i & 1);
res[i] = x + y;
}
return res;
Create an array to fit the answers, +1?
for each, starting at the low end.
res[0] = res[0] + 0&1 = 0 + 0 = 0;
res[1] = res[0] + 1&1 = 0 + 1 = 1;
res[2] = res[1] + 0&1 = 1 + 0 = 0;
res[3] = res[1] + 1&1 = 1 + 1 = 2;
Looking at this pattern, I can see that because of the right shift, and the masking with &, it's splitting the problem into 2, one that's been solved previously due to the iteration order, and a bit check of the last digit.
assuming a 8 bit int, for brevity,
1 = 00000001
2 = 00000010
3 = 00000011
Split the binary into parts.
i i>>1 y&1
1 = 0000000 1
2 = 0000001 0
3 = 0000001 1
So it fetches the results for the number of ones in the first half of the array, then counts the last digit.
Because of the iteration order, and array initialisation values, this is guaranteed to work.
For values < 0 , due to 2's compliment it gets hairy, which is why it only works for values >=0
in 'res[i] = res[i >> 1] + (i & 1);'
one number's result is divide into 2 parts
the last bit is 1 or not,which can be calculate by (i & 1).
the first (n-1) bits,this number is equals to res[i >> 1]'s bitcount.this is a simple recursive call
shift by 1 gives the floor number divided by 2.
AND 1 returns 1 if the last bit of the number is 1
Hope the below table helps to see what is happening :) Just my 2 cents.
<pre>
--------------------------------
<b>
# 8 4 2 1 >>1 &1 Ans
</b>
-------------------------------
0 0 0 0 0 0 0 0
1 0 0 0 1 0 1 1
2 0 0 1 0 1 0 1
3 0 0 1 1 1 1 2
4 0 1 0 0 2 0 1
5 0 1 0 1 2 1 2
6 0 1 1 0 3 0 2
7 0 1 1 1 3 1 3
8 1 0 0 0 4 0 1
9 1 0 0 1 4 1 2
10 1 0 1 0 5 0 2
11 1 0 1 1 5 1 3
12 1 1 0 0 6 0 2
13 1 1 0 1 6 1 3
14 1 1 1 0 7 0 3
15 1 1 1 1 7 1 4
</pre>

How can I round up to the nearest multiple of the specified number?

I've looked at many questions regarding rounding up to the nearest multiple of a number, but I can't understand their methods well enough to adopt them for rounding up to 45 or they use language specific methods of other languages.
Here is a bit more detailed explanation if the above doesn't make much sense yet:
Example input:
int num1 = 67;
int num2 = 43;
Expected results:
>>round(num1) = 90
>>round(num2) = 45
It's enough to add the missing mod45:
int upperround45(int i) {
int temp = i%45;
//For the algorithm we wish the rest to be how much more than last multiple of 45.
if (temp < 0 )
temp = 45 + temp;
if (temp == 0) {
return i;
} else {
return i + 45 - temp;
}
}
EDIT:
In general:
int upperround(int num, int base) {
int temp = num%base;
if (temp < 0 )
temp = base + temp;
if (temp == 0)
return num;
return num + base - temp;
Since people have such trouble with rounding to multiple of an integer number, whether rounding up/down/nearest, here are very simple methods for doing so:
public static int roundDown(int value, int multiplier) {
return value / multiplier * multiplier;
}
public static int roundHalfUp(int value, int multiplier) {
return (value + multiplier / 2) / multiplier * multiplier;
}
public static int roundUp(int value, int multiplier) {
return (value + multiplier - 1) / multiplier * multiplier;
}
Test
Value Down Half Up
0 0 0 0
1 0 0 4
2 0 4 4
3 0 4 4
4 4 4 4
Value Down Half Up
0 0 0 0
1 0 0 5
2 0 0 5
3 0 5 5
4 0 5 5
5 5 5 5
Negative Numbers
They don't work right for negative numbers. "Round down" usually means "towards zero", unlike Math.floor() which rounds towards negative infinity.
Here are versions that can handle negative values. These are consistent with the RoundingMode options of similar names used by BigDecimal.
public static int roundDown(int value, int multiplier) {
if (multiplier <= 0) throw new IllegalArgumentException();
return value / multiplier * multiplier;
}
public static int roundHalfUp(int value, int multiplier) {
if (multiplier <= 0) throw new IllegalArgumentException();
return (value + (value < 0 ? multiplier / -2 : multiplier / 2)) / multiplier * multiplier;
}
public static int roundUp(int value, int multiplier) {
if (multiplier <= 0) throw new IllegalArgumentException();
return (value + (value < 0 ? 1 - multiplier : multiplier - 1)) / multiplier * multiplier;
}
Test
Value Down Half Up
-4 -4 -4 -4
-3 0 -4 -4
-2 0 -4 -4
-1 0 0 -4
0 0 0 0
1 0 0 4
2 0 4 4
3 0 4 4
4 4 4 4
Value Down Half Up
-5 -5 -5 -5
-4 0 -5 -5
-3 0 -5 -5
-2 0 0 -5
-1 0 0 -5
0 0 0 0
1 0 0 5
2 0 0 5
3 0 5 5
4 0 5 5
5 5 5 5
The easiest way I can think of is the following
public static int round(int num) {
return num - num % 45 + (num%45==0? 0 : 45);
}
Tested
int num1 = 67;
int num2 = 43;
int num3 = 90;
System.out.println(num1 - num1 % 45 + (num1%45==0? 0 : 45)); // 90
System.out.println(num2 - num2 % 45 + (num2%45==0? 0 : 45)); // 45
System.out.println(num3 - num3 % 45 + (num3%45==0? 0 : 45)); // 90

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

Java modulus if number on left is smaller than number on right?

What would (0 + 1) % 10? return? How do you deal with numbers on the left being smaller than numbers on the right? How is this even possible?
The modulo is the remainder of an integer division. Say you have integers a and b.
n = a / b (integer), and
m = a % b = a - ( b * n )
Then
b * n + m = a
Examples:
a b n = a/b b * n m = a%b
0 5 0 0 0
1 5 0 0 1
2 5 0 0 2
3 5 0 0 3
4 5 0 0 4
5 5 1 5 0
6 5 1 5 1
....
10 5 2 10 0
12 5 2 10 2
etc.
Basically, the integer division determines how many times b fully fits inside a. If b < a, that's zero times. The modulo operation then returns what is left. If b < a, that's a.
(0 + 1) % 10 would return 1
What is making you confused about small and large numbers in an expression?

Funny unsigned in java

I found the unsigned integer is so straight in Java. If I want to present the 0xFXXX XXXX, Java requires me to declare a long variable to store the 0xFXXX XXXX, and do a bitwise AND operation with the 4294967295(0xFFFFFFFFL).
Any one could share your experiences about the unsigned problem to others or me?
Java uses the most common method of representing signed integers - Two's complement
Might want to check this out: http://www.javamex.com/java_equivalents/unsigned.shtml
C++:
unsigned byte b = ...;
b += 100;
unsigned int v = ...;
v *= 2;
Java equivalent:
int b = ...;
b = (b + 100) & 0xff;
long v = ...;
v = (v * 2) & 0xffffffffL;
When you come to using the unsigned value, cast it to the type you want, and it will wrap naturally, giving you the correct value:
// Example: write an unsigned int (stored in a long)
// to a byte buffer.
ByteBuffer bb = ...
long unsignedInt = ...
bb.putInt((int) unsignedInt);
In java integers are 32 bits long; however, the first bit is for sign. In effect, integers are only 31 bits long.
Your number is positive 32 bit long digit; therefore, it cannot fit into integer, thus need a long.
EDIT: Why the downvote?!
Integers are represented as 2's complement, for simple 8 bit word:
MSB
0 1 1 1 1 1 1 1 = 127
0 1 1 1 1 1 1 0 = 126
0 0 0 0 0 0 1 0 = 2
0 0 0 0 0 0 0 1 = 1
0 0 0 0 0 0 0 0 = 0
1 1 1 1 1 1 1 1 = −1
1 1 1 1 1 1 1 0 = −2
1 0 0 0 0 0 0 1 = −127
1 0 0 0 0 0 0 0 = −128
MSB, the first digit effectively indicates the sign
Edit 2: I am tired of discussing a moot point. Before downvoting, refer to this

Categories

Resources