Time complexity halving an array - java

What would be the time complexity of partitioning an array in two and finding the minimum element overall?
Is it O(n) or O(log n)?

The complexity of dividing an (unsorted) array into 2 sorted partitions is O(NlogN).
Once you have two sorted partitions, it is O(1) to find the smallest element in either ... and hence both partitions.
(The smallest element of a sorted partition is the first one.)

Time Complexity for Partitioned Array
If an array A is already divided in two sorted partitions P1 and P2, where P1 is distributed along the indexes of A 0 <= i < k and P2 along the indexes k <= i < n with k an arbitrary index within the range 0 <= k < n.
Then, you know that the smallest element of both partitions is their first. Accessing both partition's first element has a time complexity of O(1) and comparing the two smallest values retrieved has again a time complexity of O(1).
So, the overall complexity of finding the minimum value in an array divided into two sorted partitions is O(1).
Time Complexity for Array to Partition
Instead, if the given array A has to be sorted in two sorted partitions (because this is a requirement) and then you need to find its minimum element. Then you need to divide your array into two partitions with an arbitrary index k, sort the two partitions with the most efficient sorting algorithm, which has complexity O(n log n), and then applying the same logic exposed above in finding the minimum element.
For any given value of k, with k 0 <= k < n, we would have to apply the sorting algorithm twice (on both partitions). However, since the additive property of Complexity Computation states that the addition of two complexities of the same order is still equal to the same complexity, then for example for k = n/2 we would have that: O(n/2 log n/2) + O(n/2 log n/2) still produces O(n log n). More in general O(k log k) + O((n-k) log (n-k)) with 0 <= k < n and n => ∞, which will still give us O(n log n) due to the constant factors property. Finally, we need to account to this complexity the constant complexity, O(1) of finding the minimum element among the two partitions, which will still give us O(n log n).
In conclusion, the overall complexity for dividing an array A in two partitions P1 and P2 and finding the minimum element overall is O(n log n).

Related

Find the Kth min element in the grid?

We are given a grid of size N * N where each element A[i][j] is calculated by this equation (i + j) ^ 2 + (j-i) * 10^5.
We need to find the Kth min element in optimized way.
Constraints :
1 <= number of test cases <= 20
1 <= N <= 5*10^4
1 <= k <= N^2
How to solve this problem in an efficient way ?
The problem that you are trying to solve (finding kth smallest element in an unordered array) is called the selection problem. There are many ways to solve this problem, and one of the best known ways is the quick select algorithm.
You can solve this problem in O(N log N) time. Note that that is sublinear in the size of the matrix, which is N*N. Of course you should never actually construct the matrix.
First, it helps to see what the values in the matrix looks like:
Note that over the possible range of matrix sizes, the smallest element is always at (i,j) = (N-1,0).
The largest element will be either (0,N-1) or (N-1,N-1), depending on the size of the matrix.
Consider the elements on the line from the smallest to largest. If you pick any one of these elements, then you can trace the contour to find the number of <= elements in O(N) time.
Furthermore, the elements on this line are always monotonically increasing from smallest to largest, so do a binary search on this line of elements, to find the largest one such that the number of <= elements is < k. At O(N) time per test, this takes O(N log N) all together.
Let's say the element you discover has value x, and the number of elements <= x is r, with r < k. Next trace the contour for the next higher element on the line, call its value y, and make list of all the values v such that x < v <= y. There will be O(N) elements in this list, and this takes only O(N) time.
Finally, just use sorting or quickselect to pick the (k-r)th element from this list. Again this takes at mostO(N log N) time.

Algorithm with O(m (log n + log m)) time complexity for finding kth smallest element in n*m matrix with each row sorted?

I ran into an interview question recently.
We have m*n matrix such that each row is in non-decreasing order (sorted with distinct elements). design an algorithm on order O(m (log m+ log n)) to find k-th smallest element on this matrix (just one element as k-th smallest element).
I think this is not possible so search on Google and find this link and another solution and this answer to a similar question.
I think as follows:
Put the median of all rows into an array and we find the median of this array in O(m) and called it pivot
We find the rank of this element in O(m log n). i.e: in each row how many elements are lower than the pivot found in step (1).
By comparing k and "rank of the pivot" we can know that in each row works on the right half or left half. (reduce to m*n/2 matrix.)
But the time complexity of this algorithm is O(m * log^2 n). What is the algorithm that can works on O(m (log n + log m))? Is there any idea?
m - rows
n - columns
Is it compulsory that you want a solution with O(m (log m+ log n)) Complexity?
I Can Think of a Solution with Complexity O(k * log-m) with extra space of O(m)
You can use a modified PriorityQueue (heap) DataStructure for this complexity
class PQObject {
int value; // PQ sorting happens on this int..
int m; // And m and n are positions.
int n;
}
You can just put all the values from the first column to the Priority Queue and Start popping until the kth smallest element
Every time you pop re-insert the next value of the row using m and n in the popped object.
Ultimately the problem comes down to find the kth smallest element in M sorted arrays.

Why are these loop & hashing operations take O(N) time complexity?

Given the array :
int arr[]= {1, 2, 3, 2, 3, 1, 3}
You are asked to find a number within the array that occurs odd number of times. It's 3 (occurring 3 times). The time complexity should be at least O(n).
The solution is to use an HashMap. Elements become keys and their counts become values of the hashmap.
// Code belongs to geeksforgeeks.org
// function to find the element occurring odd
    // number of times
    static int getOddOccurrence(int arr[], int n)
    {
        HashMap<Integer,Integer> hmap = new HashMap<>();
        // Putting all elements into the HashMap
        for(int i = 0; i < n; i++)
        {
            if(hmap.containsKey(arr[i]))
            {
                int val = hmap.get(arr[i]);
                // If array element is already present then
                // increase the count of that element.
                hmap.put(arr[i], val + 1); 
            }
            else
                // if array element is not present then put
                // element into the HashMap and initialize 
                // the count to one.
                hmap.put(arr[i], 1); 
        }
        // Checking for odd occurrence of each element present
          // in the HashMap 
        for(Integer a:hmap.keySet())
        {
            if(hmap.get(a) % 2 != 0)
                return a;
        }
        return -1;
    }
