For a program that I am writing for fun (one that finds the Highest Common Factor and the Lowest Common Multiple for you); I've come across some difficulty.
I have two arrays that contain 14 numbers. To find the Lowest Common Multiple of all the numbers, I need to compare every element in each array. So far I've got this test:
for(int i = 0; i < C_I_14; i++)
{
for(int j = 0; j < C_I_14; j++)
{
if(array[i] == arr[j])
{
tesst[i] = array[i];
}
}
}
(where C_I_14 = 14)
The thing is, there are endless amounts of things that could go wrong with:
tesst[i] = array[i]
So, can anyone help me sort out my little algorithm?
Sort each of your input arrays, then get the intersection using std::set_intersection.
If the ordering matters, you will find
std::mismatch
std::lexicographical_compare
quite useful
Otherwise, look at
std::sort (!! important) followed by
std::set_intersection
Related
What is the best way to sort an section-wise sorted array as depicted in the second image?
The problem is performing a quick-sort using Message Passing Interface. The solution is performing quick-sort on array sections obtained by using MPI_Scatter() then joining the sorted
pieces using MPI_Gather().
Problem is that the array as a whole is unsorted but sections of it are.
Merging the sub-sections similarly to this solution seems like the best way of sorting the array, but considering that the sub-arrays are already within a single array other sorting algorithms may prove better.
The inputs for a sort function would be the array, it's length and the number of equally sorted sub-sections.
A signature would look something like int* sort(int* array, int length, int sections);
The sections parameter can have any value between 1 and 25. The length parameter value is greater than 0, a multiple of sections and smaller than 2^32.
This is what I am currently using:
int* merge(int* input, int length, int sections)
{
int* sub_sections_indices = new int[sections];
int* result = new int[length];
int section_size = length / sections;
for (int i = 0; i < sections; i++) //initialisation
{
sub_sections_indices[i] = 0;
}
int min, min_index, current_index;
for (int i = 0; i < length; i++) //merging
{
min_index = 0;
min = INT_MAX;
for (int j = 0; j < sections; j++)
{
if (sub_sections_indices[j] < section_size)
{
current_index = j * section_size + sub_sections_indices[j];
if (input[current_index] < min)
{
min = input[current_index];
min_index = j;
}
}
}
sub_sections_indices[min_index]++;
result[i] = min;
}
return result;
}
Optimizing for performance
I think this answer that maintains a min-heap of the smallest item of each sub-array is the best way to handle arbitrary input. However, for small values of k, think somewhere between 10 and 100, it might be faster to implement the more naive solutions given in the question you linked to; while maintaining the min-heap is only O(log n) for each step, it might have a higher overhead for small values of n than the simple linear scan from the naive solutions.
All these solutions create a copy of the input, and they maintain O(k) state.
Optimizing for space
The only way to save space I see is to sort in-place. This will be a problem for the algorithms mentioned above. An in-place algorithm will have two swap elements, but any swaps will likely destroy the property that each sub-array is sorted, unless the larger of the swapped pair is re-sorted into the sub-array it is being swapped to, which will result in an O(n²) algorithm. So if you really do need to conserve memory, I think a regular in-place sorting algorithm would have to be used, which defeats your purpose.
So I need to sort an vector, and instead of doing things by hand i am using insert and erase.
so far my code is
for (int x = 0; x < arr.size(); x++) {
for (int y = x; y < arr.size(); y++)
{
if ( arr[y] < arr[x])
{
arr.insert(arr.begin()+x,arr[y]);
arr.erase(arr.begin()+y+1);
}
}
}
and yet when it runs I get time outs in my test cases and works for like 3 of them (test cases being 245+ integers of long numbers). I have to use vectors and have to use insertion sort as part of the design (finds minimum swaps to sort but thats cut from here), which i know has bad runtime.
What am I doing wrong here for the compiler to act like this?
Every time when you call arr.insert or arr.erase you get O(n) complexity. Try to use std::swap (arr[x], arr[y]) instead.
Given that the input will be N numbers from 0 to N (with duplicates) how I can optimize the code bellow for both small and big arrays:
void countingsort(int* input, int array_size)
{
int max_element = array_size;//because no number will be > N
int *CountArr = new int[max_element+1]();
for (int i = 0; i < array_size; i++)
CountArr[input[i]]++;
for (int j = 0, outputindex = 0; j <= max_element; j++)
while (CountArr[j]--)
input[outputindex++] = j;
delete []CountArr;
}
Having a stable sort is not a requirement.
edit: In case it's not clear, I am talking about optimizing the algorithm.
IMHO there's nothing wrong here. I highly recommend this approach when max_element is small, numbers sorted are non sparse (i.e. consecutive and no gaps) and greater than or equal to zero.
A small tweak, I'd replace new / delete and just declare a finite array using heap, e.g. 256 for max_element.
int CountArr[256] = { }; // Declare and initialize with zeroes
As you bend these rules, i.e. sparse, negative numbers you'd be struggling with this approach. You will need to find an optimal hashing function to remap the numbers to your efficient array. The more complex the hashing becomes the benefit between this over well established sorting algorithms diminishes.
In terms of complexity this cannot be beaten. It's O(N) and beats standard O(NlogN) sorting by exploiting the extra knowledge that 0<x<N. You cannot go below O(N) because you need at least to swipe through the input array once.
Given a big array which has numbers in range from 1 to 100. What's the best approach to sort it out?
The interviewer was emphasizing on the word range ie max number which is present in the array is 100.
try this:
long result[100] = {0};
for (iterator it = vec.begin(); it != vec.end(); ++it)
{
result[*it - 1]++;
}
So, you will move linear over your vector and count all numbers there exist. As result you will receive how many 1 you had, how many 2 you had and etc, i.e. it will be as sorted.
UPD: as KillianDS wrote, I mean counting sort. It's the fast one.
Well since the answer was basically given, example code. There's no need to copy data from the original array; it can be generated from the data in the histogram, called a variant algorithm in the wiki counting sort variant section:
std::vector <size_t> hist(101, 0); // using index 1 to 100 inclusive
size_t i, j, n;
for (i = 0; i < vec.size(); i++)
hist[vec[i]]++;
i = 0;
for(j = 1; j <= 100; j++)
for(n = hist[j]; n; n--)
vec[i++] = j;
May be they wanted to hear about radix sort.
It seems counting sort is the most suitable algorithm for this problem, it's O(n), stable, and easy to implement. http://en.wikipedia.org/wiki/Counting_sort
In MATLAB inorder to access the odd or even rows and columns of a matrix we use
A = M(1:2:end,1:2:end);
Is there an equivalent for this in C++? or How do i do this in C++.
Basically what i want to do is in matlab i have
A(1:2:end,1:2:end) = B(1:2:end,:);
A(2:2:end,2:2:end) = B(2:2:end,:);
I want to implement the same in C++
This is available only in a fairly obscure class, std::valarray. You need a std::gslice (Generalized slice) with stride {2,2} to access the std::valarray.
In C++ the for loop is constructed as follows
for (initial state; condition for termination; increment)
So if you are looking for the odd elements, you can:
for (int i = 0; i < size; i += 2),
whereas if you are looking for the even elements:
for (int i = 1; i < size; i += 2).
Where size depends if you are looping through the rows or columns. Take into account that because C++ arrays start at index 0, your odd elements will correspond to even indexes and your even elements will correspond to odd indexes.
Now, the answer: If you want to get the elements of a matrix, in C++ you must loop through the matrix with a for loop. You can modify the elements you access by modifying the increment property of the for loop.
for(int i= 0; i < rows/2; i++)
for(int j= 0; j < columns/2; j++)
A[i][j] = M[i*2][j*2];