Big(O) notation - which one is correct - algorithm

I am trying to learn Big(O) notation. While searching for some articles online, I came across two different articles , A and B
Strictly speaking in terms of loops - it seems that they almost have the same kind of flow.
For example
[A]'s code is as follows (its done in JS)
function allPairs(arr) {
var pairs = [];
for (var i = 0; i < arr.length; i++) {
for (var j = i + 1; j < arr.length; j++) {
pairs.push([arr[i], arr[j]]);
}
}
return pairs;
}
[B]'s code is as follows (its done in C)- entire code is here
for(int i = 0; i < n-1 ; i++) {
char min = A[i]; // minimal element seen so far
int min_pos = i; // memorize its position
// search for min starting from position i+1
for(int j = i + 1; j < n; j++)
if(A[j] < min) {
min = A[j];
min_pos = j;
}
// swap elements at positions i and min_pos
A[min_pos] = A[i];
A[i] = min;
}
The article on site A mentions that time complexity is O(n^2) while the article on site B mentions that its O(1/2·n2).
Which one is right?
Thanks

Assuming that O(1/2·n2) means O(1/2·n^2), the two time complexity are equal. Remember that Big(O) notation does not care about constants, so both algorithms are O(n^2).

You didn't read carefully. Article B says that the algorithm performs about N²/2 comparisons and goes on to explain that this is O(N²).

Related

First missing Integer approach's time complexity

I want to understand the time complexity of my below algorithm, which is an acceptable answer for the famous first missing integer problem:
public int firstMissingPositive(int[] A) {
int l = A.length;
int i = 0;
while (i < l) {
int j = A[i];
while (j > 0 && j <= l) {
int k = A[j - 1];
A[j - 1] = Integer.MAX_VALUE;
j = k;
}
i++;
}
for (i = 0; i < l; i++) {
if (A[i] != Integer.MAX_VALUE)
break;
}
return i + 1;
}
Observations and findings:
Looking at the loop structure I thought that the complexity should be more than n as I may visit every element more than twice in some cases. But to my surprise, the solution got accepted. I am not able to understand the complexity.
You are probably looking at the nested loops and thinking O(N2), but it's not that simple.
Every iteration of the inner loop changes an item in A to Integer.MAX_VALUE, and there are only N items, so there cannot be more than N iterations of the inner loop in total.
The total time is therefore O(N).

BIg O help for beginner

Ok, I am trying to understand the concept of Big O. I have a function I am suppose to find the Big O and I am not quite "getting it" this is an example in the book of one that is like my homework.. I know the answer is O(nk) but can someone please break this down in simplistic terms so I might better understand.
int selectkth(int a[], int k, int n)
{
int i, j, mini, tmp;
for (i=0; i < k; i++)
{
mini = i;
for (j = i+1; j < n; j++)
{
if (a[j] < a[mini])
mini = k;
tmp = a[i];
a[i] = a[mini];
a[mini] = tmp;
}
}
return a[k-1];
}
When calculating the bigO try to think of the worst time complexity, and pay attention to loops. Here we have two loops:
// Below line is run k times
for (i=0; i < k; i++)
// Worst case scenario, loop below will run n times.
for (j = i+1; j < n; j++)
bigO would be these two values multiplied togehter = k*n
Also check out this post: What is a plain English explanation of "Big O" notation?

Big Oh Logarithmic(ish) complexity calculation

So I've been trying to get a handle on Big Oh calculations. I feel I have the basics down but am stumped on what seems a really easy calculation. So if the calculation below has a big oh of O(n log n) (I really hope I've at least got that right) what does changing the order of the loops do to the complexity? Thanks so much in advance for your time.
int ONLogN(int N) //O(n log n)
{
int iIterations = 0;
for (int i = 0; i < N; ++i)
{
++iIterations;
for (int j = 1; j < N + 1; j *= 2)
++iIterations;
}
return iIterations;
}
int WhatBigOhIsThis(int N) //???
{
int iIterations = 0;
for (int j = 1; j < N + 1; j *= 2)
{
++iIterations;
for (int i = 0; i < N; ++i)
++iIterations;
}
return iIterations;
}
The index variables on the two loops are independent, hence the resulting complexity is necessarily the same.
You're still looping for the same number of iterations. Changing the order of the loops would have no effect on complexity

Max sum in an array with constraints

