Insertion comparison #'s seem too big - c++

I am confused if these comparison numbers are supposed to be this large in value for a vector with 100 random two-digit numbers. Full program --> safe link: https://ideone.com/oybDbD The program output is at the bottom page of the link. Appreciate input.
int insertionSort (vector<int> &v) {
int j, temp, counter = 0;
for (int i = 1; i < v.size(); i++) {
j = i;
while (++counter && j > 0 && v[j] < v[j-1]){
temp = v[j];
v[j] = v[j-1];
v[j-1] = temp;
j--;
}
}
return counter;
}

The average case performance of insertion sort is O(N^2) (see the wiki entry). For your vector of 100 elements, the expected number of comparisons is therefore O(10000). Coming out with 2656 or, in your second run, 4995, comparisons is therefore lower than you might otherwise expect.

Related

Can I create a for loop with two variables and still have time complexity of O(n)?

Say I have a for loop as:
for(int i=0,j=i+1;i<n-1,j<n;j++)
{
//some code
if(condition)
{
i++;
j=i;
}
}
What will be the time complexity and why?
Edited:
void printAllAPTriplets(int arr[], int n)
{
for (int i = 1; i < n - 1; i++)
{
// Search other two elements of
// AP with arr[i] as middle.
for (int j = i - 1, k = i + 1; j >= 0 && k < n;)
{
// if a triplet is found
if (arr[j] + arr[k] == 2 * arr[i])
{
cout << arr[j] << " " << arr[i]
<< " " << arr[k] << endl;
// Since elements are distinct,
// arr[k] and arr[j] cannot form
// any more triplets with arr[i]
k++;
j--;
}
// If middle element is more move to
// higher side, else move lower side.
else if (arr[j] + arr[k] < 2 * arr[i])
k++;
else
j--;
}
}
}
What would be the time complexity of this particular function and why?? #walnut #DeducibleSteak #Acorn .This is the code for "Printing all triplets in sorted array that form AP"
O(n^2) is when you iterate through all the possible values of one variable each time you iterate through the second one. As such:
for(int i=0; i < n; i++){
for (int j = 0; j < m; j++{
//Do some action
}
}
In your example, even though you're using two vars, but it's still a O(n).
Assuming that increasing i by one takes one second, then assigning the new i to j takes one second too, then the complexity is O(2n). Since constant numbers are insignificant when speaking about complexities, then the complexity of your code is still O(n)
The loop you have written does not make sense, because you are using the comma operator and discarding one of the conditions, so it is equivalent to j < n.
Even if the condition gets triggered many times (but a constant number w.r.t. n, i.e. not becoming larger as n grows), then you can easily show you will do <= k*n iterations, which means O(n) iterations.
If that is not true, but the condition is at least side-effect free, then you can only bound it by O(n^2), e.g. as #walnut suggests with j == n - 1 (like in a triangle matrix).
If you allow for side-effects in the condition (e.g. j = 0, with an equals sign), then it can be an infinite loop, so there is no possible bound.

Time complexity of an algorithm that finds prime numbers given a vector

I am trying to find the time complexity of the following algorithm that finds the prime numbers given the vector. Specifically I am not sure about the last for loop with another loop nested in it. I think it's O(sqrt(n)/2), and then the loop inside it is O(n)?
void PrimeFind (std::vector<bool> &vec)
{
int vsize = vec.size();
size_t sqvsize = ceil(sqrt(vsize));
std::fill(vec.begin(), vec.end(), true);
vec[0] = false;
vec[1] = false;
for (int i = 4; i < vsize; i += 2)
{
vec[i] = false;
}
for (int i = 3; i < sqrtvsize; i += 2)
{
if (vec[i])
{
for (int j = i * i; j < vsize; j += i)
{
vec[j] = false;
}
}
}
}
Work performed by basic sieve of Erastophene is almost entirely culling composite numbers and it takes
In your case you start from i * i which effectively reduces number of culling operation by i - 1 for every prime. So, we need to count number of all primes till n (vsize). This is
So, asymptotically we have
Where the last addend is the number of primes less than n.

Find indices i<j in an array of size n so that the sum of values at those indices is equal to i + j

My solution :
#include <bits/stdc++.h>
int main() {
int n;//Size of array
std::cin>>n;
std::vector<long long>vec_int;
int temp = n;
while(n--){
long long k ;
std::cin>>k;
vec_int.push_back(k);
}
n = temp;
int num = 0;
for(int i = 0 ; i < n-1 ; i++){
for(int j = i+1; j<n; j++){
if(i<j && i+j == vec_int[i]+vec_int[j])
num++;
}
}
std::cout<<num;
return 0;
}
I am scanning the array which takes about O(n^2) time. On very large arrays the time limit for the question exceeds the 2s duration. I tried sorting the array but didn't get too far. How can I speed this up? Is it possible to do this in O(n) time complexity.
Consider redefinition of your problem. The expression:
i+j == vec_int[i]+vec_int[j]
is algebraically equivalent to:
vec_int[i] - i == -(vec_int[j] - j)
So define:
a[i] = vec_int[i] - i
And now the question is to count how many times a[i] == -a[j].
This can be tested in O(n). Use unordered_map m to count how many times each negative value is present in a. Then for each positive value a[i] will be paired with m[-a[i]] negative values. Also count number of zeroes in a and compute number of pairs between those.

c++ array can't get the right array

I have Array A[9]= {1,2,3,4,5,6,7,8,9} and I need to delete the numbers which are not dividing by 2. The code I tried to do:
int main()
{
int n;
ifstream fd(Cdf);
fd>>n; // read how many numbers are in the file.
int A[n];
for(int i = 0; i < n; i++)
{
fd >> A[i]; //read the numbers from file
}
for(int i = 0; i < n; i ++) // moving the numbers.
{
if(A[i] % 2 !=0)
{
for(int j = i; j < n; j++)
{
A[i] = A[i+1];
}
}
}
fd.close();
return 0;
}
But I get numbers like 224466888. what I need to do to get 2,4,6,8?
I need to delete numbers in the same array.
First you should use std::vector for dynamic size arrays.
Second, for removing numbers that are even in a vector, you can do :
std::vector<int> inf = {12,0,5,6,8};
auto func = [](int i){return i % 2 != 0;};
inf.erase(std::remove_if(inf.begin(),inf.end(),func), inf.end());
EDIT :
Ok, so you can still do this without std::vectors, but it will be uglier :
#include <algorithm>
int res[] = {2,5,9,8,6,7};
int size = 6;
auto func = [](int i){return i % 2 != 0;};
int new_size = std::remove_if(res,res + size, func) - res;
All the data you want is in [0, new_size[ range, the other part of your array is now garbage.
Your removal loop is indexing with the wrong variable:
for(int j = i; j < n; j++)
{
A[i] = A[i+1];
}
You're using i, which doesn't change in the loop.
Change it to j. You also need to subtract one from the upper limit, as you'd step outside of the array otherwise when accessing A[j + 1].
for(int j = i; j < n - 1; j++)
{
A[j] = A[j + 1];
}
An array can't be used for your purpose. It is allocated on stack and its size can't be changed dynamically (you can't change the size of an array in general, not only when it is allocated on stack).
You could allocate a second array and keep reallocating it with realloc everytime you add a new element but that's not the good way to do it. You are working with C++ so just use a std::vector<int> and your problems will be solved:
std::vector<int> evenArray;
evenArray.reserve(sizeof(A)/sizeof(A[0])/2);
if (number is even) {
evenArray.pushBack(number);
}
Mind that vector stores elements contiguously so this is legal:
int *evenA = &evenArray[0];
For your inner for loop you should be referencing j, not i.
for(int j = i; j < n - 1; j++)
{
A[j] = A[j+1];
}
Otherwise, what's the point of creating j?
Of course, this also means if you read the whole array back you will display all the characters that were shifted (which will just be equal to the last number). So, you should probably keep track of the new length of the array and just iterate to that instead of the end of the array.
EDIT:
In the inner for loop you need to loop to n - 1 otherwise when you have A[j + 1] it will go off the end of the array when you to change it, which may or may not give you a runtime error.

Return the count of negative numbers in the optimal way

A variation of "Searching in a Matrix that is sorted rowwise and columnwise"
Given a 2D Matrix that is sorted rowwise and columnwise. You have to return the count of negative numbers in most optimal way.
I could think of this solution
initialise rowindex=0
if rowindex>0 rowindex++
else apply binary search
And implemented in with this code for 5X5 matrix
#include<iostream>
#include<cstdio>
using namespace std;
int arr[5][5];
int func(int row)
{
int hi=4;
int lo=0;
int mid=(lo+hi)/2;
while(hi>=lo)
{
mid=(lo+hi)/2;
.
if(mid==4)
{
return 5;
}
if(arr[row][mid]<0 && arr[row][mid+1]<0)
{
lo=mid+1;
}
else if(arr[row][mid]>0 && arr[row][mid+1]>0)
{
hi=mid-1;
}
else if(arr[row][mid]<0 && arr[row][mid+1]>0)
{
return mid+1;
}
}
}
int main()
{
int ri,ci,sum;
ri=0; //rowindex
ci=0; //columnindex
sum=0;
for(int i=0; i<5; i++)
{
for(int j=0; j<5; j++)
{
cin>>arr[i][j];
}
}
while(ri<5)
{
if(arr[ri][ci]>=0)
{
ri++;
}
else if(arr[ri][ci]<0)
{
int p=func(ri);
sum+=p;
ri++;
}
}
printf("%d\n",sum);
}
I ran the code here http://ideone.com/PIlNd2
runtime O(xlogy) for a matrix of x rows and y columns
Correct me if i am wrong in time complexity or implementation of code
Does anyone have any better idea than this to improve Run-time complexity?
O(m+n) algorithm, where m and n are the dimensions of the array, working by sliding down the top of the negative portion, finding the last negative number in each row. This is most likely what Prashant was talking about in the comments:
int negativeCount(int m, int n, int **array) {
// array is a pointer to m pointers to n ints each.
int count = 0;
int j = n-1;
for (int i = 0, i < m; i++) {
// Find the last negative number in row i, starting from the index of
// the last negative number in row i-1 (or from n-1 when i==0).
while (j >= 0 && array[i][j] >= 0) {
j--;
}
if (j < 0) {
return count;
}
count += j+1;
}
return count;
}
We can't do better than worst-case O(m+n), but if you're expecting far fewer than m+n negative numbers, you may be able to get a better usual-case time.
Suppose you have an n by n array, where array[i][j] < 0 iff i < n-j. In that case, the only way the algorithm can tell that array[i][n-1-i] < 0 for any i is by looking at that cell. Thus, the algorithm has to look at at least n cells.
You are conducting a binary search. Whereby you divide n by 2 to find the midpoint then continue to divide, before returning a value. That looks like a binary search, even though you are dividing columns for each row. Therefore, you are performing O(log n). Or something like O(x log n/y).