Number of occurrences of a number in a particular range? - arrays

Given a large unsorted array, I need to find out the number of occurrences of a given number in a particular range. (There can be many queries)
e.g. if arr[]={ 6,7,8,3,4,1,2,4,6,7,8,9} and left_range=3 and right_range=7 and number=4, then the output will be 2. (considering a 0 indexed array)
arr[i] can be in the range of 1 to 100000. The array can have up to 100000 numbers.
Can you guide me about which data structure or algorithm I should use here?
PS: Pre-processing the array is allowed.

Here's a solution that doesn't require segment tree.
Preprocessing:
For each number arr[i], push i to the 2D vector(or ArrayList) with index arr[i].
Answering Queries:
For any query do a binary search on vector[num] to find the index of the maximum index of num in that vector that's less than or equal to right range, let's call it R. Then find the minimum index that's greater than or equal to left range, let's call it L. Print R - L + 1
Runtime:
Preprocessing in O(1) per item, taking total O(N) time.
Per Query answer: O(lg(N))
Space: Quite linear assuming vector or ArrayList

Related

Minimum steps needed to make all elements equal by adding adjacent elements

I have an array A of size N. All elements are positive integers. In one step, I can add two adjacent elements and replace them with their sum. That said, the array size reduces by 1. Now I need to make all the elements same by performing minimum number of steps.
For example: A = [1,2,3,2,1,3].
Step 1: Merge index 0 and 1 ==> A = [3,3,2,1,3]
Step 2: Merge index 2 and 3 (of new array) ==> [3,3,3,3]
Hence number of steps are 2.
I couldn't think of a straight solution, so tried a recursive approach by merging all indices one by one and returning the min level I can get when either array size is 1 or all elements are equal.
Below is the code I tried:
# Checks if all the elements are same or not
def check(A):
if len(set(A)) == 1:
return True
return False
# Recursive function to find min steps
def min_steps(N,A,level):
# If all are equal return the level
if N == 1 or check(A):
return level
# Initialize min variable
mn = float('+inf')
# Try merging all one by one and recur
for i in range(N-1):
temp = A[:]
temp[i]+=temp[i+1]
temp.pop(i+1)
mn = min(mn, min_steps(N-1,temp, level+1))
return mn
This solution has complexity of O(N^N). I want to reduce it to polynomial time near to O(N^2) or O(N^3). Can anyone help me modify this solution or tell me if I am missing something?
Combining any k adjacent pairs of elements (even if they include elements formed from previous combining steps) leaves exactly n-k elements in total, each of which we can map back to the contiguous subarray of the original problem that constitutes the elements that were added together to form it. So, this problem is equivalent to partitioning the array into the largest possible number of contiguous subarrays such that all subarrays have the same sum: Any adjacent pair of elements within the same subarray can be combined into a single element, and this process repeated within the subarray with adjacent pairs chosen in any order, until all elements have been combined into a single element.
So, if there are n elements and they sum to T, then a simple O(nT) algorithm is:
For i from 0 to T:
Try partitioning the elements into subarrays each having sum i. This amounts to scanning along the array, greedily adding the current element to the current subarray if the sum of elements in the current subarray is strictly < i. When we reach a total of exactly i, the current subarray ends and a new subarray (initially having sum 0) begins. If adding the current element takes us above the target of i, or if we run out of elements before reaching the target, stop this scan and try the next outer loop iteration (value of i). OTOH if we get to the end, having formed k subarrays in the process, stop and report n-k as the optimal (minimum possible) number of combining moves.
A small speedup would be to only try target i values that evenly divide T.
EDIT: To improve the time complexity from O(nT) to O(n^2), it suffices to only try target i values corresponding to sums of prefixes of the array (since there must be a subarray containing the first element, and this subarray can only have such a sum).

Find way to separate array so each subarrays sum is less or equal to a number

