number of possible arrays with certain conditions using dp - algorithm

an array of increasing natural numbers between 1 and n is called beautiful if each number in the array is divisible by it's previous number. using dynamic programming, the question is to find the number of beautiful arrays with size k with the given time complexity:
O(n*k*root(n))
O(n*k*log(n))
what I could think of for the first one is that the number of divisors of a number can be found with O(root(n)) time complexity. I want to design a recursive algorithm that calculates the number of possible arrays for each i < k but I can't figure out how.

This problem can be broken into two parts:
Find the divisor DAG (nodes 1…n, arcs a → b iff a divides
b). Trial division will do this in Θ(n √n); enumerating
multiples, in Θ(n log n). The graph has Θ(n log n) arcs.
Count the number of paths of length k in a DAG. This is a basic
Θ((m + n) k)-time dynamic program. There is one path of length
0 from each node. The number of paths of length ℓ from each node is
the sum of the number of paths of length ℓ−1 from its successors.

Related

Efficiently counting matching inversions between multiple lists at once

This is a question about taking multiple rankings of the same elements and computing a statistic that depends on whether each possible inversion matches between one or more lists or not.
Given
L equal-length lists of length N comprising the first N integers in various orders
an arbitrary set of L weights , one corresponding to each list
some arbitrary non-linear scalar function f
I'd like to compute in O(L N log N) time (it's trivial to do in O(L N^2) time) the following quantity:
where
represents whether the integer i appears before the integer j in list l .
Is there a known algorithm for doing this? Or is it known to be impossible in O(L N log N) time?
So far I've found a binary-indexed trees inversion counting algorithm and I'm wondering if I could get what I need by building upon this idea.

log(n) vs log(k) in runtime of an algorithm with k < n