I have this problem , where given an array of positive numbers i have to find the maximum sum of elements such that no two adjacent elements are picked. The maximum has to be less than a certain given K. I tried thinking on the lines of the similar problem without the k , but i have failed so far.I have the following dp-ish soln for the latter problem
int sum1,sum2 = 0;
int sum = sum1 = a[0];
for(int i=1; i<n; i++)
{
sum = max(sum2 + a[i], sum1);
sum2 = sum1;
sum1 = sum;
}
Could someone give me tips on how to proceed with my present problem??
The best I can think of off the top of my head is an O(n*K) dp:
int sums[n][K+1] = {{0}};
int i, j;
for(j = a[0]; j <= K; ++j) {
sums[0][j] = a[0];
}
if (a[1] > a[0]) {
for(j = a[0]; j < a[1]; ++j) {
sums[1][j] = a[0];
}
for(j = a[1]; j <= K; ++j) {
sums[1][j] = a[1];
}
} else {
for(j = a[1]; j < a[0]; ++j) {
sums[1][j] = a[1];
}
for(j = a[0]; j <= K; ++j) {
sums[1][j] = a[0];
}
}
for(i = 2; i < n; ++i) {
for(j = 0; j <= K && j < a[i]; ++j) {
sums[i][j] = max(sums[i-1][j],sums[i-2][j]);
}
for(j = a[i]; j <= K; ++j) {
sums[i][j] = max(sums[i-1][j],a[i] + sums[i-2][j-a[i]]);
}
}
sums[i][j] contains the maximal sum of non-adjacent elements of a[0..i] not exceeding j. The solution is then sums[n-1][K] at the end.
Make a copy (A2) of the original array (A1).
Find largest value in array (A2).
Extract all values before the it's preceeding neighbour and the values after it's next neighbour into a new array (A3).
Find largest value in the new array (A3).
Check if sum is larger that k. If sum passes the check you are done.
If not you will need to go back to the copied array (A2), remove the second larges value (found in step 3) and start over with step 3.
Once there are no combinations of numbers that can be used with the largest number (i.e. number found in step 1 + any other number in array is larger than k) you remove it from the original array (A1) and start over with step 0.
If for some reason there are no valid combinations (e.g. array is only three numbers or no combination of numbers are lower than k) then throw an exception or you return null if that seems more appropriate.
First idea: Brute force
Iterate all legal combination of indexes and build the sum on the fly.
Stop with one sequence when you get over K.
keep the sequence until you find a larger one, that is still smaller then K
Second idea: maybe one can force this into a divide and conquer thing ...
Here is a solution to the problem without the "k" constraint which you set out to do as the first step: https://stackoverflow.com/a/13022021/1110808
The above solution can in my view be easily extended to have the k constraint by simply amending the if condition in the following for loop to include the constraint: possibleMax < k
// Subproblem solutions, DP
for (int i = start; i <= end; i++) {
int possibleMaxSub1 = maxSum(a, i + 2, end);
int possibleMaxSub2 = maxSum(a, start, i - 2);
int possibleMax = possibleMaxSub1 + possibleMaxSub2 + a[i];
/*
if (possibleMax > maxSum) {
maxSum = possibleMax;
}
*/
if (possibleMax > maxSum && possibleMax < k) {
maxSum = possibleMax;
}
}
As posted in the original link, this approach can be improved by adding memorization so that solutions to repeating sub problems are not recomputed. Or can be improved by using a bottom up dynamic programming approach (current approach is a recursive top down approach)
You can refer to a bottom up approach here: https://stackoverflow.com/a/4487594/1110808

Are these 2 knapsack algorithms the same? (Do they always output the same thing)

In my code, assuming C is the capacity, N is the amount of items, w[j] is the weight of item j, and v[j] is the value of item j, does it do the same thing as the 0-1 knapsack algorithm? I've been trying my code on some data sets, and it seems to be the case. The reason I'm wondering this is because the 0-1 knapsack algorithm we've been taught is 2-dimensional, whereas this is 1-dimensional:
for (int j = 0; j < N; j++) {
if (C-w[j] < 0) continue;
for (int i = C-w[j]; i >= 0; --i) { //loop backwards to prevent double counting
dp[i + w[j]] = max(dp[i + w[j]], dp[i] + v[j]); //looping fwd is for the unbounded problem
}
}
printf( "max value without double counting (loop backwards) %d\n", dp[C]);
Here is my implementation of the 0-1 knapsack algorithm: (with the same variables)
for (int i = 0; i < N; i++) {
for (int j = 0; j <= C; j++) {
if (j - w[i] < 0) dp2[i][j] = i==0?0:dp2[i-1][j];
else dp2[i][j] = max(i==0?0:dp2[i-1][j], dp2[i-1][j-w[i]] + v[i]);
}
}
printf("0-1 knapsack: %d\n", dp2[N-1][C]);
Yes, your algorithm gets you the same result. This enhancement to the classic 0-1 Knapsack is reasonably popular: Wikipedia explains it as follows:
Additionally, if we use only a 1-dimensional array m[w] to store the current optimal values and pass over this array i + 1 times, rewriting from m[W] to m[1] every time, we get the same result for only O(W) space.
Note that they specifically mention your backward loop.

Resources