Given an array A of size N, for each element A[i], I want to find all j such that A[j] > A[i]. Currently, I cannot think of a method better than O(i)(Traverse all 0 <= j < i and check). Is there an algorithm that achieves better time complexity than above? Space Complexity can be O(N)
Update 1
We can assume the array has distinct elements
Update 2
Let us consider array A = [4 6 7 1 2 3 5]. Let dom(i) = {j | 0 < j < i such that A[j] > A[i] }
dom(0) = empty
dom(1) = empty
dom(2) = empty
dom(3) = {0, 1, 2}
dom(4) = {0, 1, 2}
dom(5) = {0, 1, 2}
dom(6) = {1, 2}
Also the space complexity of O(N) is meant to be per every iteration i
Lower time complexity cannot be achieved, as, for example, if your array is all descending, all lists would have quadratic total length, so if your task is to get the lists, this is as fast as it can get. Your solution already achieves this O(N^2), so it already is optimal.
There are faster ways to calculate some things related to this, though. For example, if you are actually looking to get just the total count of all such pairs, it can be done in O(n ln n) time, see this post.
Related
I am going through this program mentioned here.
Given an array arr[] of N integers. The task is to count the total number of subarrays of the given array such that the difference between the consecutive elements in the subarrays is one. That is, for any index i in the subarrays, arr[i+1] – arr[i] = 1.
Examples:
Input : arr[] = {1, 2, 3}
Output : 3
The subarrays are {1, 2}. {2, 3} and {1, 2, 3}
Input : arr[] = {1, 2, 3, 5, 6, 7}
Output : 6
Efficient Approach: An efficient approach is to observe that in an array of length say K, the total number of subarrays of size greater than 1 = (K)*(K-1)/2.
So, the idea is to traverse the array by using two pointers to calculate subarrays with consecutive elements in a window of maximum length and then calculate all subarrays in that window using the above formula.
Below is the step-by-step algorithm:
Take two pointers to say fast and slow, for maintaining a window of consecutive elements.
Start traversing the array.
If elements differ by 1 increment only the fast pointer.
Else, calculate the length of the current window between the indexes fast and slow.
My question is about the statement An efficient approach is to observe that in an array of length say K, the total number of subarrays of size greater than 1 = (K)*(K-1)/2 How this formula (K)*(K-1)/2 is derived?
The number of subarrays of size 1 is K.
The number of subarrays of size 2 is K-1.
( We need to select subarrays of size 2, hence we can have pair with the indices (0,1), (1,2), .......(K-1,K). In total we can have K-1 such pairs)
The number of subarrays of size 3 is K-2.
...
...
The number of subarrays of size K is 1
So, the number of subarrays of size greater than 1 is
= K-1 + K-2 + K-3+ ...... 1
= (K + K-1 + K-2 + K-3+ ...... 1) - K //adding and removing K
= (K(K+1)/2) - K
= K(K-1)/2
You have an array of integers. you have to find the number of subarrays which mean (sum of those elements divided by the count of those elements) rounds to zero.
I have solved this with O(n^2) time but it is not efficient enough. Is there a way to do it?
example:
[-1, 1, 5, 4]
subarrays which mean rounds to zero are:
[-1, 1] = 0 , [-1, 1, 5, -4] = 1/4 which rounds to zero
Denote new array composed of pairs (prefix sum, cnt) where first element is the prefix summation and second element is number of elements, for example,
int[] arr = [-1, 1, 5 ,4]:
int[] narr = [(0, 0), (-1, 1), (0, 2), (5, 3), (9, 4)]
the question is converted to count pair (i, j) in narr where i < j and Math.abs(narr[j][0] - narr[i][0]) < narr[j][1] - narr[i][1] = j - i which is further boiled down to:
narr[j][0] - j < narr[i][0] - i < narr[i][0] + i < narr[j][0] + j
so the question is further converted to the following question:
for some intervals: [[1, 2], [-1, 0], ...] (initially is empty), given an interval [x, y], count how many intervals are totally within the range of [x, y], then we add this interval, and repeat this procedure for total N times. (how to manage the data structure of intervals become the key problem)
If we just brute force iterate every intervals and do the validation, the query time complexity is O(N) and insertion time complexity is O(1), total O(N^2)
If we use square decomposition, the query time complexity is O(sqrt(N)) and insertion time complexity is O(1) , total O(Nsqrt(N))
If we use treap (using first or second as priority, use another as key), the average total time complexity we can achieve is O(NlgN)
If you don't know the technique of square decomposition or treap , I suggest you reading couple of articles first.
Update:
After carefully 30 mins thinking, I find treap cannot achieve O(NlgN) average time complexity.
Instead we can use 2d segment tree to achieve O(NlgNlgN):
Please read this article instead:
2d segment tree
You are given an integer array a of size n and an integer m. you have to distribute the elements of array A into M groups such that the maximum sum of elements in each group is minimum and the elements of array A allocated to any group is contiguous. Write a program to determine the maximum sum of elements among all the groups.
The brute force could be having all the M possible sub-arrays from the given array and checking with them. But this would take a time complexity of O(n^3).
Here I used dynamic programming which would take both the time and space complexity of O(n*M).
Try all the possible partitions that are possible using recursion. Let dp[ind][k] be the minimum of maximum sums till index 'ind' with 'k' partitions. Hence the possible states will be partition at every index from the index ind till n. The minimum of maximum sums of all those states will be our answer.
In order not to recur for visited element, we can use memoize.
Below is the implementation of the above approach:
from sys import maxsize
from sys import setrecursionlimit
setrecursionlimit(10**6)
def max_sum_groups_min(arr, n, ind, M, dp):
# If M segments have been divided
if M == -1:
# If we are at the end
if ind == n:
return -maxsize
# If we do not reach end, return a maximum number
# that cannot be a min value than existing answer
return maxsize
# If at the end, but M segmments are not formed
if ind == n:
return maxsize
# If it's already visited: Memoization
if dp[ind][M] != False:
return dp[ind][M]
ans = maxsize
cur = 0
# Iterate and try to break at every segment and create a segment
for i in range(ind, n):
# sum of elements in current segment
cur += arr[i]
# Find the maximum of all segments after adding and
# find minimum in all possible combinations
ans = min(ans, max(max_sum_groups_min(arr, n, i + 1, M - 1, dp), cur))
# Return the answer by memoizing it
dp[ind][M] = ans
return ans
n = int(input("Enter array size: "))
arr = list(map(int, input("Enter list of elements: ").split()))
group = int(input("Enter the group size: "))
# keeping 'False' inorder to keep track it's not visited
dp = [[False for _ in range(group)] for _ in range(n)]
print(max_sum_groups_min(arr, n, 0, group - 1, dp))
For eg: n = 8, arr = [1, 2, 3, 4, 5, 6, 7, 8], M = 4
Here the given array can be divided into 4 groups as:
{1, 2, 3, 4}, {5, 6}, {7}, {8}
in which 2nd group has largest sum(11) among all the groups which is minimum of all possibilities.
Thanks,
Jayanth.
Say I have an array of N integers set to the value '0', and I want to pick a random element of that array that has the value '0' and put it to value '1'
How do I do this efficiently ?
I came up with 2 solutions but they look quite ineficient
First solution
int array[N] //init to 0s
int n //number of 1s we want to add to the array
int i = 0
while i < n
int a = random(0, N)
if array[a] == 0
array[a] = 1
i++
end if
end while
It would be extremely inefficient for large arrays because of the probability of collision
The second involves a list containing all the 0 positions remaining and we choose a random number between 0 and the number of 0 remaining to lookup the value in the list that correspond to the index in the array.
It's a lot more reliable than the first solution, since the number of operations is bounded, but still has a worst case scenario complexity of N² if we want to fill the array completely
Your second solution is actually a good start. I assume that it involves rebuilding the list of positions after every change, which makes it O(N²) if you want to fill the whole array. However, you don't need to rebuild the list every time. Since you want to fill the array anyway, you can just use a random order and choose the remaining positions accordingly.
As an example, take the following array (size 7 and not initially full of zeroes) : [0, 0, 1, 0, 1, 1, 0]
Once you have built the list of zeros positions, here [0, 1, 3, 6], just shuffle it to get a random ordering. Then fill in the array in the order given by the positions.
For example, if the shuffle gives [3, 1, 6, 0], then you can fill the array like so :
[0, 0, 1, 0, 1, 1, 0] <- initial configuration
[0, 0, 1, 1, 1, 1, 0] <- First, position 3
[0, 1, 1, 1, 1, 1, 0] <- Second, position 1
[0, 1, 1, 1, 1, 1, 1] <- etc.
[1, 1, 1, 1, 1, 1, 1]
If the array is initially filled with zeros, then it's even easier. Your initial list is the list of integers from 0 to N (size of the array). Shuffle it and apply the same process.
If you do not want to fill the whole array, you still need to build the whole list, but you can truncate it after shuffling it (which just means to stop filling the array after some point).
Of course, this solution requires that the array does not change between each step.
You can fill array with n ones and N-n zeros and make random shuffling.
Fisher-Yates shuffle has linear complexity:
for i from N−1 downto 1 do
j ← random integer such that 0 ≤ j ≤ i
exchange a[j] and a[i]
Does anyone know an Algorithm that sorts k-approximately an array?
We were asked to find and Algorithm for k-approximate sorting, and it should run in O(n log(n/k)). but I can't seem to find any.
K-approx. sorting means that an array and any 1 <= i <= n-k such that sum a[j] <= sum a[j] i<=j<= i+k-1 i+1<=j<= i+k
I know I'm very late to the question ... But under the assumption that k is some approximation value between 0 and 1 (when 0 is completely unsorted and 1 is perfectly sorted) surely the answer to this is quicksort (or mergesort).
Consider the following array:
[4, 6, 9, 1, 10, 8, 2, 7, 5, 3]
Let's say this array is 'unsorted' - now apply one iteration of quicksort to this array with the (length[array]/2)th element as a pivot: length[array]/2 = 5. So the 5th element is our pivot (i.e. 8):
[4, 6, 2, 1, 3, 9, 7, 10, 8]
Now this is array is not sorted - but it is more sorted than one iteration ago, i.e. its approximately sorted but for a low approximation, i.e. a low value of k. Repeat this step again on the two halves of the array and it becomes more sorted. As k increases towards 1 - i.e. perfectly sorted - the complexity becomes O(N log(N/1)) = O(N log(N)).