Detecting Common Elements in an Unsorted Array [closed] - java

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I found a code which will detect common elements in an unsorted array. The program runs in linear time! But i did not understand the logic of the program. It would be very helpful if some one could explain the logic of the program.
Here is the code:
public class DeleteUnsortedDataFromArray {
public static List<Integer> findDuplicatesArray(int[] sequence){
int bitarray = 0;
for(int i=0; i< sequence.length; i++){
int x = 1;
x = x << sequence[i];
if((bitarray & x) != 0){
System.out.println("Duplicate found in given array: " + sequence[i]);
} else {
bitarray = bitarray | x;
}
}
return null;
}
public static void main(String[] args) {
int[] input = {1,1,2,3};
findDuplicatesArray(input);
}
}

What it does is to represent each found value as an 1 in a position of the bits composing an integer (bitarray).
The lines:
x = 1;
x = x << sequence[i];
Will put a 1 at the position given by the sequence value+1 (<< is a shift operator).
For example, if sequence[i] value is four, x will have the binary value: ...010000
The line:
(bitarray & x) != 0
Uses bit operation AND to check if a position has been already occupied and hence the valued found.
The problem is that this algorithm only works if your values at sequence are constrained to be low: Between 0 and 30 as there are 32 bits in an Java integer and the value 0 is represented as a 1 at the position 0 of bitarray.
You should consider too what happens when the sequence values are negative.

It works only as long as all values in the array belong to [0, number-of-bits-in-int). If of course you can say 'works' about a function that is supposed to return list of duplicates but always returns null.

You can understand the algorithm as using an array of booleans to test whether a value has occured previously in the array or not. Now instead of using an array of booleans, what you are doing is using the bits in an int to represent whether a value has occured previously or not. The code calls this "bitarray".
To set the Ith bit in an int, you use
x = (x | (1<< i));
Here '|' is the bitwise or operator.
And to test whether the Ith bit has been set you check the condition
if((x & (1<< i)) != 0){
}
here '&' is the bitwise and operator.
Moreover, the algorithm used above will only work if the range of values in the array is between 0 and 31 inclusive. That's because java ints are represented using 32 bits. However it consumes lesser space than other alternatives like using a HashSet or an explicit array of booleans.
However, if space is at a premium, and you know that the range of data in the array is small, you can consider using Bitset class (link).

Related

Same logic code with same data type code passes in Java but not in C++?

