How to analyze the following algorithm complexity [duplicate] - java

This question already has answers here:
What is time complexity and how to find it? [duplicate]
(2 answers)
What is complexity of this code? (Big O) Is that linear?
(1 answer)
Closed 2 years ago.
I am new to algorithm analysis, so I appreciate if anyone can help me. I have the following algorithm for sorting an array:
for(int i = 0 ; i < list ; i++){
if(list[i] > list[i+1]){
swap list[i] with list[i+1]
i = -1;
}
}
I claim that this algorithm is a linear algorithm (i.e, O(n)) but I did not know how to prove this.
I appreciate any help.
Thanks in advance.

This algorithm is actually cubic (O(n^3) where n = length of list) in the worst case scenario. Imagine the following input: list = [5,4,3,2,1].
First iteration: list[0] > list[1]. The swap is made such that list = [4,5,3,2,1], and i is reduced to -1, so the loop starts over.
Second iteration: list[0] < list[1].
Third iteration: list[1] > list[2]. The swap is made such that list = [4,3,5,2,1], and i is reduced to -1, so the loop starts over.
Fourth iteration: list[0] > list[1]. The swap is made such that list = [3,4,5,2,1], and i is reduced to -1, so the loop starts over.
The same pattern continues: we will need 6 more iterations to bring 2 to the start of the list, 10 iterations for 1, and 5 to skim over the list once it's all sorted. Overall 4+6+10+5=25 which is 5^2. So why n^3 and not n^2?
Intuition:
For a list that sorted in reverse like the one in the above example, we would need to bring each element to the head of the list from greatest to smallest. The j'th element in the initial list is the j'th greatest overall and will need (1+2+...+j)=O(j^2) steps to bring to the head of the list.
Therefore, in order to reverse the list of length n, we need approximately (1^2 + 2^2 + ... + n^2) steps. That is the sum of squares from 1 to n which is O(n^3) - if you don't know why, it's a very well-known formula in arithmetics: sum of squares.
Disclaimer: Of course, it wouldn't be exactly n^3 steps, but it will be approximately so (which is after all the definition of Big-O notation. It will be closer to n^3 the bigger n gets).

Related

Time complexity of the following program [duplicate]

This question already has answers here:
How can I find the time complexity of an algorithm?
(10 answers)
Closed 4 years ago.
So, basically I wanted to find all the elements in the second array which are less than or equal to the element of 1st array. Both the arrays are sorted. I know the solution. I don't want that.
I just want to know the time complexity of this program and how will we calculate it. Thank you in advance.
int count=0;
for(int i=0;i<n;i++)
{
for(int j=count;j<m;j++)
{
if(arr[i]>=arr[j])
//some O(1) code
else
{
count=j;
break;
}
}
}
The complexity will be O(n*m) simply because the outer loop for each value of n will run m times.
Well there is only one array in your code. In contrary to your explaination that says there are two arrays.
Assuming there is a typo and there should be a second array:
Worst: You can establish an upper bound at O(n * m). Happens if all elements in the second are smaler than in the first.
Best: You can establish a lower bound at O(n) .
Happens if all elements of the second are bigger than in the first(first element breaks the loop).
Average: If you asume an even distribution you get an average at O(n * m / 2).
Conclusion Its a O(n²) league algorithm.
Only one array:
However if I take the code "as is" - only one array and also take into account that it is sorted:
If arr1[i] < arr2[j] for i < j holds:
It will skip the inner loop for j>i. -> the inner loop will stop at j==i; -> upper bound at O(n * m / 2). Still an O(n²) league.
Reverse Order
So arr[i] < arr[j] for i>j holds:
It will skip the inner loop for j < i so the inner loop will be executed at most one time: O(n+m) rsp. O(n).
But I guess it is a typo and you ment two arrays so I skip the case sorted with duplicates(it is again O(n*m) eg. if all elements are the same).
O(n*m)- since you are going through 'n' outer elements
and for each outer element you have an inner loop with m elements.
For loops time complexity - O(n). Basically how many times the for loop will run.
Complexity : O(m*n)
As two for loops involved in this, it may be vary in different cases but it has to be O(m*n) if both gets executed.

