The question is - to find the sum of all maximum values from all subarrays. For instance, I have the array {2, 8, 4, 3, 5}, the solution will be 92. Where all of my subarrays are:
{2},{8},{4},{3},{5},
{2,8},{8,4},{4,3},{3,5},
{2,8,4},{8,4,3},{4,3,5},
{2,8,4,3},{8,4,3,5},
{2,8,4,3,5}
And all maximum values from all subarrays are:
2 - 8 - 4 - 3 - 5 -
8 - 8 - 4 - 5 -
8 - 8 - 5 -
8 - 8 -
8
Do you know the way to solve this problem in linear time complexity?
It should be very straightforward. See the following algorithm
sum = 0
max = 0
for every array 'arr' in the array of arrays
do
for every element 'arri' in the array 'arr'
do
if arri >= max, max = arri
end for
max = 0
sum = sum + max
end for
Related
I have an array A=[a1,a2,a3, ..., aN] I would like to take a product of each 3 elements:
s1=a1+a2+a3
s2=a4+a5+a6
...
sM=a(N-2)+a(N-1)+aN
My solution:
k=size(A);
s=0;
for n=1:k
s(n)=s(n-2)+s(n-1)+s(n);
end
Error: Attempted to access s(2); index out of bounds because numel(s)=1.
Hoe to fix it?
If you want to sum in blocks, for the general case when the number of elements of A is not necessarily a multiple of the block size, you can use accumarray:
A = [3 8 5 8 2 3 4 7 9 6 4]; % 11 elements
s = 3; % block size
result = accumarray(ceil((1:numel(A))/s).', A(:));
If you want a sliding sum with a given block size, you can use conv:
A = [3 8 5 8 2 3 4 7 9 6 4]; % 11 elements
s = 3; % block size
result = conv(A(:).', ones(1,s), 'valid');
You try to calculate sby using values from s. Dont you mean s(n)=A(n-2)+A(n-1)+A(n);? Also size returns more than one dimension on its own.
That being said, getting the 2 privous values n-2 and n-1 doenst work for n=1;2 (because you must have positive indices). You have to explain how the first two values should be handeled. I assume either 0 for elements not yet exisiting
k=size(A,2); %only the second dimension when A 1xn, or length(A)
s=zeros(1,k); %get empty values instead of appending each value for better performance
s(1)=A(1);
s(2)=A(2)+A(1);
for n=3:k %start at 3
s(n)=A(n-2)+A(n-1)+A(n);
end
or sshoult be 2 values shorter than A.
k=size(A,2);
s=zeros(1,k-2);
for n=1:k-2
s(n)=A(n)+A(n+1)+A(n+2);
end
You initialise s as a scalar with s = 0. Then you try and index it like an array, but it only has a single element.
Your current logic (if fixed) will calculate this:
s(1) = a(1)+a(2)+a(3)
s(2) = a(2)+a(3)+a(4)
...
% 's' will be 2 elements shorter than 'a'
So we need to be a bit wiser with the indexing to get what you describe, which is
s(1) = a(1)+a(2)+a(3)
s(2) = a(4)+a(5)+a(6)
...
% 's' will be a third as big as 'a'
You should pre-allocate s to the right size, like so:
k = numel(A); % Number of elements in 'A'
s = zeros( 1, k/3 ); % Output array, assuming 'k' is divisible by 3
for n = 0:3:k-3
s(n/3+1) = a(n+1) + a(n+2) + a(n+3);
end
You could do this in one line by reshaping the array to have 3 rows, then summing down each column, this assumes that the number of elements in a is divisible by 3, and that a is a row vector...
s = sum( reshape( a, 3, [] ) );
Lets say I have a 4 dimensional matrix, from which I would like to retrieve the maximum values over the 2nd and 3rd dimension.
A = rand(4, 4, 4, 4);
[max_2, in_2] = max(A, [], 2);
[max_3, in_3] = max(max_2, [], 3);
How could I use ind_2 and ind_3 to obtain a logical 4 dimensional matrix, where a 1 entry means this entry is maximum in the 2nd and 3rd dimension?
I would use this approach:
A = rand(4, 4, 4, 4); % example data
B = permute(A, [1 4 2 3]); % permute dims 2 and 3 to the end
B = reshape(B, size(A,1), size(A,4), []); % collapse last two dims
C = bsxfun(#eq, B, max(B, [], 3)); % maximize over collapsed last dim
C = reshape(C, size(A,1), size(A,4), size(A,2), size(A,3)); % expand dims back
C = permute(C, [1 3 4 2]); % permute dims back. This is the final result
Here's an approach working with linear indices and uses argmax indices from max function, so it would only consider the first argmax in case of ties for the max value -
% Get size parameters
[m,n,p,q] = size(A);
% Reshape to merge second and third dims
[~, in_23] = max(reshape(A,m,[],q), [], 2);
% Get linear indices equivalent that could be mapped onto output array
idx1 = reshape(in_23,m,q);
idx2 = bsxfun(#plus,(1:m)', m*n*p*(0:q-1)) + (idx1-1)*m;
% Initialize output array an assign 1s at linear indices from idx2
out = false(m,n,p,q);
out(idx2) = 1;
Explanation with a sample
1) Input array :
>> A
A(:,:,1,1) =
9 8
9 1
A(:,:,2,1) =
2 9
8 1
A(:,:,1,2) =
1 7
8 1
A(:,:,2,2) =
8 5
9 7
2) Reshape array for a better visualization :
>> reshape(A,m,[],q)
ans(:,:,1) =
9 8 2 9
9 1 8 1
ans(:,:,2) =
1 7 8 5
8 1 9 7
3) The question is to take max value from each of the rows. For that, we had idx2 as the linear indices :
>> idx2
idx2 =
1 13
2 14
Looking back at the reshape version, thus we chose (bracketed ones) -
>> reshape(A,m,[],q)
ans(:,:,1) =
[9] 8 2 9
[9] 1 8 1
ans(:,:,2) =
1 7 [8] 5
8 1 [9] 7
So, looking closely, we see that for the first row, we had two 9s, but we are choosing the first one only.
4) Finally, we are assigning these into the output array initialized as logical zeros :
>> out
out(:,:,1,1) =
1 0
1 0
out(:,:,2,1) =
0 0
0 0
out(:,:,1,2) =
0 0
0 0
out(:,:,2,2) =
1 0
1 0
I have got two arrays with same elements... (But in different order)
e.g 1 2 12 9 7 15 22 30
and 1 2 7 12 9 20 15 22
how many swaps operations are needed to form the 2nd array from the first.?
I have tried taking no. of different elements for each index and dividing the result by 2 but that isn't fetching me the right answer...
One classic algorithm seems to be permutation cycles (https://en.m.wikipedia.org/wiki/Cycle_notation#Cycle_notation). The number of swaps needed equals the total number of elements subtracted by the number of cycles.
For example:
1 2 3 4 5
2 5 4 3 1
Start with 1 and follow the cycle:
1 down to 2, 2 down to 5, 5 down to 1.
1 -> 2 -> 5 -> 1
3 -> 4 -> 3
We would need to swap index 1 with 5, then index 5 with 2; as well as index 3 with index 4. Altogether 3 swaps or n - 2. We subtract n by the number of cycles since cycle elements together total n and each cycle represents a swap less than the number of elements in it.
1) re-index elements from 0 to n-1. In your example, arrayA becomes 0..7 and arrayB becomes 0 1 4 2 3 7 5 6.
2) sort the second array using your swapping algorithm and count the number of operations.
A bit naive, but I think you can use recursion as follows (pseudo code):
function count_swaps(arr1, arr2):
unless both arrays contain the same objects return false
if arr1.len <= 1 return 0
else
if arr1[0] == arr2[0] return count_swaps(arr1.tail, arr2.tail)
else
arr2_tail = arr2.tail
i = index_of arr1[0] in arr2_tail
arr2_tail[i] = arr2[0]
return 1+count_swaps(arr1.tail, arr2_tail)
Here's a ruby implementation:
require 'set'
def count_swaps(a1, a2)
raise "Arrays do not have the same objects: #{a1} #{a2}" unless a1.length == a2.length && Set[*a1]==Set[*a2]
return count_swap_rec(a1, a2)
end
def count_swap_rec(a1, a2)
return 0 if a1.length <= 1
return count_swaps(a1[1..-1], a2[1..-1]) if a1[0] == a2[0]
a2_tail = a2[1..-1]
a2_tail[a2_tail.find_index(a1[0])] = a2[0]
return 1 + count_swaps(a1[1..-1], a2_tail)
end
Let's say, I have an array like this:
1 2 3 4 5
And given pair is (2,3), then number of possible subarrays that don't have (2,3) present in them will be,,
1. 1
2. 2
3. 3
4. 4
5. 5
6. 1 2
7. 3 4
8. 4 5
9. 3 4 5
So, the answer will be 9.
Obviously, there can be more of such pairs.
Now, one method that I thought of is of O(n^2) which involves finding all such elements of maximum length n. Can I do better? Thanks!
Let's see, this adhoc pseudocode should be O(n):
array = [1 2 3 4 5]
pair = [2 3]
length = array.length
n = 0
start = 0
while (start < length)
{
# Find next pair
pair_pos = start
while (pair_pos < length) and (array[pair_pos,pair_pos+1] != pair) # (**1)
{
pair_pos++
}
# Count subarrays
n += calc_number_of_subarrays(pair_pos-start) # (**2)
# Continue after the pair
start = pair_pos+2
}
print n
Note **1: This seems to involve a loop inside the outer loop. Since every element of the array is visited exactly once, both loops together are O(n). In fact, it is probably easy to refactor this to use only one while loop.
Note **2: Given an array of length l, there are l+(l-1)+(l-2)+...+1 subarrays (including the array itself). Which is easy to calculate in O(1), there is no loop involved. c/f Euler. :)
You don't need to find which subarrays are in an array to know how many of them there are. Finding where the pair is in the array is at most 2(n-1) array operations. Then you only need to do a simple calculation with the two lengths you extract from that. The amount of subarrays in an array of length 3 is, for example, 3 + 2 + 1 = 6 = (n(n+1))/2.
The solution uses that in a given array [a, ..., p1, p2, ..., b], the amount of subarrays without the pair is the amount of subarrays for [a, ..., p1] + the amount of subarrays for [p2, ..., b]. If multiple of such pairs exist, we repeat the same trick on [p2, ..., b] as if it was the whole array.
function amount_of_subarrays ::
index := 1
amount := 0
lastmatch := 0
while length( array ) > index do
if array[index] == pair[1] then
if array[index+1] == pair[2] then
length2 := index - lastmatch
amount := amount + ((length2 * (length2 + 1)) / 2)
lastmatch := index
fi
fi
index := index + 1
od
//index is now equal to the length
length2 := index - lastmatch
amount := amount + ((length2 * (length2 + 1)) / 2)
return amount
For an array [1, 2, 3, 4, 5] with pair [2, 3], index will be 2 when the two if-statements are true. amount will be updated to 3 and lastmatch will be updated to 2. No more matches will be found, so lastmatch is 2 and index is 5. amount will be 3 + 6 = 9.
Please help me solve this problem...
a = [1 2 3 4 5 6 7 8 9 10]
b = [12 4 13 7 5 7 8 10 3 12]
c = [4 5 3 2 6 7 5 3 4 5]
I have to find the first value on a, if the value on b is less than 10 for more than 3 consecutive places and index for the starting of satisfying the condition. Also the value of c after finding the value of b for same index.
Ans should be index for b=4, index for a=4 and value for a =4 and c=2
Thank you in advance
You may use strfind as one approach -
str1 = num2str(b <10,'%1d') %%// String of binary numbers
indx = strfind(['0' str1],'0111') %%// Indices where the condition is met
ind = indx(1) %%// Choose the first occurance
a_out = a(ind) %%// Index into a
c_out = c(ind) %%// Index into c
Output -
ind =
4
a_out =
4
c_out =
2
To find a given number of consecutive values lower than a threshold, you can apply conv to a vector of 0-1 values resulting from the comparison:
threshold = 10; %// values "should" be smaller than this
number = 4; %// at least 4 consecutive occurrences
ind = find(conv(double(b<threshold), ones(1,number), 'valid')==number, 1);
%// double(b<threshold) gives 0-1.
%// conv(...)==... gives 1 when the sought number of consecutive 1's is reached
%// find(... ,1) gives the first index where that happens
a_out = a(ind);
c_out = c(ind);