I have a mathematical/algorithmic problem here.
Given an array of numbers, find a way to separate it to 5 subarrays, so that sum of each subarrays is less than or equal to a given number. All numbers from the initial array, must go to one of the subarrays, and be part of one sum.
So the input to the algorithm would be:
d - representing the number that each subarrays sum has to be less or equal
A - representing the array of numbers that will be separated to different subarrays, and will be part of one sum
Algorithm complexity must be polynomial.
Thank you.
If by "subarray" you mean "subset" as opposed to "contiguous slice", it is impossible to find a polynomial time algorithm for this problem (unless P = NP). The Partition Problem is to partition a list of numbers into to sets such that the sum of both sets are equal. It is known to be NP-complete. The partition problem can be reduced to your problem as follows:
Suppose that x1, ..., x_n are positive numbers that you want to partition into 2 sets such that their sums are equal. Let d be this common sum (which would be the sum of the xi divided by 2). extend x_i to an array, A, of size n+3 by adding three copies of d. Clearly the only way to partition A into 5 subarrays so that the sum of each is less than or equal to d is if the sum of each actually equals d. This would in turn require 3 of the subarrays to have length 1, each consisting of the number d. The remaining 2 subarrays would be exactly a partition of the original n numbers.
On the other hand, if there are additional constraints on what the numbers are and/or the subarrays need to be, there might be a polynomial solution. But, if so, you should clearly spell out what there constraints are.
Set up of the problem:
d : the upper bound for the subarray
A : the initial array
Assuming A is not sorted.
(Heuristic)
Algorithm:
1.Sort A in ascending order using standard sorting algorithm->O(nlogn)
2.Check if the largest element of A is greater than d ->(constant)
if yes, no solution
if no, continue
3.Sum up all the element in A, denote S. Check if S/5 > d ->O(n)
if yes, no solution
if no, continue
4.Using greedy approach, create a new subarray Asi, add next biggest element aj in the sorted A to Asi so that the sum of Asi does not exceed d. Remove aj from sorted A ->O(n)
repeat step4 until either of the condition satisfied:
I.At creating subarray Asi, there are only 5-i element left
In this case, split the remaining element to individual subarray, done
II. i = 5. There are 5 subarray created.
The algorithm described above is bounded by O(nlogn) therefore in polynomial time.

finding the maximum number in array

there is an array of numbers an this array is irregular and we should find a maximum number (n) that at least n number is bigger than it (this number may be in array and may not be in array )
for example if we give 2 5 7 6 9 number 4 is maximum number that at least 4 number (or more than it ) is bigger than 4 (5 6 7 9 are bigger)
i solve this problem but i think it gives time limit in big array of numbers so i want to resolve this problem in another way
so i use merge sort for sorting that because it take nlog(n) and then i use a counter an it counts from 1 to k if we have k number more than k we count again for example we count from 1 to 4 then in 5 we don't have 5 number more than 5 so we give k-1 = 4 and this is our n .
it's good or it maybe gives time limit ? does anybody have another idea ?
thanks
In c++ there is a function called std::nth_element and it can find the nth element of an array in linear time. Using this function you should find the N - n- th element (where N is the total number of elements in the array) and subtract 1 from it.
As you seek a solution in C you can not make use of this function, but you can implement your solution similarly. nth_element performs something quite similar to qsort, but it only performs partition on the part of the array where the n-th element is.
Now let's assume you have nth_element implemented. We will perform something like combination of binary search and nth_element. First we assume that the answer of the question is the middle element of the array (i.e. the N/2-th element). We use nth_element and we find the N/2th element. If it is more than N/2 we know the answer to your problem is at least N/2, otherwise it will be less. Either way in order to find the answer we will only continue with one of the two partitions created by the N/2th element. If this partition is the right one(elements bigger than N/2) we continue solving the same problem, otherwise we start searching for the max element M on the left of the N/2th element that has at least x bigger elements such that x + N/2 > M. The two subproblems will have the same complexity. You continue performing this operation until the interval you are interested in is of length 1.
Now let's prove the complexity of the above algorithm is linear. First nth_element is linear performing operations in the order of N, second nth_element that only considers one half of the array will perform operations in the order of N/2 the third - in the order of N/4 and so on. All in all you will perform operations in the order of N + N/2 + N/4 + ... + 1. This sum is less than 2 * N thus your complexity is still linear.
Your solution is asymptotically slower than what I propose above as it has a complexity O(n*log(n)), while my solution has complexity of O(n).
I would use a modified variant of a sorting algorithm that uses pivot values.
The reason is that you want to sort as few elements as possible.
So I would use qsort as my base algorithm and let the pivot element control which partition to sort (you will only need to sort one).

