Counting bits in an array - algorithm

Given that we know how many bits are set in N elements that is if say we have array A and array of array B .
A store element
B[i] store positions of bits set corresponding to A[i].
Then question is can we find how many bits are set in sum of all A[i] for 1<=i<=N using this B array.
Like say we have A=[700,40]
As 700 is 1010111100 so we have [2 3 4 5 7 9]
As 40 is 101000 so we have [3 5]
B is [[2,3,4,5,7,9],[3,5]]
And we want count of bits set in 740.
How this can be done in efficient way ? Please help

This is about binary addition. In your example
A[0] = 1010111100 B[0] = [2,3,4,5,7,9]
A[1] = 0000101000 B[1] = [3,5]
A[0]+A[1] = 1011100100
So the sum is represented as [2,5,6,7,9]. Can you see how to get to this array given B[0] and B[1]?
Here's how you can proceed with just two arrays:
set B = B[0]
while B[1] not empty:
for each b in B[1]:
if b not in B:
append b to B
remove b from B[1]
else:
remove b from B
increment each of the remaining elements in B[1] by 1
return length(B)
You have to mimic binary addition via the elements of the B arrays.
To get the number of bits set, you just return the number of elements in B.

So given the array B, you want to calculate the sum of the elements of A, 740 in this example?
Easy:
int sum = 0;
foreach( var bSubArray in B)
foreach( var b in bSubArray)
sum += Power( 2, b);

Related

Find maximum number of Candies

Given an array of numbers. We can select 3 numbers at a time from the array.
Suppose A, B, C where A <= B <= C. You get B number candy from this selection.
You can pick one element only once. You need to maximize number of candies.
Note: The size of array will be multiple of 3.
Ex:
[4,5,6,7,8,9]
output:
14
Explanation:
We selected [4,8,9] first, then [5,6,7] so the max no. of candies: 8+6=14
1.first,we know A <= B <= C ,so we know we should chose a max B, but must < C, so we can only chose less max , in this case is (nums.length - 1) - 1. A we will chose the first one,but it doesn't matter
2.we chose the second array , B will be nums.length - 1 - 1 - 1 - 1
3.So we found the result : result += nums[nums.length -1 -i*2 -1]
public static int maxCandies(int[] nums){
Arrays.sort(nums); // sort the array
int result = 0;
for(int i = 0;i<nums.length/3;i++)
result += nums[nums.length-1-i*2-1]; // always add the less max num
return result;
}

Can someone explain the mathematics behind this solution

A question asks:
Take a sequence of numbers from 1 to n (where n > 0).
Within that sequence, there are two numbers, a and b.
The product of a and b should equal the sum of all numbers in the sequence excluding a and b.
Given a number n, could you tell me the numbers excluded from the sequence?
My plan was to get the sum of the range, then create an array using the combination enumerator to get all of the possible pairs of the range, then check if the product of the pair equals the sum of the range minus the sum of the pair. This solution worked, but took way too long:
def removNb(n)
arr = [*1..n]
sum = arr.inject(:+)
ab = []
[*(n/2)..n].combination(2).to_a.each do |pair|
if pair.inject(:*) == sum - pair.inject(:+)
ab << pair
ab << [pair[1],pair[0]]
end
end
ab
end
Here is a solution that I found:
def removNb(n)
res = []
total = (n*n + n) / 2
range = (1..n)
(1..n).each do |a|
b = ((total - a) / (a * 1.0 + 1.0))
if b == b.to_i && b <= n
res.push([a,b.to_i])
end
end
return res
end
but can't understand how it works. I understand the equation behind the total.
You could form a equation
a * b = (sum of sequence from 1 to n) - (a + b)
from this statement
the product of a and b should be equal to the sum of all numbers in
the sequence, excluding a and b
sum of sequence from 1 to n (denote as total) = n(n+1)/2 = (n*n + n) / 2
Reorder above equation, you get
b = (total - a) / (a + 1)
The remaining work is to test if there exist integer a and b matching this equation
The code returns an array of all pairs of numbers in the sequence that have the desired property. Let's step through it.
Initialize the array to be returned.
res = []
Compute the sum of the elements in the sequence. The sum of the elements of any arithmetic sequence equals the first element plus the last element, multiplied by the number of elements in the sequence, the product divided by 2. Here that is total = n*(1+n)/2, which can be expressed as
total = (n*n + n) / 2
range = (1..n) is unnecessary as range is not subsequently referenced.
Loop through the elements of the sequence
(1..n).each do |a|
For each value of a we seek another element of the sequence b such that
a*b = total - a - b
Solving for b:
b = (total - a)/ (a * 1.0 + 1.0)
If b is in the range, save the pair [a, b]
if b == b.to_i && b <= n
res.push([a,b.to_i])
end
Return the array res
res
This method contains two errors:
If [a,b] is added to res, it will be added twice
[a,a] could be added to res (such as n=5, a=b=3)
I would write this as follows.
def remove_numbers(n)
total = n*(n+1)/2
(1..n-1).each_with_object([]) do |a,res|
next unless (total-a) % (a+1) == 0
b = (total-a)/(a+1)
res << [a,b] if (a+1..n).cover?(b)
end
end
For example,
remove_numbers 10
#=> [[6, 7]]
remove_numbers 1000
#=> []
Out of cursiosity:
(2..10_000).map { |x| [x, remove_numbers(x).size] }.max_by(&:last)
#=> [3482, 4]
remove_numbers 3482
#=> [[1770, 3423], [2023, 2995], [2353, 2575], [2460, 2463]]

