I've been working on a recursive function in C which takes an int array and its size and does a selection sort where the array should now be ordered from least to greatest:
void selection_sort(int integers[], size_t size)
{
if (size == 0) {
return;
}
int largest = 0;
int largest_index = 0;
int temp;
for (int i = 0; i < size; ++i) {
if (integers[i] > integers[largest_index]) {
largest_index = i;
}
}
temp = integers[largest_index];
integers[largest_index] = integers[size - 1];
integers[size - 1] = temp;
selection_sort(integers, size - 1);
}
So if integers contains 17, 8, 14, 25, and 11, after calling selection_sort, it will now contain 8, 11, 14, 17, and 25. The code works as it should, however, I was trying to trace the logic out on paper and I don't think I'm thinking of it correctly because I'm not getting the numbers that I should. I was wondering if someone could thoroughly explain the logic of the function step-by-step. Any help would be appreciated!
Lets break out your code to understand its workflow.
your function takes two arguments one is array and other is size of the array
selection_sort(int integers[], size_t size)
Second part, if size of the array is zero then return
if (size == 0) {
return;
}
Third part, define variables
int largest = 0; //this variable is not used
int largest_index = 0; //this is index for largest array value
int temp; //temporary variable for swapping
Fourth part finding the largest value index in array
for (int i = 0; i < size; ++i) { //Iterate array from 0 to size
if (integers[i] > integers[largest_index]) { /*check if current index value is greater than largest value index */
largest_index = i; /* if value is greater than current index value add index in largest_index variable */
}
In first iteration for array [17, 8, 14, 25, 11] largest_index will be 3 (25).
Fifth part, Swap highest value and last element of the array
[17, 8, 14, 25, 11] will become [17, 8, 14, 11, 25]
temp = integers[largest_index]; //take 25 in temp
integers[largest_index] = integers[size - 1];
integers[size - 1] = temp; //swap 11 with 25
Last part, call the function recursively with array of reduced size by 1 element
Example in first iteration array will [17, 8, 14, 11] and second iteration [11, 8, 14], it will keep decreasing array size till it returns(size becomes zero)
selection_sort(integers, size - 1);
Related
I am stuck in this question for long time.
the question is - to move duplicates to the end of the array while preserving the order(time complexity must be O(nlogn)).
limitation:
order must be preserved.
can use only 1 helper array
the range of values in the array are not known and can be really large from n(which is the size fo the array).
values are positives.
time complexity - nlogn
example:
arr = {7, 3, 1, 2, 7, 9, 3, 2, 5, 9, 6, 2}, n = 12
result:
arr = {7, 3, 1, 2, 9, 5, 6, 2, 9, 2, 3, 7}
this what i did right now but i am stuck from thier:
copied original array to temp array
sort the temp array using quick sort
move duplicate to the end in temp array
i know that i need to do some comparison with the original array but this the part that i am stuck.
code:
int findDulpilcatesV2(int* arr, int n) {
int i, * tempArr, j = 0, countNonRepeatEl = 0, searchKeyIndex, elIndex;
tempArr = (int*)calloc(n, sizeof(int));
assert(tempArr);
// Saving original array in temp array
for (i = 0; i < n; i++)
{
tempArr[i] = arr[i];
}
// Sorting temp array
quickSort(tempArr, 0, n - 1);
// Move duplicates to the end
for (i = 0; i < n; i++)
{
if (tempArr[i] != tempArr[i+1])
{
swap(&tempArr[j], &tempArr[i]);
countNonRepeatEl++;
j++;
}
}
free(tempArr);
tempArr = NULL;
return countNonRepeatEl;
}
I came across a problem:
Given an array, find the max count of this array, where count for an element in the array is defined as the no. of elements from this array which can divide this element.
Example: max count from the array [2,2,2,5,6,8,9,9] is 4 as 6 or 8 can be divided by 2,2,2 and by themselves.
My approach is:
Sort the array.
Make a set from this array (in a way such that even this set is sorted in non-descending order).
Take another array in which the array indices are initialized to the no. of times an element appears in the original array. Example: in above example element '2' comes three times, hence index '2-1' in this new array will be initialized to 3, index '9-1' will be initialized to 2 as '9' comes 2 times in this array.
Using two loops I am checking the divisibility of largest (moving largest to smallest) element in the set with smallest (moving smallest to largest) element of the set.
Conditions
1 <= arr[i] <= 10000
1 <= i <= 10000
#include <stdio.h>
#include <stdlib.h>
#include<limits.h>
int cmp(const void *a, const void *b)
{
return (*(int*)a - *(int*)b);
}
void arr_2_set(int *arr, int arr_size,int *set, int *len)
{
int index = 0;
int set_len = 0;
int ele = INT_MIN;
qsort(arr,arr_size,sizeof(int),cmp);
while(index < arr_size)
{
if(ele != arr[index])
{
ele = arr[index];
set[set_len] = ele;
set_len++;
}
index++;
}
*len = set_len;
}
int main(void)
{
int arr[]={2,2,2,5,6,8,9,9}; //array is already sorted in this case
int size = sizeof(arr)/sizeof(arr[0]);
int set[size];
int index = 0;
int set_len = 0;
arr_2_set(arr, size, set, &set_len); //convert array to set - "set_len" is actual length of set
int rev = set_len-1; //this will point to the largest element of set and move towards smaller element
int a[100000] = {[0 ... 99999] = 0}; //new array for keeping the count
while(index<size)
{
a[arr[index] -1]++;
index++;
}
int half;
int max=INT_MIN;
printf("set len =%d\n\n",set_len);
for(;rev>=0;rev--)
{
index = 0;
half = set[rev]/2;
while(set[index] <= half)
{
if(set[rev]%set[index] == 0)
{
a[set[rev] -1] += a[set[index]-1]; //if there are 3 twos, then 3 should be added to count of 8
//printf("index =%d rev =%d set[index] =%d set[rev] =%d count = %d\n",index,rev,set[index],set[rev],a[set[rev] -1]);
}
if(max < a[set[rev]-1])
max = a[set[rev]-1];
index++;
}
}
printf("%d",max);
return 0;
}
Now my question is how can I speed up this program? I was able to pass 9/10 test cases - for the 10th test case (which was hidden), it was showing "Time Limit Exceeded".
For creating a set and finding the count - use a single while loop, when the size of array is big then using a single loop will matter a lot.
In the later half section where two nested loops are there - don't go from largest to smallest element. Go from smallest to largest element while checking which largest element with index lower than the current element can divide this element, add the count of that element to the current element's count (using set[i]/2 logic will still hold here). This way you'll avoid a lot of divisions. Example: if set is {2,3,4,8} in this case, lets say your current position is 8 then you go down till largest element smaller than or equal to 8 which can divide 8 and add it's count to current element's (8) count.
for the 10th test case (which was hidden), it was showing "Time Limit Exceeded".
That may suggest a more time efficient algorithm is expected.
The posted one, first sorts the array (using qsort) and then copies only the unique values into another array, set.
Given the constraints on the possible values, it may be cheaper to implement a counting sort algorithm.
The last part, which searches the maximum number of dividends, can then be implemented as a sieve, using an additional array.
#include <stdio.h>
enum constraints {
MAX_VALUE = 10000
};
int count_dividends(size_t n, int const *arr)
{
// The actual maximum value in the array will be used as a limit.
int maxv = 0;
int counts[MAX_VALUE + 1] = {0};
for (size_t i = 0; i < n; ++i)
{
if ( counts[arr[i]] == 0 && arr[i] > maxv )
{
maxv = arr[i];
}
++counts[arr[i]];
}
// Now, instead of searching for the dividends of an element, it
// adds the number of factors to each multiple.
// So, say there are two elements of value 3, it adds 2 to all
// the multiples of 3 in the total array.
int totals[MAX_VALUE + 1] = {0};
int count = 0;
// It starts from 2, it will add the numbers of 1's once, at the end.
for (int i = 2; i <= maxv; ++i)
{
// It always skips the values that weren't in the original array.
if ( counts[i] != 0 )
{
for ( int j = 2 * i; j <= maxv; j += i)
{
if ( counts[j] != 0 )
totals[j] += counts[i];
}
if ( counts[i] + totals[i] > count )
{
count = counts[i] + totals[i];
}
}
}
return count + counts[1];
}
int main(void)
{
{
int a[] = {2, 4, 5, 1, 1, 6, 14, 8, 2, 12, 1, 13, 10, 2, 8, 5, 9, 1};
size_t n = (sizeof a) / (sizeof *a);
// Expected: 10, because of 1 1 1 1 2 2 2 4 8 8
printf("%d\n", count_dividends(n, a));
}
{
int a[] = {2, 4, 5, 2, 7, 10, 9, 8, 2, 4, 4, 6, 5, 8, 4, 7, 6};
size_t n = (sizeof a) / (sizeof *a);
// Expected: 9, because of 2 2 2 4 4 4 4 8 8
printf("%d\n", count_dividends(n, a));
}
}
I have a simple function in C to get whether an array is sorted, but I seem to be getting different values every time. Sometimes I get 3 tests passed and sometimes I get 2 tests passed and am unsure what the problem is.
int is_sorted(int a[], int n)
{
for(int i = 0; i < n; i++)
{
if(a[i] > a[i + 1])
{
return 0;
}
}
return 1;
}
int main()
{
int a[] = {2, 4, 9, 8, 12};
int b[] = {-5, -2, 0, 8, 11, 15};
int aa[] = {2, 18, 12, 9, 1, 2, 8, 11, 16, 3};
int c[] = {4, 6, 8, 10};
npassed = 0;
if(!is_sorted(a, 5))
{
npassed++;
}
if(is_sorted(b, 6))
{
npassed++;
}
if(!is_sorted(aa, 10))
{
npassed++;
}
if(is_sorted(c, 5))
{
npassed++;
}
printf("number passed is_sorted : %i\n", npassed);
}
your function accepts two arguments:
a: the array
n: the arrays size
to check if it is sorted you iterate over all elements and see if its next element is bigger than itself. To do that, you count with i from zero (the lowest possible index) to n-1 (the highest possible index).
But you always check if i is greater than i+1. And what happens if you reach the last possible index for i? Then i+1 is equal to n and therefore outside the array. And what's outside your array is random data.
I have the following (incomplete) function:
/* Populates char* name with the named location of the ith (flat) element
* of an array with ndim dimensions where the length of each dimension
* is already stored in the int* dim.
*
* name: a pointer to where the name should be populated
* n: the base name of the array
* dim: an int[] containing the length of each dimension
* ndim: length of the dim array
* i: name of the iteration variable being used
**/
void populateName(char *name, const char *n, int *dim, int ndim, const char *i) {
strcpy(name, n);
char *loc = (char*)(name + strlen(n));
char *curr;
for (int k = 0; k < ndim; k++) {
...
sprintf(loc, "[%s]", curr);
loc += strlen(loc);
}
}
What should go in the "..." in the for loop? For example, calling populateName() with:
int dim[2] = {3, 4};
char name[1024];
populateName(name, "x", dim, 2, "i");
should result in something like:
name = "x[i / 3][i % 4]"
or some other valid name for accessing the ith location in an array defined as:
int x[3][4];
Context: I'm writing a C program which generates C programs which filter large amounts of data based on user-defined data types and rules written in an IDL.
Edit: A python function which returns a tuple containing the location / coordinates in the array might get me going in the right direction. In particular the following array should have each element correspond with it's flat position in the array (using pylab here):
In [14]: x
Out[14]:
array([[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 6, 7, 8],
[ 9, 10, 11]],
[[12, 13, 14],
[15, 16, 17]]])
In [15]: x.flat.copy()
Out[15]:
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17])
A good approach to solve a problem like this one is to try out a few examples. Consider the following picture that shows the memory layout for a 3D array x[2][3][5]:
How can we convert offset 14 to position x[0][2][4]? Well, first, we see that each x[i] holds 15 (3*5) blocks, so first of all we determine to which block does 14 belong to, by computing the integer division 14/15 = 0. So, offset 14 is somewhere inside x[0].
We can now apply the same method. x[i][j] holds 5 blocks, so offset 14 belongs to block number 14/5 = 2. In fact, the correct calculation is (14/5)%3, as we will see for offset 18. And finally, x[i][j][k] holds single blocks, so the last index is given by 14%5. Think of it like this: we are interpreting these blocks of memory as if they had different sizes at each step. First, we assume everything is divided in chunks of 15 elements. Then, we assume everything is divided in chunks of 5 elements.
You can play with this example and see that offset 18 maps to x[1][0][3] because 18/15 = 1; (18/5)%3 = 0, and 18%5 = 3.
It can be seen that the general case is that for dimension n, we interpret the memory layout as if it was organized in j blocks, where j is the product of every dimension greater than n, so we have to index position (i/j)%n.
Here's my implementation:
void populateName(char *name, const char *n, int *dim, int ndim, const char *i) {
strcpy(name, n);
char *loc = (char*)(name + strlen(n));
int j;
int *mul = malloc(sizeof(int)*ndim);
mul[ndim-1] = 1;
/* Compute cumulative multipliers array */
for (j = ndim-2; j >= 0; j--) {
mul[j] = mul[j+1] * dim[j+1];
}
for (j = 0; j < ndim; j++) {
loc += sprintf(loc, "[(%s/%d)%%%d]", i, mul[j], dim[j]);
}
free(mul);
}
As you can see, it uses a cumulative array of multipliers, where mul[i] holds the product of every dimension greater than i.
By the way, you don't need curr; since sprintf returns the number of characters printed, we just have to move loc that same amount. It gets a little more efficient than calling strlen repeatedly after sprintf.
I don't have much time to test this, but with the example I showed, I get this:
x[(i/15)%2][(i/5)%3][(i/1)%5]
Which looks correct. Here's an example program:
int main()
{
int dims[] = { 2, 3, 5, 7, 9 };
char name[1024];
populateName(name, "x", dims, 5, "i");
printf("%s\n", name);
return 0;
}
This prints:
x[(i/945)%2][(i/315)%3][(i/63)%5][(i/9)%7][(i/1)%9]
It gets trickier to read for arbitrary n dimensional arrays, but the principle is always the same.
Let's say I have an array a of length n and a second array indices, also of length n. indices contains some arbitrary permutation of the sequence [0, n). I want to to rearrange a such that it's in the order specified by indices. For example, using D syntax:
auto a = [8, 6, 7, 5, 3, 0, 9];
auto indices = [3, 6, 2, 4, 0, 1, 5];
reindexInPlace(a, indices);
assert(a == [5, 9, 7, 3, 8, 6, 0]);
Can this be done in both O(1) space and O(n) time, preferably without mutating indices?
With mutating indices :(. Without looks hard (see stable in-place mergesort).
a = [8, 6, 7, 5, 3, 0, 9]
indices = [3, 6, 2, 4, 0, 1, 5]
for i in xrange(len(a)):
x = a[i]
j = i
while True:
k = indices[j]
indices[j] = j
if k == i:
break
a[j] = a[k]
j = k
a[j] = x
print a
This is what I call a "permute from" algorithm. In C-like language it would look as follows
for (i_dst_first = 0; i_dst_first < n; ++i_dst_first)
{
/* Check if this element needs to be permuted */
i_src = indices[i_dst_first];
assert(i_src < n);
if (i_src == i_dst_first)
/* This element is already in place */
continue;
i_dst = i_dst_first;
pending = a[i_dst];
/* Follow the permutation cycle */
do
{
a[i_dst] = a[i_src];
indices[i_dst] = i_dst;
i_dst = i_src;
i_src = indices[i_src];
assert(i_src != i_dst);
} while (i_src != i_dst_first);
a[i_dst] = pending;
indices[i_dst] = i_dst;
}
Note though that this algorithm destroys the index array. I call it "permute from" since the index[i] value specifies from where to take the i-th element of the resultant sequence.
Note also, that the number of "element move" operations required for in-place permutation of a sequence is equal to number of misplaced elements + number of cycles in the permutation. This algorithm achieves this limit, so in terms of the number of moves no better algorithm is possible.
Potential problem with this algorithm is that it is based on "juggling" approach, making its cache behavior far from optimal. So, while this algorithm is the best one in theory, it could lose to some more "practical" algorithms in real life.
One can also implement a "permute to" algorithm, where index[i] value specifies where to relocate the original i-th element.
If a is an array of integers, then an O(n)-time, O(1)-space algorithm is possible that keeps the order of permutation indices. In this case we can permute a into indexes and use a as a temporary storage of the inverse permutation. After the permutation is performed, the arrays a and indices are swapped, and indices is inverted in situ using e.g. algorithm J from TAoCP. The following is a working Java program:
int [] a = {8, 6, 7, 5, 3, 0, 9};
int [] indices = {3, 6, 2, 4, 0, 1, 5};
int n = indices.length;
int i, j, m;
// permute a and store in indices
// store inverse permutation in a
for (j = 0; j < n; ++j) {
i = indices[j]; indices[j] = a[i]; a[i] = j;
}
// swap a and indices
for (j = 0; j < n; ++j) {
i = indices[j]; indices[j] = a[j]; a[j] = i;
}
// inverse indices permutation to get the original
for (i = 0; i < n; ++i) {indices[i] = -indices[i] - 1;}
for (m = n - 1; m >= 0; --m) {
// for (i = m, j = indices[m]; j >= 0; i = j, j = indices[j]) ;
i = m; j = indices[m];
while (j >= 0) {i = j; j = indices[j];}
indices[i] = indices[-j - 1];
indices[-j - 1] = m;
}
This answers the question when indices array is mutable.
Here is a solution when it is not mutable.
void mutate(int[] input, int[] indices) {
int srcInd;
for (int tarInd = 0; tarInd < input.length; tarInd++) {
srcInd = indices[tarInd];
while(srcInd < tarInd) {
// when src is behind, it will have it's final value already and the original
// value would have been swapped with src's src pos. Keep searching for the
// original value until it is somewhere ahead of tarInd.
srcInd = indices[srcInd];
}
swap(input, srcInd, tarInd);
}
}
I think the classic way to deal with this problem is to work round the cycles, and to do this you need a marker bit per data item from somewhere. Here I pinched the top bit of the index array, which you could restore - of course this assumes that you don't have -ve array indexes or are using all bits of an unsigned number as an index. One reference for this is Knuth Volume 1 section 1.3.3 answer to question 12, which deals with the special case of transposing a matrix. Knuth gives references to slower in-place methods. The paper "Permuting in Place" by Fich, Munro, and Poblete claims nlogn time and O(1) space in the worst case.
import java.util.Arrays;
public class ApplyPerm
{
public static void reindexInPlace(int[] rearrangeThis, int[] indices)
{
final int TOP_BIT = 0x80000000;
for (int pos = 0; pos < rearrangeThis.length; pos++)
{
if ((indices[pos] & TOP_BIT) != 0)
{ // already dealt with this
continue;
}
if (indices[pos] == pos)
{ // already in place
continue;
}
// Now shift an entire cycle along
int firstValue = rearrangeThis[pos];
int currentLocation = pos;
for (;;)
{
// pick up untouched value from here
int replaceBy = indices[currentLocation];
// mark as dealt with for the next time we see it
indices[currentLocation] |= TOP_BIT;
if (replaceBy == pos)
{ // have worked our way round
rearrangeThis[currentLocation] = firstValue;
break;
}
if ((replaceBy & TOP_BIT) != 0)
{
throw new IllegalArgumentException("Duff permutation");
}
// Move value up
rearrangeThis[currentLocation] = rearrangeThis[replaceBy];
// and fill in source of value you have just moved over
currentLocation = replaceBy;
}
}
}
public static void main(String[] s)
{
int[] a = new int[] {8, 6, 7, 5, 3, 0, 9};
int[] indices = new int[] {3, 6, 2, 4, 0, 1, 5};
reindexInPlace(a, indices);
System.out.println("Result is " + Arrays.toString(a));
}
}
You can do this by hiding the values in the real array. By this way you can do this in both O(1) space and O(n) time.
Basically, you traverse through your indices array first, store the value of the indice array in the correct position. Now this can be done in the algorithm of your choice. For me, I would simply store the number's trailing bits from the Most Significant bit position. Do this in one traversal. Now the base array would be messed up.
During the second traversal store all the upper half bits to lower half.
The obvious disadvantage of this technique is that the stored integer
value can hold as much as half the bits. Meaning if you are dealing
with 4 byte integer, the values can only be of 2 bytes. However instead of using up half the array as show in the code below, it can be enhanced by using a better algorithm where you hide the value in the index array. Here you will require the max bits reserved in worst case would be the length of the array rather than constant 16 in the previous case. It will perform worst than the former when the length exceeds 2 power 16.
import java.util.Arrays;
class MyClass {
public static void main(String[] args) {
MyClass myClass = new MyClass();
int[] orig_array = {8, 6, 7, 5, 3, 0, 9};
int[] indices = {3, 6, 2, 4, 0, 1, 5};
myClass.meth(orig_array, indices);
}
public void meth(int[] orig_array, int[] indices){
for(int i=0;i<orig_array.length;i++)
orig_array[i] += orig_array[indices[i]] + orig_array[indices[i]] << 15 ;
for(int i=0;i<orig_array.length;i++)
orig_array[i] = orig_array[i] >> 16;
System.out.print(Arrays.toString(orig_array));
}
}
Here's a C++ version (it modifies the indices):
#include <algorithm>
#include <iterator>
template<class It, class ItIndices>
void permutate_from(
It const begin,
typename std::iterator_traits<It>::difference_type n,
ItIndices indices)
{
using std::swap;
using std::iter_swap;
for (typename std::iterator_traits<It>::difference_type i = 0; i != n; ++i)
{
for (typename std::iterator_traits<ItIndices>::value_type j = i; ; )
{
swap(j, indices[j]);
if (j == i) { break; }
iter_swap(begin + j, begin + indices[j]);
}
}
}
Example:
int main()
{
int items[] = { 2, 0, 1, 3 };
int indices[] = { 1, 2, 0, 3 };
permutate_from(items, 4, indices);
// Now items[] == { 0, 1, 2, 3 }
}
JavaScript version
var input = [1,2,3,4,5],
specArr = [0,2,1,4,3];
function mutate(input, specArr) {
var visited = [0,2]
for(var i=0; i<specArr.length; i++) {
var tmp;
//keep track of array items we've already looped through (wouldn't want to mutate twice :D)
visited.push(specArr[i]);
// if index hasn't changed we do nothing to input arr
if (visited.indexOf(1) < 0) {
// if it has changed temporarily store the value
tmp = input[i];
//swap input array item with spec item
input[i] = input[specArr[i]];
//swap specced array item with input item above
input[specArr[i]] = tmp;
}
}
}
mutate(input, specArr);