I am having trouble understanding the difference between log(k) and log(n) in complexity analysis.
I have an array of size n. I have another number k < n that is an input of the algorithm (so it's not a constant known ahead of time). What are some examples of algorithms that would have log(n) vs those that would have log(k) in their complexity? I can only think of algorithms that have log(n) in their complexity.
For example, mergesort has log(n) complexity in its runtime analysis (O(nlogn)).
If your algorithm takes a list of size n and a number of magnitude k < n, the input size is on the order of n + log(k) (assuming k may be on the same asymptotic order of n). Why? k is a number represented in a place-value system (e.g., binary or decimal) and a number of magnitude k requires on the order of log k digits to represent.
Therefore, if your algorithm takes an input k and uses it in a way that requires all its digits be used or checked (e.g., equality is being checked, etc.) then the complexity of the whole algorithm is at least on the order of log k. If you do more complicated things with the number, the complexity could be even higher. For instance, if you have something like for i = 1 to k do ..., the complexity of your algorithm is at least k - maybe higher, since you're comparing to a log k-bit number k times (although i will use fewer bits than k for many/most values of i, depending on the base).
There's no "one-size-fits-all" explanation as to where an O(log k) term might come up.
You sometimes see this runtime arise in searching and sorting algorithms where you only need to rearrange some small part of the sequence. For example, the C++ standard library's std::partial_sort function, which rearranges the sequence so that the first k elements are in sorted order and the remainder are in arbitrary order in time O(n log k). One way this could be implemented is to maintain a min-heap of size at most k and do n insertions/deletions on it, which is n operations that each take time O(log k). Similarly, there's an O(n log k)-time algorithm for finding the k largest elements in a data stream, which works by maintaining a max-heap of at most k elements.
(Neither of these approaches are optimal, though - you can do a partial sort in time O(n + k log k) using a linear-time selection algorithm and can similarly find the top k elements of a data stream in O(n).)m
You also sometimes see this runtime in algorithms that involve a divide-and-conquer strategy where the size of the problem in question depends on some parameter of the input size. For example, the Kirkpatrick-Seidel algorithm for computing a convex hull does linear work per level in a recurrence, and the number of layers is O(log k), where k is the number of elements in the resulting convex hull. The total work is then O(n log k), making it an output-sensitive algorithm.
In some cases, an O(log k) term can arise because you are processing a collection of elements one digit at a time. For example, radix sort has a runtime of O(n log k) when used to sort n values that range from 0 to k, inclusive, with the log k term arising from the fact that there are O(log k) digits in the number k.
In graph algorithms, where the number of edges (m) is related to but can be independent of the number of nodes (n), you often see runtimes like O(m log n), as is the case if you implement Dijkstra's algorithm with a binary heap.

Find time complexity of an element which is neither kth maximum nor kth minimum?

There are N distinct numbers which are given not in sorted order. How much time it will take to select a number say which is neither k-th minimum nor k-th maximum?
I tried like this =>
Take initial k + 1 numbers and sort them in O(k log k). Then pick up kth number in that sorted list, that will be neither the kth minimum nor kth maximum .
Hence, time complexity = O(K log k)
Example =>
Select a number which is neither the 2nd minimum nor 2nd maximum.
array[] = {3,9,1,2,6,5,7,8,4}
Take initial 3 numbers or subarray = 3,9,1 and sorted subarray will be = 1,3,9
Now pick up 2nd element 3. Now, 3 is not the 2nd minimum nor 2nd maximum .
Now, time complexity = O(k lg k) = O(2 lg 2) = O(1).
The problem is trivial if N < k. Otherwise there's no k'th largest or smallest element in the array -- so one can pick any element (for example the first) in O(1) time.
If N is large enough you can take any subset of size 2k+1 and choose the median. Then you have found a number that is guaranteed not to be the kth largest or smallest number in the overall array. In fact you get something stronger -- it's guaranteed that it will not be in the first k or last k numbers in the sorted array.
Finding a median of M things can be done in O(M) time, so this algorithm runs in O(k) time.
I believe this is asymptotically optimal for large N -- any algorithm that considers fewer than k items cannot guarantee that it chooses a number that's not the kth min or max in the overall array.
If N isn't large enough (specifically N < 2k+1), you can find the minimum (or second minimum value if k=1) in O(N) time. Since k <= N < 2k+1, this is also O(k).
There are three cases where no solution exists: (k=1, N=1), (k=1, N=2), (k=2, N=2).
If you only consider cases where k <= N, then the complexity of the overall algorithm is O(k). If you want to include the trivial cases too then it's somewhat messy. If I(k<=N) is the function that's 1 when k<=N and 0 otherwise, a tighter bound is O(1 + k*I(k<=N)).
I think there many points that must be noticed in your solution:
Firstly it would require to take 2k+1 elements instead of k+1 in your solution. More specifically you take :
array[] = {3,9,1,2,6,5,7,8,4}
Take initial 3 numbers or subarray = 3,9,1 and sorted subarray will be = 1,3,9
Now pick up 2nd element 3. Now, 3 is not the 2nd minimum nor 2nd maximum .
but to check that 3 is not the 2nd minimum nor 2nd you can't do it with your k+1 elements:subarray = 3,9,1 you have to check the array to see what is the 2 max and min and check your solution.
On the other hand by taking 2k+1 elements and sorting them ,since your elements are distinct you would know that the k+1 element is greater from the k first elements and smaller from the k last elements of your sorted subarray.
In your example you could see:
array[] = {3,9,1,2,6,5,7,8,4}
subarray[]={3,9,1,2,6} then sort the subarray :{1,2,3,6,9} ,and give as an answer the number 3 .
An example where your solution would not be rigt:
array[] = {9,8,2,6,5,3,7,1,4} where your algorithm would return the number 2 which is the second min .
As of terms of complexity .By taking 2k+1 elements it would not change the complexity that you found because it would be O((2k+1)log(2k+1)) which is O(klog(k)).
Clearly if n<2k+1 the above algorithm won't work ,so you will have to sort the entire array which would take nlog n , but in this case n<2k+1 so it O(klogk).
Finally the algorithm based on the above will be O(klog k) .A thing that might be confusing is that the problem has two parameters k,n .If K is much smaller than n this is efficient algorithm since you don't need to look and short the n-size array but when k,n are very close then it is the same as sorting the n-size array .
One more thing that you should understand is that big O notation is way of measuring the time complexity when an input n is given to the algorithm ,and shows the asymptotic behavior of the algorithm for big input n. O(1) denotes that the algorithm is running ALWAYS in constant time .So in the end when you refer:
Now, time complexity = O(k lg k) = O(2 lg 2) = O(1).
This is not Right you have to measure the complexity with k being the input variable and not a constant ,and this shows the behavior of the algorithm for a random input k. Clearly the above algorithm doesn't take O(1) (or else constant time) it takes O(k log(k)).
Finally ,after searching for a better approach of the problem, if you want a more efficient way you could find kth min and kth max in O(n) (n is the size of the array) .And with one loop in O(n) you could simply select the first element which is different from kth min and max. I think O(n) is the lowest time complexity you can get since finding kth min and max take the least O(n).
For how to find kth min,max in O(n) you could see here:
How to find the kth largest element in an unsorted array of length n in O(n)?
This solution is O(n) while previous solution was O(klog k) .Now for k parameter close to n ,as explained above it is the same as O(n log(n)) ,so in this occasion the O(n) solution is better .But if most of the times k is much smaller than n then then O(k log k) may be better .The good thing with the O(n) solution (second solution) is that in all cases it takes O(n) regardless to k so it is more stable but as mentioned for small k the first solution may be better (but in the worst case it can reach O(nlogn)).
You can sort the entire list in pseudo-linear time using radix-sort and select the k-th largest element in constant time.
Overall it would be a worst-case O(n) algorithm assuming the size of the radix is much smaller than n or you're using a Selection algorithm.
O(n) is the absolute lower bound here. There's no way to get anything better than linear because if the list is unsorted you need to at least examine everything or you might miss the element you're looking for.

Find triplets in an array whose sum is some integer X

Given a sorted array[1..n] where each element ranging from 1 to 2n. Is there a way to find triplet whose sum is given integer x. I know O(n^2) solution. Is there any algorithm better than n^2 ones.
It is possible to achieve an O(n log n) time complexity using that fact the maximum value of each element is O(n).
For each 1 <= y <= 4 * n, let's find the number of pairs of elements that sum up to y. We can create a polynomial of 2 * n power, where the i-th coefficient of this polynomial is the number of occurrences of the number i in the given array. Now we can find the square(I'll call it s) of this polynomial in O(n log n) time using Fourier's Fast Transform. The i-th coefficient of s is exactly the number of pairs of elements that sum up to i.
Now we can iterate over the given array. Let's assume that the current element is a. Then we just need to check the number of pairs that sum up to X - a. We have already done it in the step 1).
If all triplets must consist of different elements, we need to subtract the number of such triplets that sum up to X but contain duplicates. We can do it in O(n log n) time, too(for triplets that consist of three equal elements, we just need to subtract the number of occurrences of X / 3 in the given array. For triplets with one duplicate, we can just iterate over the element that is repeated twice(a) and subtract the number of occurrences of X - 2 * a).
If we need to find a triplet itself, not just count them, we can do the following:
Count the number of triplets and pairs as suggested above.
Find such an element that there is a pair that sums up to X with it.
Find two elements that sum up to the desired sum of this pair.
All these steps can be accomplished in linear time(using the fact that all sums are O(n)).
Your problem is apparently the non-zero sum variant of the 3SUM problem.
Because you know the possible range of the integers beforehand, you can achieve lower bounds than the general case, according to the second paragraph of the article:
When the elements are integers in the range [-N, ..., N], 3SUM can be
solved in O(n + N log N) time by representing the input set S as a
bit vector, computing the set S + S of all pairwise sums as a discrete
convolution using the Fast Fourier transform, and finally comparing
this set to -S.
In your case, you would have to pre-process the array by subtracting n + X/3 before running the algorithm.
One thing to note is that the algorithm assumes you're working with a set of numbers, and I'm not sure what (if any) implications there may be on running time if your array may include duplicates.

Rewrite O(N W) in terms of N

I have this question that asks to rewrite the subset sum problem in terms of only N.
If unaware the problem is that given weights, each with cost 1 how would you find the optimal solution given a max weight to achieve.
So the O(NW) is the space and time costs, where space will be for the 2d matrix and in the use of dynamic programming. This problem is a special case of the knapsac problem.
I'm not sure how to approach this as I tried to think about it and only thing I thought of was find the sum of all weights and just have a general worst case scenario. Thanks
If the weight is not bounded, and so the complexity must depend solely on N, there is at least an O (2N) approach, which is trying all possible subsets of N elements and computing their sums.
If you are willing to use exponential space rather than polynomial space, you can solve the problem in O(n 2^(n/2)) time and O(2^(n/2)) space if you split your set of n weights into two sets A and B of roughly equal size and compute the sum of weights for all the subsets of the two sets, and then hash all sums of subsets in A and hash W - x for all sums x of subsets of B, and if you get a collision between a subset of A and a subset of B in the hash table then you have found a subset that sums to W.

Resources