I was solving a leetcode question where we have to find the number of set possible that adds to a target.
Given an integer array with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target.
I wrote the code in Java
JAVA
class Solution {
public int combinationSum4(int[] nums, int target) {
int[] dp = new int[target+1];
dp[0] = 1;
for(int i = 1; i <= target; i++){
for(int num : nums){
if(i >= num){
dp[i] += dp[i-num];
}
}
}
return dp[target];
}
}
It passed all the test cases, but when I wrote the same code in C++. Its failing few of the test cases.
C++
class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
int dp[target+1] = {0};
dp[0] = 1;
for(int i = 1; i <= target; i++){
for(int num : nums){
if(i >= num){
dp[i] += dp[i-num];
}
}
}
return dp[target];
}
};
The test case being :
nums : [3,33,333]
target : 10000
Error that I am getting :
Line 9: Char 27: runtime error: signed integer overflow: 1941940377 + 357856184 cannot be represented in type 'int' (solution.cpp)
Note : In the code I have only changed the declaration of dp array part as you can see. Why am I getting this error. Whats going wrong?
The int at leetcode seems to be 32 bits which can usually represent numbers in the range [-2^31, 2^31).
Overflowing signed integers has undefined behaviour in C++. A signed 32 bit int have different representations on different platforms. You'll most often find the Two's complement version, but there are others.
2^31-1 = 2147483647
1941940377 + 357856184 = 2299796561 // overflow error in C++
Add (if needed)
#include <cstdint>
and replace
int dp[target+1] = {0};
with
std::vector<std::uintmax_t> dp(target+1, 0);
std::uintmax_t gives you the largest unsigned integer type available and overflowing unsigned integers has a well defined behaviour in C++, so even if you do end up with a calculation larger than the limit, say 18446744073709551615 for a 64 bit integer, it will just wrap around. 18446744073709551615 + 1 == 0 in that case.
In Java, overflowing an int has well defined behaviour.
2147483647 + 1 = -2147483648
which is why you don't get in trouble when using that code in Java.
While #TedLyngmo's answer seems to have correctly identified the problem, I disagree about the solution.
You should not just ignore overflow, even if its behavior is well defined. The coding problem you were given is in itself flawed, as, indeed, the number of possible additive decompositions of an integer increases exponentially with the value of that integer, meaning the size of the output is at least some linear function of the value of the input number - and that means any fixed-size type will be inappropriate.
If you actually wanted to solve this problem and produce correct output without overflow, you would need a "big int" class - something which can hold arbitrarily-large values.
Here's an example C++ BigInt implementation:
https://github.com/kasparsklavins/bigint
There are others, of course (but there isn't one in the standard library).

How can I get the position of bits

I have a decimal number which I need to convert to binary and then find the position of one's in that binary representation.
Input is 5 whose binary is 101 and Output should be
1
3
Below is my code which only provides output as 2 instead I want to provide the position of one's in binary representation. How can I also get position of set bits starting from 1?
public static void main(String args[]) throws Exception {
System.out.println(countBits(5));
}
private static int countBits(int number) {
boolean flag = false;
if (number < 0) {
flag = true;
number = ~number;
}
int result = 0;
while (number != 0) {
result += number & 1;
number = number >> 1;
}
return flag ? (32 - result) : result;
}
Your idea of having countBits return the result, instead of putting a System.out.println inside the method, is generally the best approach. If you want it to return a list of bit positions, the analogue would be to have your method return an array or some kind of List, like:
private static List<Integer> bitPositions(int number) {
As I mentioned in my comments, you will make life a lot easier for yourself if you use >>> and get rid of the special code to check for negatives. Doing this, and adapting the code you already have, gives you something like
private static List<Integer> bitPositions(int number) {
List<Integer> positions = new ArrayList<>();
int position = 1;
while (number != 0) {
if (number & 1 != 0) {
positions.add(position);
}
position++;
number = number >>> 1;
}
return positions;
}
Now the caller can do what it wants to print the positions out. If you use System.out.println on it, the output will be [1, 3]. If you want each output on a separate line:
for (Integer position : bitPositions(5)) {
System.out.println(position);
}
In any case, the decision about how to print the positions (or whatever else you want to do with them) is kept separate from the logic that computes the positions, because the method returns the whole list and doesn't have its own println.
(By the way, as Alex said, it's most common to think of the lower-order bit as "bit 0" instead of "bit 1", although I've seen hardware manuals that call the low-order bit "bit 31" and the high-order bit "bit 0". The advantage of calling it "bit 0" is that a 1 bit in position N represents the value 2N, making things simple. My code example calls it "bit 1" as you requested in your question; but if you want to change it to 0, just change the initial value of position.)
Binary representation: Your number, like anything on a modern day (non-quantum) computer, is already a binary representation in memory, as a sequence of bits of a given size.
Bit operations
You can use bit shifting, bit masking, 'AND', 'OR', 'NOT' and 'XOR' bitwise operations to manipulate them and get information about them on the level of individual bits.
Your example
For your example number of 5 (101) you mentioned that your expected output would be 1, 3. This is a bit odd, because generally speaking one would start counting at 0, e.g. for 5 as a byte (8 bit number):
76543210 <-- bit index
5 00000101
So I would expect the output to be 0 and 2 because the bits at those bit indexes are set (1).
Your sample implementation shows the code for the function
private static int countBits(int number)
Its name and signature imply the following behavior for any implementation:
It takes an integer value number and returns a single output value.
It is intended to count how many bits are set in the input number.
I.e. it does not match at all with what you described as your intended functionality.
A solution
You can solve your problem using a combination of a 'bit shift' (>>) and an AND (&) operation.
int index = 0; // start at bit index 0
while (inputNumber != 0) { // If the number is 0, no bits are set
// check if the bit at the current index 0 is set
if ((inputNumber & 1) == 1)
System.out.println(index); // it is, print its bit index.
// advance to the next bit position to check
inputNumber = inputNumber >> 1; // shift all bits one position to the right
index = index + 1; // so we are now looking at the next index.
}
If we were to run this for your example input number '5', we would see the following:
iteration input 76543210 index result
1 5 00000101 0 1 => bit set.
2 2 00000010 1 0 => bit not set.
3 1 00000001 2 1 => bit set.
4 0 00000000 3 Stop, because inputNumber is 0
You'll need to keep track of what position you're on, and when number & 1 results in 1, print out that position. It look something like:
...
int position = 1;
while (number != 0) {
if((number & 1)==1)
System.out.println(position);
result += number & 1;
position += 1;
number = number >> 1;
}
...
There is a way around working with bit-wise operations to solve your problem.
Integer.toBinaryString(int number) converts an integer to a String composed of zeros and ones. This is handy in your case because you could instead have:
public static void main(String args[]) throws Exception {
countBits(5);
}
public static void countBits(int x) {
String binaryStr = Integer.toBinaryString(x);
int length = binaryStr.length();
for(int i=0; i<length; i++) {
if(binaryStr.charAt(i)=='1')
System.out.println(length-1);
}
}
It bypasses what you might be trying to do (learn bitwise operations in Java), but makes the code look cleaner in my opinion.
The combination of Integer.lowestOneBit and Integer.numberOfTrailingZeros instantly gives the position of the lowest 1-Bit, and returns 32 iff the number is 0.
Therefore, the following code returns the positions of 1-Bits of the number number in ascending order:
public static List<Integer> BitOccurencesAscending(int number)
{
LinkedList<Integer> out = new LinkedList<>();
int x = number;
while(number>0)
{
x = Integer.lowestOneBit(number);
number -= x;
x = Integer.numberOfTrailingZeros(x);
out.add(x);
}
return out;
}

Printing PowerSet with help of bit position

Googling around for a while to find subsets of a String, i read wikipedia and it mentions that
.....For the whole power set of S we get:
{ } = 000 (Binary) = 0 (Decimal)
{x} = 100 = 4
{y} = 010 = 2
{z} = 001 = 1
{x, y} = 110 = 6
{x, z} = 101 = 5
{y, z} = 011 = 3
{x, y, z} = 111 = 7
Is there a possible way to implement this through program and avoid recursive algorithm which uses string length?
What i understood so far is that, for a String of length n, we can run from 0 to 2^n - 1 and print characters for on bits.
What i couldn't get is how to map those on bits with the corresponding characters in the most optimized manner
PS : checked thread but couldnt understood this and c++ : Power set generated by bits
The idea is that a power set of a set of size n has exactly 2^n elements, exactly the same number as there are different binary numbers of length at most n.
Now all you have to do is create a mapping between the two and you don't need a recursive algorithm. Fortunately with binary numbers you have a real intuitive and natural mapping in that you just add a character at position j in the string to a subset if your loop variable has bit j set which you can easily do with getBit() I wrote there (you can inline it but for you I made a separate function for better readability).
P.S. As requested, more detailed explanation on the mapping:
If you have a recursive algorithm, your flow is given by how you traverse your data structure in the recursive calls. It is as such a very intuitive and natural way of solving many problems.
If you want to solve such a problem without recursion for whatever reason, for instance to use less time and memory, you have the difficult task of making this traversal explicit.
As we use a loop with a loop variable which assumes a certain set of values, we need to make sure to map each value of the loop variable, e.g. 42, to one element, in our case a subset of s, in a way that we have a bijective mapping, that is, we map to each subset exactly once. Because we have a set the order does not matter, so we just need whatever mapping that satisfies these requirements.
Now we look at a binary number, e.g. 42 = 32+8+2 and as such in binary with the position above:
543210
101010
We can thus map 42 to a subset as follows using the positions:
order the elements of the set s in any way you like but consistently (always the same in one program execution), we can in our case use the order in the string
add an element e_j if and only if the bit at position j is set (equal to 1).
As each number has at least one digit different from any other, we always get different subsets, and thus our mapping is injective (different input -> different output).
Our mapping is also valid, as the binary numbers we chose have at most the length equal to the size of our set so the bit positions can always be assigned to an element in the set. Combined with the fact that our set of inputs is chosen to have the same size (2^n) as the size of a power set, we can follow that it is in fact bijective.
import java.util.HashSet;
import java.util.Set;
public class PowerSet
{
static boolean getBit(int i, int pos) {return (i&1<<pos)>0;}
static Set<Set<Character>> powerSet(String s)
{
Set<Set<Character>> pow = new HashSet<>();
for(int i=0;i<(2<<s.length());i++)
{
Set<Character> subSet = new HashSet<>();
for(int j=0;j<s.length();j++)
{
if(getBit(i,j)) {subSet.add(s.charAt(j));}
}
pow.add(subSet);
}
return pow;
}
public static void main(String[] args)
{System.out.println(powerSet("xyz"));}
}
Here is easy way to do it (pseudo code) :-
for(int i=0;i<2^n;i++) {
char subset[];
int k = i;
int c = 0;
while(k>0) {
if(k%2==1) {
subset.add(string[c]);
}
k = k/2;
c++;
}
print subset;
}
Explanation :- The code divides number by 2 and calculates remainder which is used to convert number to binary form. Then as you know only selects index in string which has 1 at that bit number.

Interesting thing happening when I take a number, multiply it by 10, and then add 1 [duplicate]

This question already has answers here:
Multiplication of two ints overflowing to result in a negative number
(5 answers)
Closed 9 years ago.
static int fn = 0;
static int sn = 0;
static boolean running = false;
public static void run()
{
while (running == true)
{
fn = numbers[0];
sn = numbers[1];
if (sign == 0)
{
input.setText(String.valueOf(fn));
}
}
}
static class one implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if (Display.sign == 0)
{
Display.numbers[0] = Display.numbers[0] *10;
Display.numbers[0] = Display.numbers[0] +1;
}
}
}
This is the code for a calculator that I am programming (not all of it of course). This is the part where I display the number on the screen which I have done, but weirdly this works up until 10 characters
So after I get the program to display 1111111111 I want to do it once more and it gives me this weird number -1773790777. I am confused about how the program comes up with this. As you can see, above Display.numbers[] is the array I am storing the two numbers in. So to go over a place I multiply the number in the array by 10 then add 1. So how does this give me a negative number in the first place and what can I do to solve this problem?
Is your number overflowing?
You can check it by looking at Integer.MAX_VALUE (assuming you are using an integer). If you go over that you will loop will get weird results like this. See - http://javapapers.com/core-java/java-overflow-and-underflow/ for more details.
It's overflowing!
1111111111*10 + 1 = 11111111111 which is 0x2964619C7 in hexadecimal. It's a 34-bit value which can't be stored in a 32-bit int
In Java arithmetic operations wrap around by default, so if the result overflowed then it'll be wrapped back to the other end of the value range. See How does Java handle integer underflows and overflows and how would you check for it?
However due to the use of 2's complement, the result will be the lower bits of the result 11111111111 mod 232 = 2521176519 = 0x964619C7 which is -1'773'790'777 in 32-bit int, that's why you see the number. You should read more on binary, that's the basic of nowadays computers
In Java 8 you'll have an easier way to detect overflow with the new *Exact methods
The platform uses signed two's complement integer arithmetic with int and long primitive types. The developer should choose the primitive type to ensure that arithmetic operations consistently produce correct results, which in some cases means the operations will not overflow the range of values of the computation. The best practice is to choose the primitive type and algorithm to avoid overflow. In cases where the size is int or long and overflow errors need to be detected, the methods addExact, subtractExact, multiplyExact, and toIntExact throw an ArithmeticException when the results overflow. For other arithmetic operations such as divide, absolute value, increment, decrement, and negation overflow occurs only with a specific minimum or maximum value and should be checked against the minimum or maximum as appropriate.
https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html

