finding maximum of a subarray - algorithm

Preprocess an array A in O(n log n) time so that you can answer queries of the form
findmax(i,j): find the maximum value in an interval [i; j] (that is, the maximum value
among the array elements A[i],A[i + 1],...,A[j]) in O(1)) time per query.
Additional question: Show how to preprocess in O(n) time so that you can answer the above queries in O(log n) time.

The problem is known as range minimum (maximum) query - RMQ. The link basically answers both of your questions.
The classic solutions are dynamic programming and segment trees.

Related

Are there any Computational problem with ϴ(logn)^2 algorithm?

Are there any real computaional problems which can be solved by time complexity of log(n) * log(n)?
This is different from finding smallest element in sorted matrix, which is log(n)+log(n) or 2log(n).
There are can be some kind of pattern printing algorithm which can be made as ϴ(logn)^2 but I'm not sure if they are classified as Computational Problems.
A range query on a d-dimensional range tree with k results runs in O(log^d(n) + k) time. So a query that you know will result in a bounded number of results on a 2-d range tree runs in O(log^2(n)) time.
See https://en.wikipedia.org/wiki/Range_tree
Dichotomic search in a sorted array when the indexes are processed as binary strings (bignums).

A linear algorithm for this specification?

This is my question I have got somewhere.
Given a list of numbers in random order write a linear time algorithm to find the 𝑘th smallest number in the list. Explain why your algorithm is linear.
I have searched almost half the web and what I got to know is a linear-time algorithm is whose time complexity must be O(n). (I may be wrong somewhere)
We can solve the above question by different algorithms eg.
Sort the array and select k-1 element [O(n log n)]
Using min-heap [O(n + klog n)]
etc.
Now the problem is I couldn't find any algorithm which has O(n) time complexity and satisfies that algorithm is linear.
What can be the solution for this problem?
This is std::nth_element
From cppreference:
Notes
The algorithm used is typically introselect although other selection algorithms with suitable average-case complexity are allowed.
Given a list of numbers
although it is not compatible with std::list, only std::vector, std::deque and std::array, as it requires RandomAccessIterator.
linear search remembering k smallest values is O(n*k) but if k is considered constant then its O(n) time.
However if k is not considered as constant then Using histogram leads to O(n+m.log(m)) time and O(m) space complexity where m is number of possible distinct values/range in your input data. The algo is like this:
create histogram counters for each possible value and set it to zero O(m)
process all data and count the values O(m)
sort the histogram O(m.log(m))
pick k-th element from histogram O(1)
in case we are talking about unsigned integers from 0 to m-1 then histogram is computed like this:
int data[n]={your data},cnt[m],i;
for (i=0;i<m;i++) cnt[i]=0;
for (i=0;i<n;i++) cnt[data[i]]++;
However if your input data values does not comply above condition you need to change the range by interpolation or hashing. However if m is huge (or contains huge gaps) is this a no go as such histogram is either using buckets (which is not usable for your problem) or need list of values which lead to no longer linear complexity.
So when put all this together is your problem solvable with linear complexity when:
n >= m.log(m)

Segment tree: amount of numbers smaller than x

I'm trying to solve this problem.
I found tutorial for this problem but I don't get how to build segment tree that will find amount of numbers less than x in O(log n) (x can change). In tutorial it has been omitted.
Can anyone explain me how to do it ?
It is pretty simple:
Store a sorted array of all numbers in a range covered by a particular node( O(n * log n) memory and time for initialization).
To answer a query, decompose the query segment into O(log n) nodes(the same way as it is done for a standard min/max/sum segment tree) and run binary search over the array stored in each of those nodes to find the number of elements less than x. It gives O(log^2 n) time per query. You can also achieve O(log n) using fractional cascading, but it is not necessary.

Find minimum element of a subsequence

Given a sequence S of n integer elements, I need a function min(i,j) that finds the minimum element of the sequence between index i and index j (both inclusive) such that:
Initialization takes O(n);
Memory space O(n);
min(i,j) takes O(log(n)).
Please suggest an algorithm for this.
Segmenttree is that what you need because it fulfils all your requirements.
Initialisation takes O(n) with Segment Tree
Memory is also O(n)
Queries can be done in O(log n)
Beside this, the tree is dynamic and can support updating in O(log n). This means one can modify the element of some element i in O(log n) and still retrieve the minimum.
This TopCoder tutorial: An < O(n), O(1) > approach discusses your problem in a more detail way. In the notation, means the approach takes f(n) complexity to setup, and g(n) complexity to query.
Also, this post chews the algorithm again: Range Minimum Query <O(n), O(1)> approach (from tree to restricted RMQ).
Hope them clarifies your question :)
Segment tree is just what you need(it can be build in O(n) time and one query takes O(log n) time).
Here is an article about it: http://wcipeg.com/wiki/Segment_tree.
Even though there is an algorithm that uses O(n) time for initialization and O(1) time per query, segment tree can be a good choice because it is much simpler.

Is n operations of O(1) average time each considered O(n) in average?

I'm studying to data structures exam and I'm trying to solve this question:
given an array of n numbers and a number Z, find x,y such as x+y=Z , in O(n) average time.
My suggestion is move the array's content to a hash table, and using open addressing do the following:
For each number A[i] search for Z-A[i] in the hash table (O(1) in average for each operation.) Worst case you'll perform n searches, O(1) average time each, that's O(n) in average.
Is my analysis correct?
Given that you are traversing all your array the second time, yes that is O(n) * O(1) (and not O(n)+O(1) as previously stated from me) (for hash lookup in average time), so you are talking about an algorithm of O(n) complexity .

Resources