I don't get why this overall operation takes O(N) time complexity. If I think about it, the loop alone takes O(N) time complexity. Those hmap.put (an insert operation) and hmap.get(a find operations) take O(N) and they are nested within the loop. So normally I would think this function takes O(N^2) times. Why it instead takes O(N)?.
I don't get why this overall operation takes O(N) time complexity.
You must examine all elements of the array - O(N)
For each element of the array you call contain, get and put on the array. These are O(1) operations. Or more precisely, they are O(1) on averaged amortized over the lifefime of the HashMap. This is due to the fact that a HashMap will grow its hash array when the ratio of the array size to the number of elements exceeds the load factor.
O(N) repetitions of 2 or 3 O(1) operations is O(N). QED
Reference:
Is a Java hashmap really O(1)?
Strictly speaking there are a couple of scenarios where a HashMap is not O(1).
If the hash function is poor (or the key distribution is pathological) the hash chains will be unbalanced. With early HashMap implementations, this could lead to (worst case) O(N) operations because operations like get had to search a long hash chain. With recent implementations, HashMap will construct a balanced binary tree for any hash chain that is too long. That leads to worst case O(logN) operations.
HashMap is unable to grow the hash array beyond 2^31 hash buckets. So at that point HashMap complexity starts transitioning to O(log N) complexity. However if you have a map that size, other secondary effects will probably have affected the real performance anyway.
The algorithm first iterates the array of numbers, of size n, to generate the map with counts of occurrences. It should be clear why this is an O(n) operation. Then, after the hashmap has been built, it iterates that map and finds all entries whose counts are odd numbers. The size of this map would in practice be somewhere between 1 (in the case of all input numbers being the same), and n (in the case where all inputs are different). So, this second operation is also bounded by O(n), leaving the entire algorithm O(n).

Time complexity of k-th smallest number using PriorityQueue in Java

I am trying to solve the popular interview question Find the k-th smallest number in an array of distinct integers. I read some solutions and found that a heap data structure suits this problem very well.
So, I have tried to implement a solution using the PriorityQueue class of the Collections framework, assuming that it is functionally identical to a heap.
Here is the code that I've tried:
public static int getKthMinimum(int[] input, int k){
PriorityQueue<Integer> heap = new PriorityQueue<Integer>();
// Total cost of building the heap - O(n) or O(n log n) ?
for(int num : input){
heap.add(num); // Add to heap - O(log n)
}
// Total cost of removing k smallest elements - O(k log n) < O(n) ?
while(k > 0){
heap.poll(); // Remove min - O(log n)
k--;
}
return heap.peek(); // Fetch root - O(1)
}
Based on the docs, the poll & add methods take O(log n) time and peek takes constant time.
What will be the time complexity of the while loop? (I think O(k log n)).
Should O(k log n) be considered higher than O(n) for the purpose of this question? Is there a threshold where it switches?
What will be the total time complexity of this code? Will it be O(n)?
If not already O(n), is there a way to solve it in O(n), while using the PriorityQueue class?
1. What will be the time complexity of the while loop? (I think O(k log n)).
O(k log n) is correct.
2. Should O(k log n) be considered higher than O(n) for the purpose of this question? Is there a threshold where it switches?
You cannot assume that. k can be anywhere from 0 to n−1, which means that k log n can be anywhere from 0 to n log n.
3. What will be the total time complexity of this code? Will it be O(n)?
O(n log n), because that's the cost of building the heap.
It's possible to build a heap in O(n) time, but your code doesn't do that; if it did, your total complexity would be O(n + k log n) or, equivalently, O(MAX(n, k log n)).
4. If not already O(n), is there a way to solve it in O(n), while using the PriorityQueue class?
No. There exist selection algorithms in worst-case O(n) time, but they're a bit complicated, and they don't use PriorityQueue.
The fastest PriorityQueue-based solutions would require O(MAX(n, n log MIN(k, n−k))) time. (The key is to keep only the k smallest elements in the heap while iterating — or the n−k largest elements and use a max-heap, if k is large enough for that to be worthwhile.)

Can InsertionSort complexity be brought down to O(nlogn)?

I was wondering if by using BinarySearch & ArrayLists in java the complexity of InsertionSOrt can be brought down to O(nlogn) from O(n2).
There are 2 things that contribute to O(n2) complexity in insertion sort :
1) Searching appropriate position for the elements to be replaced - which is O(n) per iteration. It can be reduced to O(log n) using binary search.
2) Once the correct position is found then shifting the elements greater than (or smaller than) the element to the right. In the worst case you will insert an element to the front of the list and this would require shifting all remaining elements in the sorted list to the right - Worst case is O(n) per iteration.
So total complexity using Binary Search & ArrayList would be :
O(n * n + n * log n)
The complexity for Insertion Sort is :
Iterate through all the remaining elements which are to be sorted. (O(n) for n elements)
a. if the next element (say at position k) is greater than the element at pos k-1, then do nothing (checking is O(1) ). i.e, O(n * 1) is best case where already all elements are sorted.
b. if the element at pos k is smaller than that at k-1, then move the element left until it is greater than the element to its left or there are no elements left to compare. . So O(n*n)

Categories