Order of growth according to Big-O Notation [duplicate]

This question already has answers here:
Big O, how do you calculate/approximate it?
(24 answers)
How can I find the time complexity of an algorithm?
(10 answers)
Closed 4 years ago.
Hello Stack Users, I am having trouble finishing this growth according to size algorithm problem. I was able to figure out the first two of the problem which are not listed in the picture. That would be 1. O(1) and 3. O(N) I was able to place these into their correct slots. I still cannot figure out how to determine the growth rate for 2,4,5,6 into the slots provided. Any suggestions on how to determine this?
O(N)
The first for loop takes N and the second also takes N so
O(N) = N + N = 2N = N
O(N^2)
The first for loop takes N and the second also N, but in this case it is nested. inner loop takes N for every other loop of outer loop
O(N) = N * N = O(N^2)
O(N)
The first for loop it takes N and the second also 5, but it is nested so
O(N) = 5 * N = 5N = O(N)
O(log(N))
to divide a number N by 2 continuously until it reaches 1, it takes
log(N)

Longest subarray with sum less than equal to k [duplicate]

This question already has answers here:
Longest positive subarray
(2 answers)
Closed 6 years ago.
Given an array of positive integers a, and an integer k, I'm trying to figure out an algorithm which will give me the length of the longest subarray, the sum of which is less than or equal to k. I have figured out how to solve it in O(n^2) time, but am trying to solve in in as close to O(n) as I can.
For a O(n) solution, I'm trying to create a start index and an end index, which will give me a window. I want to check if the sum within this window is <= k AND if the length of this window is greater than the last recorded length. However, when typing it out, my logic breaks down.
I think you mean
maxLen = currLen;
I don't think its part of your problem but you don't use end and I don't think it's updated correctly. Just remove it.

Given a list, find K different elements such that their sum is S

I know that when asked to find two elements whose add up to a given number then the solution can be obtained in O(n) time, namely by making a hashmap and when iterating over the list, simply find an element such that a[j]=S - l[i]. I want to be able to generalize this to K distinct elements. How would i approach such a problem? Recursively, nested loops? I'm assuming that the best complexity in this case will be O(n^{k-1}), is this intuition also correct?
The straight-forward adaptation of this algorithm is the following:
When iterating over the list, instead of finding one element e with S = e + l[i], find k elements e[j] with S = Sum e[j] + l[i].
sums <- HashMap<Number, Set<Number>>
put (0, { }) into sums //we can achieve a sum of 0 with no element
for j from 1 to k - 1 //number of elements to use
newSums <- HashMap<Number, Set<Number>>
for i from 0 to n - 1
for each entry (sum, elements) in sums //iterate every combination of j elements
newSum <- l[i] + sum
if not newSums contains newSum
newSums.add (newSum, elements union { i })
next
swap(sums, newSums)
next
for i from 0 to n - 1
lookingForSum <- S - l[i]
if sums contains lookingForSum
return sums[lookingForSum] union { i }
next
The critical part is that sums may become very large. After the first iteration (k=1), there are n different sums (if all entries are different). Hence, the second iteration runs n * n times, producing at most n * (n + 1) / 2 different sums (or O(n^2)). Then, the third iteration runs n * O(n^2) = O(n^3) times, and so on. So the overall time complexity is indeed O(n^{k-1}).
EDIT: I realize the following algorithm allows duplicates as well. So, yes, I think the complexity will increase to O(n^(k-1)) if only unique elements need to be considered.
This question depends whether k is even or odd. For instance, consider k to be 3, i.e. a+b+c = S, where a,b,c belong to the array. By brute force, we know that the complexity will be O(n^3). However, if you store all the array elements in a set, all we need to find is to see if S - (a+b) is present in the set. This gives us O(n^2) complexity.
Now if you consider k = 4, if you realize, all you need to do is to compute a set R of sums of all 2-element subsets of the original array (makes sense?). Then, for every two elements a and b in the original array, check if S−a−b is in R. That again gives us O(n^2) algorithm for k = 4.
Drawing similar intuition, when k is even, all we need to do are:
Determine a set R that stores all the sums of all the k/2-element tuples of the original array.
For every k/2 tuple of elements in the original array, compute its sum, say s. If S - s ∈ R, a solution is present.
The complexity thus is O(n^(k/2))
When k is odd, only a slight modification is required.
For the first step, sums of all (k-1)/2 - tuples of the original array are stored in R.
For every (k+1)/2 tuple of elements in the original array, compute its sum, say s. If S - s ∈ R, a solution is present.
Complexity will be O(n ^ (k+1)/2 )