find all indices of multiple value pairs in a matrix

Suppose I have a matrix A, containing possible value pairs and a matrix B, containing all value pairs:
A = [1,1;2,2;3,3];
B = [1,1;3,4;2,2;1,1];
I would like to create a matrix C that contains all pairs that are allowed by A (i.e. C = [1,1;2,2;1,1]).
Using C = ismember(A,B,'rows') will only show the first occurence of 1,1, but I need both.
Currently I use a for-loop to create C, which looks like:
TFtot = false(size(B(:,1,1),1);
for i = 1:size(a(:,1),1)
TF1 = A(i,1) == B(:,1) & A(i,2) = B(:,2);
TFtot = TF1 | TFtot;
end
C = B(TFtot,:);
I would like to create a faster approach, because this loop currently greatly slows down the algorithm.
You're pretty close. You just need to swap B and A, then use this output to index into B:
L = ismember(B, A, 'rows');
C = B(L,:);
How ismember works in this particular case is that it outputs a logical vector that has the same number of rows as B where the ith value in B tells you whether we have found this ith row somewhere in A (logical 1) or if we haven't found this row (logical 0).
You want to select out those entries in B that are seen in A, and so you simply use the output of ismember to slice into B to extract out the affected rows, and grab all of the columns.
We get for C:
>> C
C =
1 1
2 2
1 1
Here's an alternative using bsxfun:
C = B(all(any(bsxfun(#eq, B, permute(A, [3 2 1])),3),2),:);
Or you could use pdist2 (Statistics Toolbox):
B(any(~pdist2(A,B),1),:);
Using matrix-multiplication based euclidean distance calculations -
Bt = B.'; %//'
[m,n] = size(A);
dists = [A.^2 ones(size(A)) -2*A ]*[ones(size(Bt)) ; Bt.^2 ; Bt];
C = B(any(dists==0,1),:);

Find number of continuous subarray having sum zero

You have given a array and You have to give number of continuous subarray which the sum is zero.
example:
1) 0 ,1,-1,0 => 6 {{0},{1,-1},{0,1,-1},{1,-1,0},{0}};
2) 5, 2, -2, 5 ,-5, 9 => 3.
With O(n^2) it can be done.I am trying to find the solution below this complexity.
Consider S[0..N] - prefix sums of your array, i.e. S[k] = A[0] + A[1] + ... + A[k-1] for k from 0 to N.
Now sum of elements from L to R-1 is zero if and only if S[R] = S[L]. It means that you have to find number of indices 0 <= L < R <= N such that S[L] = S[R].
This problem can be solved with a hash table. Iterate over elements of S[] while maintaining for each value X number of times it was met in the already processed part of S[]. These counts should be stored in a hash map, where the number X is a key, and the count H[X] is the value. When you meet a new elements S[i], add H[S[i]] to your answer (these account for substrings ending with (i-1)-st element), then increment H[S[i]] by one.
Note that if sum of absolute values of array elements is small, you can use a simple array instead of hash table. The complexity is linear on average.
Here is the code:
long long CountZeroSubstrings(vector<int> A) {
int n = A.size();
vector<long long> S(n+1, 0);
for (int i = 0; i < n; i++)
S[i+1] = S[i] + A[i];
long long answer = 0;
unordered_map<long long, int> H;
for (int i = 0; i <= n; i++) {
if (H.count(S[i]))
answer += H[S[i]];
H[S[i]]++;
}
return answer;
}
This can be solved in linear time by keeping a hash table of sums reached during the array traversal. The number of subsets can then be directly calculated from the counts of revisited sums.
Haskell version:
import qualified Data.Map as M
import Data.List (foldl')
f = foldl' (\b a -> b + div (a * (a + 1)) 2) 0 . M.elems . snd
. foldl' (\(s,m) x -> let s' = s + x in case M.lookup s' m of
Nothing -> (s',M.insert s' 0 m)
otherwise -> (s',M.adjust (+1) s' m)) (0,M.fromList[(0,0)])
Output:
*Main> f [0,1,-1,0]
6
*Main> f [5,2,-2,5,-5,9]
3
*Main> f [0,0,0,0]
10
*Main> f [0,1,0,0]
4
*Main> f [0,1,0,0,2,3,-3]
5
*Main> f [0,1,-1,0,0,2,3,-3]
11
C# version of #stgatilov answer https://stackoverflow.com/a/31489960/3087417 with readable variables:
int[] sums = new int[arr.Count() + 1];
for (int i = 0; i < arr.Count(); i++)
sums[i + 1] = sums[i] + arr[i];
int numberOfFragments = 0;
Dictionary<int, int> sumToNumberOfRepetitions = new Dictionary<int, int>();
foreach (int item in sums)
{
if (sumToNumberOfRepetitions.ContainsKey(item))
numberOfFragments += sumToNumberOfRepetitions[item];
else
sumToNumberOfRepetitions.Add(item, 0);
sumToNumberOfRepetitions[item]++;
}
return numberOfFragments;
If you want to have sum not only zero but any number k, here is the hint:
int numToFind = currentSum - k;
if (sumToNumberOfRepetitions.ContainsKey(numToFind))
numberOfFragments += sumToNumberOfRepetitions[numToFind];
I feel it can be solved using DP:
Let the state be :
DP[i][j] represents the number of ways j can be formed using all the subarrays ending at i!
Transitions:
for every element in the initial step ,
Increase the number of ways to form Element[i] using i elements by 1 i.e. using the subarray of length 1 starting from i and ending with i i.e
DP[i][Element[i]]++;
then for every j in Range [ -Mod(highest Magnitude of any element ) , Mod(highest Magnitude of any element) ]
DP[i][j]+=DP[i-1][j-Element[i]];
Then your answer will be the sum of all the DP[i][0] (Number of ways to form 0 using subarrays ending at i ) where i varies from 1 to Number of elements
Complexity is O(MOD highest magnitude of any element * Number of Elements)
https://www.techiedelight.com/find-sub-array-with-0-sum/
This would be an exact solution.
# Utility function to insert <key, value> into the dict
def insert(dict, key, value):
# if the key is seen for the first time, initialize the list
dict.setdefault(key, []).append(value)
# Function to print all sub-lists with 0 sum present
# in the given list
def printallSublists(A):
# create an empty -dict to store ending index of all
# sub-lists having same sum
dict = {}
# insert (0, -1) pair into the dict to handle the case when
# sub-list with 0 sum starts from index 0
insert(dict, 0, -1)
result = 0
sum = 0
# traverse the given list
for i in range(len(A)):
# sum of elements so far
sum += A[i]
# if sum is seen before, there exists at-least one
# sub-list with 0 sum
if sum in dict:
list = dict.get(sum)
result += len(list)
# find all sub-lists with same sum
for value in list:
print("Sublist is", (value + 1, i))
# insert (sum so far, current index) pair into the -dict
insert(dict, sum, i)
print("length :", result)
if __name__ == '__main__':
A = [0, 1, 2, -3, 0, 2, -2]
printallSublists(A)
I don't know what the complexity of my suggestion would be but i have an idea :)
What you can do is try to reduce element from main array which are not able to contribute for you solution
suppose elements are -10, 5, 2, -2, 5,7 ,-5, 9,11,19
so you can see that -10,9,11 and 19 are element
that are never gone be useful to make sum 0 in your case
so try to remove -10,9,11, and 19 from your main array
to do this what you can do is
1) create two sub array from your main array
`positive {5,7,2,9,11,19}` and `negative {-10,-2,-5}`
2) remove element from positive array which does not satisfy condition
condition -> value should be construct from negative arrays element
or sum of its elements
ie.
5 = -5 //so keep it //don't consider the sign
7 = (-5 + -2 ) // keep
2 = -2 // keep
9 // cannot be construct using -10,-2,-5
same for all 11 and 19
3) remove element form negative array which does not satisfy condition
condition -> value should be construct from positive arrays element
or sum of its elements
i.e. -10 // cannot be construct so discard
-2 = 2 // keep
-5 = 5 // keep
so finally you got an array which contains -2,-5,5,7,2 create all possible sub array form it and check for sum = 0
(Note if your input array contains 0 add all 0's in final array)

Overwrite first n elements of an array?

Here's my scenario:
a = ["","","","","","","","","",""] #10 elements. Need not always be blank.
b = ["a","b","c","d"]
I want to modify a such that the first n elements of a are replaced with the elements of b where n = b.size():
a = ["a","b","c","d","","","","","",""]
So, is there something simple like a.replace(b) minus the truncation?
An alternative would be a way to append a.size() - b.size() number of elements to b.
You can use slicing:
a[0, 4] = b
or with a dynamic length:
a[0, b.length] = b

Resources