Time complexity analysis in data structures and algo - c++

Can we compare O(m+n) with O(n), are both same because we need to focus only on the highest power?

The complexity of both O(m+n) and O(n) is linear in relation to input n. In realtion to m, the complexity of O(m+n) is linear while O(n) is constant.
So, unless we analyse only the input n and assume m to be constant, we cannot in general simplify O(m+n) to O(n).
Sometimes we may be able to combine two input dimensions into one: For example, if m is number of input strings and n is the maximum length of input string, then we might reframe the premise by analysing complexity in relation to total length of all input strings.

O(m+n) is two-dimensional (it has to parameters, m and n) and you can't reduce it to one dimension without more information about the relationship between m and n.
A concrete example: Many graph algorithms (e.g. depth first search, topological sort) have time complexity O(v + e), where v is the number of vertices and e is the number of edges. You can consider two separate types of graph:
In a dense graph with lots of edges, e is proportional to v². The time complexity of the algorithm on this type of graph is O(v + v²), or O(v²).
In a sparse graph with few edges, e is proportional to v. The time complexity of the algorithm on this type of graph is O(v + v), or O(v).

Related

Time complexity for searching a list of lists?

Suppose I store a matrix as a list of lists, where the first list represents the rows, and each element in that list is a list representing the values in that row. What would the time complexity for finding an element be?
If I'm not mistaken, the average time complexity finding an element in a list using linear search is O(n), does that mean the average time complexity for a list of lists is O(n2)?
If n means the width and height of a square matrix, then a linear search in the matrix will take O(n2) time. More generally, a linear search in a rectangular m×n matrix will take O(mn) time. Both are because that is the number of entries in the matrix, and a linear search will do O(1) work per entry.
If instead you use n to mean the total number of entries in the matrix, then the time complexity is O(n) for the same reason as above.
Note that the above assumes testing for the search target takes O(1) time (e.g. comparing primitive integers). If that's false, then you should multiply the above by the time complexity of the equality test; for example, if for some reason you have an m×n matrix of strings of length c, then the running time will be O(mnc).
Well, you would have two indexes. So the complexity is equal two a list, but multiplied by two. That beeing said, if you want to model a matrix, you might consider using an array of arrays (not to be confused with a jagged array), because in normal circumstances, a matrix has a fixed size (a List<T> is a wrapper around a T[] to allow adding and removing items).

If you have an array of fixed size, and you need to go through it !n number of times, how does using binary search change the time complexity?

We want to find all permutations of a string of length n. Then, you are to search an array of fixed constant size, say 3000 and check if the string is in the array.
String arr[3000];
Because we will have !n permutations, we need to do !n searches.
Also, what difference does it make when you check 2 different strings against an element in the array versus just checking 1 string?
What is the time complexity?
My thoughts is that it will take at worst, log2(3000) to go through the array once. Time complexity of that is O(log2(3000)) which is O(1).
Now, you need to go through this array !n times so time complexity is O(!n).
So the binary search reducing the number of searches required should not be the focus when analyzing the time complexity of this algorithm.
My question is, binary search does reduce the number of searches and if you are gonna go through it n! times, shouldn't this be a significant difference?
Any insight to better my understanding is appreciated.
Big O complexity analysis only deals with quantities that are subject to change, by definition. That you get vacuous answers when all your quantities are constant is expected.
The constant factors are relevant when comparing two algorithms of equal Big-O, so your change from 3000 -> log2(3000) is a factor of about 200.
Thus you use the binary search because you are doing more than Big-O analysis. You have also estimated the constant factors, and see an easy 200x speedup
But equally you can have multiple terms in your complexity. You might say:
Let n be the input string length
Let m be the size of arr
Our algorithm is O( n * n! * log(m) ) (n for the string equality, n! for the permutations, log(m) for the binary searching)
It also rather depends on a model of cost. Usually this maps back to some abstract machine, e.g. we assume that operations have a certain cost. E.g. You might compare sorting algorithms by just the count of comparisons, or by just the count of swaps, or by the counts of both comparisons and swaps.