custom partition problem

Could some one guide me on how to solve this problem.
We are given a set S with k number of elements in it.
Now we have to divide the set S into x subsets such that the difference in number of elements in each subset is not more than 1 and the sum of each subset should be as close to each other as possible.
Example 1:
{10, 20, 90, 200, 100} has to be divided into 2 subsets
Solution:{10,200}{20,90,100}
sum is 210 and 210
Example 2:
{1, 1, 2, 1, 1, 1, 1, 1, 1, 6}
Solution:{1,1,1,1,6}{1,2,1,1,1}
Sum is 10 and 6.
I see a possible solution in two stages.
Stage One
Start by selecting the number of subsets, N.
Sort the original set, S, if possible.
Distribute the largest N numbers from S into subsets 1 to N in order.
Distribute the next N largest numbers from S the subsets in reverse order, N to 1.
Repeat until all numbers are distributed.
If you can't sort S, then distribute each number from S into the subset (or one of the subsets) with the least entries and the smallest total.
You should now have N subsets all sized within 1 of each other and with very roughly similar totals.
Stage Two
Now try to refine the approximate solution you have.
Pick the largest total subset, L, and the smallest total subset, M. Pick a number in L that is smaller than a number in M but not by so much as to increase the absolute difference between the two subsets. Swap the two numbers. Repeat. Not all pairs of subsets will have swappable numbers. Each swap keeps the subsets the same size.
If you have a lot of time you can do a thorough search; if not then just try to pick off a few obvious cases. I would say don't swap numbers if there is no decrease in difference; otherwise you might get an infinite loop.
You could interleave the stages once there are at least two members in some subsets.
There is no easy algorithm for this problem.
Check out the partition problem also known as the easiest hard problem , that solve this for 2 sets. This problem is NP-Complete, and you should be able to find all the algorithms to solve it on the web
I know your problem is a bit different since you can chose the number of sets, but you can inspire yourself from solutions to the previous one.
For example :
You can transform this into a serie of linear programs, let k be the number of element in your set.
{a1 ... ak} is your set
For i = 2 to k:
try to solve the following program:
xjl = 1 if element j of set is in set number l (l <= i) and 0 otherwise
minimise max(Abs(sum(apxpn) -sum(apxpm)) for all m,n) // you minimise the max of the difference between 2 sets.
s.t
sum(xpn) on n = 1
(sum(xkn) on k)-(sum(xkm) on k) <= 1 for all m n // the number of element in 2 list are different at most of one element.
xpn in {0,1}
if you find a min less than one then stop
otherwise continue
end for
Hope my notations are clear.
The complexity of this program is exponential, and if you find a polynomial way to solve this you would probe P=NP so I don't think you can do better.
EDIT
I saw you comment ,I missunderstood the constraint on the size of the subsets (I thought it was the difference between 2 sets)
I don't I have time to update it I will do it when I have time.
sryy
EDIT 2
I edited the linear program and it should do what it's asked to do. I just added a constraint.
Hope this time the problem is fully understood, even though this solution might not be optimal
I'm no scientist, so I'd try two approaches:
After sorting items, then going from both "ends" and moving first and last to the actual set,then shift to next set, loop;
Then:
Checking the differences of sums of the sets, and shuffling items if it would help.
Coding the resulting sets appropriately and trying genetic algorithms.

Categories

Resources