Given an array of integers Arr and an integer K, bitwise AND is to be performed on each element A[i] with an integer X
Let Final sum be defined as follows:
Sum of ( A[i] AND X ) for all values of i ( 0 to length of array-1 )
Return the integer X subject to following constraints:
Final sum should be maximum
X should contain exactly K bits as 1 in its binary representation
If multiple values of X satisfy the above conditions, return the minimum possible X
Input:
Arr : [8,4,2]
K = 2
Output: X=12
12 Contains exactly 2 bits in its binary and is the smallest number that gives maximum possible answer for summation of all (A[i] AND X)
Approach Tried :
Took bitwise OR for all numbers in the array in binary and retained the first K bits of the binary that had 1 , made remaining bits 0, convert back to int
Passed 7/12 Test Cases
Can someone help me out with what mistake am I making with regards to the approach or suggest a better approach ? Thanks in advance.
Consider an input like [ 8, 4, 4, 4 ], K = 1. Your algorithm will give 8 but the correct answer is 4. Just because a given bit is more significant doesn't mean that it will automatically contribute more to the sum, as there might be more than twice as many elements of the array that use a smaller bit.
My suggestion would be to compute a weight for each bit of your potential X -- the number of elements of the array that have that bit set times the value of that bit (2i for bit i). Then find the K bits with the largest weight.
To do this, you need to know how big your integers are -- if they are 32 bits, you need to compute just 32 weights. If they might be bigger you need more. Depending on your programming language you may also need to worry about overflow with your weight calculations (or with the sum calculation -- is this a true sum, or a sum mod 2n for some n?). If some elements of the array might be negative, how are negatives represented (2s complement?) and how does that interact with AND?
Let dp[k][i] represent the maximum sum(a & X), a ∈ array, where i is the highest bit index in X and k is the number of bits in X. Then:
dp[1][i]:
sum(a & 2^i)
dp[k][i]:
sum(a & 2^i) + max(dp[k-1][j])
for j < i
sum(a & 2^i) can be precalculated for all values of i in O(n * m), where m is the word size. max(dp[k-1][j]) is monotonically increasing over j and we want to store the earliest instance of each max to minimise the resulting X.
For each k, therefore, we iterate over m is. Overall time complexity O(k * m + n * m), where m is the word size.
Related
Supposing I have an array A[1 ... n] , and no range for its values apart from the fact that they are positive. If I know they have up to k digits, is it possible to sort array in O(n)?
All examples I have come across for O(n) sorting give an upper bound for the values in the array. If there is a duplicate please let me know.
This depends on whether k is a constant or not.
If your numbers have k digits each, then you do have a bound on the numbers, since they can't be any bigger than 10k - 1. You could therefore use radix sort to sort the integers. The runtime of radix sort is O((n + b)logb U), where n is the number of numbers to sort, b is the base of your radix sort, and U is the maximum value that you're sorting. In your case, that works out to
O((n + b) logb 10k) = O(k(n + b)).
This is where the "it depends" comes in. If k is some fixed number that never changes - say, it's always 137 or something like that - then the above expression reduces to O(n + b), and picking b to be any constant (say, base-2 for your radix sort) gives a runtime of O(n). On the other hand, if k can vary (say, the numbers are allowed to be as big as you'd like them to be, and then after seeing the numbers you work out what k is), then the above expression can't be simplified beyond O(kn) because k is a parameter to the algorithm.
Hope this helps!
If k <= n, you can, otherwise it's not guaranteed.
If I give you n = 4 and k = 5, where would you place an element 3?
We are given an array of n integers, and a constant value k, can any one
suggest me to find out the maximum possible integer x such that arr[0]/x + arr[1]/x +.. arr[n-1]/x >=k ,
-> where '/' is the integer division
-> sum of all elements of array >= k
-> k is a constant(1<=k<=10^5)
-> 1<=n<=10^5.
e.g. n=5, k=3
arr=[1,1,1,8,8]
answer-> x=4
in something like o(N log N) ?
Here is an algorithm that often meets your bound on time efficiency. I assume that your array values are non-negative. The algorithm depends on these facts:
Your objective function arr[0]/x + arr[1]/x +.. arr[n-1]/x (let's call it f(x)) is a decreasing function of x. In other words, if x increases then f(x) will stay the same or decrease.
f(1) equals the sum of the elements of the array, so f(1) >= k. In other words, at x = 1 the objective function is not below the target value k.
If M is set to the maximum array value, the value of arr[i] // (M + 1) is zero, so f(M + 1) = 0. In other words, at x = M + 1 the objective is below the target value k.
So we have upper and lower bounds on the value of x for a decreasing function. We can therefore do a binary search from 1 to M + 1 for the value of x where
f(x) >= k and f(x + 1) < k
Only one value of x will satisfy that, and a binary search can easily find it. The binary search will take log(M) steps. Each step involves one evaluation of f(x) which takes N steps to use each array member. Thus the overall time efficiency is O(N log(M)). If M (the maximum array value) is of the order of N then that is your desired efficiency. At the limiting values you give for N and the array values, we have M < N^2, so N log(M) < 2 N log(N) and your desired efficiency is still met. If N is small and M is large, your desired efficiency is not met. (This means an array like [10^9, 10^9-1] where N = 2 and M = 10^9 which could take 30 steps in the binary search.) This may or may not meet your needs.
I cannot understand why the time complexity for this code is O(logn):
double n;
/* ... */
while (n>1) {
n*=0.999;
}
At least it says so in my study materials.
Imagine if the code were as follows:
double n;
/* ... */
while (n>1) {
n*=0.5;
}
It should be intuitive to see how this is O(logn), I hope.
When you multiply by 0.999 instead, it becomes slower by a constant factor, but of course the complexity is still written as O(logn)
You want to calculate how many iterations you need before n becomes equal to (or less than) 1.
If you call the number of iterations for k you want to solve
n * 0.999^k = 1
It goes like this
n * 0.999^k = 1
0.999^k = 1/n
log(0.999^k) = log(1/n)
k * log(0.999) = -log(n)
k = -log(n)/log(0.999)
k = (-1/log(0.999)) * log(n)
For big-O we only care about "the big picture" so we throw away constants. Here log(0.999) is a negative constant so (-1/log(0.999)) is a positive constant that we can "throw away", i.e. set to 1. So we get:
k ~ log(n)
So the code is O(logn)
From this you can also notice that the value of the constant (i.e. 0.999 in your example) doesn't matter for the big-O calculation. All constant values greater than 0 and less than 1 will result in O(logn).
Logarithm has two inputs: a base and a number. The result of a logarithm is the power you need to raise the base to to achieve the given number. Since your base is 0.999, the number is the first smaller than 1 and you have a scalar, which is n, effectively the number of steps depends on the power you need to raise your base to achieve such a small number, which multiplied with n will yield a smaller number than 1. This corresponds to the definition of the logarithm, with which I have started my answer.
EDIT:
Think about it this way: You have n as an input and you search for the first k where
n * .999^k < 1
since you are searching k by incrementing it, since if you have l >= n at a step, then you will have l * .999 in the next step. Repeating this achieves a logarithmic complexity for your multiplication algorithm.
I need to execute a loop
while (X) do Y
for a N times, which is a large number. While Y, the loop body, is rather quick, the test X takes up about 70% of the runtime.
I can calculate the number of loop iterations N beforehand so instead of using X as the condition, a simple For-Loop would be possible.
for (i=1 to N) do Y
However, N might exceed the maximum value an integer can store on the machine, so this is not an option. As an alternative, I proposed to use a floating point variable F instead. As N is large, it is likely that F cannot be exactly equal to N. Thus, I calculate F to be the largest floating point number smaller than N. This allows me to run
for (i=1 to F) do Y
while (X) do Y
Most of the iterations will not need to test X everytime, only the last N-F do.
The question is: How would I implement a for-Loop from 1 to F? Simply increasing a counter or decreasing F by 1 in each step would not work, as the numerical error would grow too large. My current solution is:
for (while F > MAXINT)
for (i=1 to MAXINT)
do Y
F -= MAXINT
while (X) do Y
Is there a better way to solve this problem?
What do you mean by numerical error? Floating point counting is exact within its precision.
Here are the maximum values representable by integers exactly using the following data types:
uint32max = 4294967295
uint64max = 18446744073709551615
float32intmax = 16777216
float64intmax = 9007199254740992
Every integer from 0 to the max is exactly representable without numerical error.
As you can see, the largest count is available with uint64. Next comes float64, then uint32 and finally float32.
What happens when you increment uint32=4294967295 ? 0.
What happens when you increment float32=16777216 ? 16777216.
Which is the better behavior?
Have you thought about using a 2-dimensional loop? If N ism the maximum count for a 1-dimensional loop, then N x N is the maximum for a 2-dimensional loop, etc. so that if you maximum count is less than MAXUINT x MAXUINT, then decompose you number N such that:
N == M * MAXUINT + R;
where
M = N / MAXUINT;
R = N - M * MAXUINT;
then
for (i = M; i--;) for (j = MAXUINT; j--;) DoStuff();
for (i = R; i--;) DoStuff();
If MAXUINT*MAXUINT is not a large enough count for you, you can add 3-, 4-, ... -dimensional loops.
How do you partition an array into 2 parts such that the two parts have equal average? Each partition may contain elements that are non-contiguous in the array.
The only algorithm I can think of is exponential can we do better?
You can reduce this problem to the sum-subset problem - also cached here. Here's the idea.
Let A be the array. Compute S = A[0] + ... + A[N-1], where N is the length of A. For k from 1 to N-1, let T_k = S * k / N. If T_k is an integer, then find a subset of A of size k that sums to T_k. If you can do this, then you're done. If you cannot do this for any k, then no such partitioning exists.
Here's the math behind this approach. Suppose there is a partitioning of A such that the two parts have the same average, says X of size x and Y of size y are the partitions, where x+y = N. Then you must have
sum(X)/x = sum(Y)/y = (sum(A)-sum(X)) / (N-x)
so a bit of algebra gives
sum(X) = sum(A) * x / N
Since the array contains integers, the left hand side is an integer, so the right hand side must be as well. This motivates the constraint that T_k = S * k / N must be an integer. The only remaining part is to realize T_k as the sum of a subset of size k.