Algorithm complexity asymptote graph

I'm preparing a C++ project , which I have to calcute many algorithms complexity big-O and compare it with the theoric value on a graph. I made a time function that calculate the time execution of an algorithm but I didn't find a way to calculte the complexity and draw the curve using time T and Input N.
Any ideas ?
In a nutshell: If you defined theoretical complexity T(n) all you have to do is to execute test x times for given range of n: n1, ..., nx and measure time of each test. Then you choose median nm from your set of n1, ..., nx and compute coefficient c, defined as: c = t(nm)/T(nm). t(nm) is measured time for median of n (nm), T(nm) is calculated teoretical complexity for nm.
Next, for each of your n, compute coefficient q, which is coefficient of consistency of theoretical and experimental complexity of your algorithm:
Finally you may draw plot of q(n) which is asymptote graph and it should converges asymptotically to 1. If your graph asymptotically goes below 1 theoretical complexity is overestimated, if goes above 1 complexity is underestimated.

Complexity in Dijkstras algorithm

So I've been attempting to analyze a specialized variant of Dijkstras algorithm that I've been working on. I'm after the worst case complexity.
The algorithm uses a Fibonacci Heap which in the case of the normal Dijkstra would run in O(E + V log V).
However this implementation needs to do a lookup in the inner loop where we update neighbours. This lookup will execute for every edge and will be in logarithmic time, where the lookup is in a datastructure that contains all edges. Also the graph has the restriction that no node will have more than 4 neighbours.
O(Vlog V) is the complexity for the outer loop but I'm not sure what the worst case will be for the inner loop. I'm thinking that since that each edge in the graph will be checked O(E) times and each edge will take logarithmic time it should be Elog E which should exceed Vlog V and result in O(Elog E) complexity for the algorithm.
Any insight would be awesome!
The amortized complexity of Decrease-Key on Fibonacci Heap is O(1), that is to say you have |E| such operations on the Fibonacci Heap, the total cost will be O(E). Also you have |V| Extract-Min operations, which cost O(lnV) each. So the total cost is O(E+VlnV).

Efficient trick for maximal bipartite matching in bigger graph

Problem: We are given two arrays A & B of integers. Now in each step we are allowed to remove any 2 non co-prime integers each from the two arrays. We have to find the maximal number of pairs that can be removed by these steps.
Bounds:
length of A, B <=105
every integer <=109
Dinic's algorithm - O(V2E)
Edmonds-karp algorithm - O(VE2)
Hopcroft–Karp algorithm - O(E sqrt(V))
My approach up till now: This can be modeled as bipartite matching problem with two sets A and B and edges can be created between every non co-prime pair of integers from the corresponding set.
But the problem is that there can be O(V2) edges in the graph and most Bipartite matching and max-flow algorithms will be super slow for such large graphs.
I am looking for some problem specific or mathematical optimization that can solve the problem in reasonable time. To pass the test cases i need at most O(V log V) or O(V sqrt(V)) algorithm.
Thanks in advance.
You could try making a graph with vertices for:
A source
Every element in A
Every prime present in any number in A
Every element in B
A destination
Add directed edges with capacity 1 from source to elements in A, and from elements in B to destination.
Add directed edges with capacity 1 from each element x in A to every distinct prime in the prime factorisation of x.
Add directed edges with capacity 1 from each prime p to every element x in B where p divides x
Then solve for max flow from source to destination.
The numbers will have a small number of factors (at most 9 because 2.3.5.7.11.13.17.19.23.29 is bigger than 10**9), so you will have at most 1,800,000 edges in the middle.
This is much fewer than the 10,000,000,000 edges you could have had before (e.g. if all 100,000 entries in A and B were all even) so perhaps your max flow algorithm has a chance of meeting the time limit.