Custom number in Java [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 create a custom number class in java, which after ranging from 000000 to 099999 would continue with 0A0000. So the last number would be 9Z9999.
I'm a bit lost on how I could implement this in Java. I suppose I would need to create a custom class which extends Number.
My goal would be to create a class on which I could iterate through (from 000000 to 9Z9999) to reserve document ID ranges.
Although I could do achieve this end with several other workarounds, I find this to be the cleanest solution.
Thank you for any help in advance.
This seems to work. Just use an ordinary number and format it:
static String asStrangeNumber ( int i ) {
// Lowest 4 digits are decimal.
int low4 = i%10000;
i /= 10000;
// Next is base 36 - 0-9-A-Z
int c = i % 36;
i /= 36;
// Remaining should be < 10.
return String.format("%1d%c%04d", i%10, c < 10 ? '0' + c: 'A' + c - 10, low4);
}
public void test() {
test (0);
test (1);
test (10);
test (100);
test (1000);
test (10000);
test (100000);
test (1000000);
}
private void test(int i) {
System.out.println(" "+i+" -> "+asStrangeNumber(i));
}
prints
0 -> 000000
1 -> 000001
10 -> 000010
100 -> 000100
1000 -> 001000
10000 -> 010000
100000 -> 0A0000
1000000 -> 2S0000
I don't think it makes sense. Number defines methods like intValue() etc., and how can you convert 0Z0000 to int?
Just create your own CustomId class, but don't extend Number.
The simplest way to do this is to create a single class that gives out IDs (note these are not numbers per se but words). This would contain 6 counters, each of which had a maximum value (9 for 5 of them 36 for the remaining one that has numbers and letters).
When each new ID is requested the bottom counter is increased, when it reaches it's maximum value it resets to zero and increases the next counter by one etc etc. (this counter could be its own class, with fields for currentValue and maximumValue and method increment() that increments the internal value and returns a boolean as to if the higher counter should be incremented)
Then the actual ID is outputted as a String, with each counter having it's current value converted to a single character (0-9 -->'0'-'9' 10-36 --> 'A'-'Z')

Categories

Resources