Finding the number of elements between i and j in an integer array in o(1)

Given an unsorted integer array and 2 numbers i and j such that 0 <= i <= j <= C(a constant say MAX_INTEGER) what kind of pre-processing can be performed on it so that you will be able to find the number of numbers between i and j(both inclusive) in o(1) time. The array can also have duplicates.
I had thought of building a frequency array f[] for the elements in the array(space o(C)) and also
another array cf[] for cumulative frequency(space o(C)).
So given i and j, i can look up the cumulative frequency array and do cf[j] - cf[i] - This will give the number of elements between i and j. To include i and j, look up the frequency array and add the values. ie cf[j] - cf[i] + f[i]+f[j]
Time complexity will be o(1) * 4 = constant time.
The look up in the frequency array can be avoided by finding the previous non zero cf array element for both i and j in the respective direction. This will increase the time complexity but will reduce the space complexity.
Wanted to know if there is a better solution for this problem.
Note - Values of i and j will be available to you only after the pre-processing is completed.
-Vijay
I can't imagine how you'd do this in O(1) without using O(C) additional space.
You can do the lookup in O(log n) very easily if you just create a sorted copy of the array on startup. (O(n log n)).
The lookup then becomes:
Binary search to find the first occurrence of i
Binary search to find the last occurrence of j
result = position_of_j - position_of_i + 1
Now, if the range of items in the array is relatively small, you could do it in O(max - min + 1) extra space and get O(1) lookup. But worst case, (max - min + 1) == C.
How about this,
First off, sort the integer array. and create a hash table with a key for every unique integer in the array and the value as indices in the array at which that integer occurs first and last in the sorted array,(since dup is possible). Space complexity of hash table would be O(n) and access complexity is constant, you have to allocate the space for hash table accordingly.
Given these extra data structures, if you want to find out the range of numbers between i and j, get first index of i and get last index of j, from the hash table and subtract the first from the latter to get the result.
Dim result() as integer
Dim C(1000) as integer
Dim Buff() as integer
Dim i as integer=50
dim j as integer=450
for count =0 to c.count-1
if c(count)>i and c(count)<j then
dim length as integer=buff.count-1
redim result(lenght+1)
for buffcount=0 to buff.count
result(buffcount)=buff(buffcount)
next
result(result.count-1)=c(count)
redim buff(result.lenght-1)
buff=result
end if
next
Idea:
1. Binary search to find the first occurrence of i
2. Binary search to find the last occurrence of j
3. result = position_of_j - position_of_i + 1
or
1. first enter size of array
2. then enter elements of array
3. then query size
4. then enter left, right
code link : HackerEarth

Arrays: find two numbers such that their sum is maximum with some additional conditions

Given a set of numbers and a number k, find the maximum sum such that if you pick a number at index i you should not pick any number from index i - K to index i + K.
This problem was asked in google to my friend. I am not able to figure out a solution better then a naive O(n^2).
You can do this in O(n) by keeping track of the maximum of all values seen in the first i-K-1 entries in the array.
Python code:
A=[3,9,10,3,6,7,1,5]
K=2
m=A[0]
bestsum=0
for i in xrange(K+1,len(A)):
m=max(A[i-K-1],m) # stores maximum of values in A[0],A[1],...,A[i-K-1]
bestsum=max(bestsum,A[i]+m)
print bestsum
For each index i we combine A[i] with m which is the highest value seen in the initial values of the array A[0],..,A[i-K-1].
You may be able to modify this http://www.geekviewpoint.com/java/dynamic_programming/positive_subset_sum or http://www.geekviewpoint.com/java/dynamic_programming/max_subarray_sum.
Sorting the array before may not be acceptable for the question

Resources