I'm trying to solve a problem which is something like this:
I'm given n numbers (1<=n<=10^5).I have to write the sum of all numbers on its left which are smaller than the current number and repeat the process for all n numbers.Then I have to find the sum of all previously obtained sum's.(Each number N,0<=N<=10^6).
For example,
1 5 3 6 4
less1 less5 less3 less6 less4
(0) + (1) + (1)+(1+5+3)+(1+3)
0 + 1 + 1 + 9 + 4
= 15
A trivial solution for this problem will be to run two loops and for each of the given number find sum of all the numbers less than that number and finally give the sum of those sum's as output.The time complexity is O(n^2).
I think a better O(nlogn) solution for this problem using Binary Indexed Tree(Fenwick Tree).
For each number I'll add each of the number in a global array a and perform two obvious operations of BIT.I think the time complexity of this algorithm is O(nlogn) which if true is obviously better than the previous O(n^2).
I have implemented the code in C++.
#include<iostream>
#include<cstdio>
using namespace std;
#define max 1000001
long int a[max];
void add(long int v,int idx){
while(idx<max){
a[idx] += v;
idx += (idx & -idx);
}
}
long int sum(int idx){
long int s=0;
while(idx>0){
s += a[idx];
idx -= (idx & -idx);
}
return s;
}
int main()
{
int t;
scanf("%d",&t);
for(int w=0;w<t;w++){
int n;
scanf("%d",&n);
for(int i=0;i<max;i++)
a[i]=0;
int arr[n];
for(int i=0;i<n;i++)
scanf("%d",&arr[i]);
long long res=0;
for(int i=0;i<n;i++){
if(arr[i]!=0){
add(arr[i],arr[i]);
res += (sum(arr[i]-1));
}
}
printf("%lld\n",res);
}
return 0;
}
I have two questions:
First, am I doing it correct? / Is my logic correct?
Second, if I'm right about the time complexity to be O(nlogn) then why does it run slow? Can you help me with any further optimizations?
Got Accepted with 1.41 seconds.At same time I have updated my finally accepted code.Any suggestion for optimization ?
Based on the comments I tried my own function for faster I/O but still it's not going my way.This is my function for fast I/O :
inline int read(){
char c=getchar_unlocked();
int n=0;
while(!(c>='0' && c<='9'))
c=getchar_unlocked();
while(c>='0' && c<='9'){
n=n*10 + (c-'0');
c=getchar_unlocked();
}
return n;
}
This is the link to the problem :
http://www.spoj.pl/problems/DCEPC206/
If there is anyone who is abled to solve it,please let me know.
Thanks.
I think your approach is a good one. I've played around with this a wee bit and haven't come up with anything generally better than what you have.
There are a couple of bugs in your code though. There are a few places suffering from integer overflow. You should change to:
long long a[max];
and
long long sum(int idx){
long long s=0;
The more apparent bug is that you're summing numbers which are less than or equal to the current number. To fix this issue, you could add a second global array for tracking the count of each value:
int b[max];
...
...
for(int i=0;i<max;i++)
a[i]=b[i]=0;
...
...
res += (sum(idx)-(++b[idx]*val));
There may be a more efficient way to fix that bug, but overall it still seems like a fast solution.
Here is another approach: the problem is similar to counting inversions, except you have to sum the elements responsible for generating inversions. We can solve this using merge sort. Modify the merge function like this:
merge(left, middle, right, array)
temp = new array
k = 0, i = left, j = middle + 1
while i <= middle and j <= right
if array[i] < array[j]
temp[k++] = array[i]
// array[i] is also smaller than all array[j+1], ..., array[right]
globalSum += array[i] * (right - j + 1)
else
// same as the classical function
Intuitively, I would say a recursive mergesort is slower than a BIT solution, but who knows? Give it a try.
Edit: This gets AC:
#include<stdio.h>
#include <iostream>
using namespace std;
#define max 100001
int n;
long long res = 0;
int temp[max];
int arr[max];
void merge(int left, int m, int right)
{
int k = 0;
int i = left, j = m + 1;
while (i <= m && j <= right)
if (arr[i] < arr[j])
{
temp[k++] = arr[i];
res += (long long)(right - j + 1) * arr[i++];
}
else
temp[k++] = arr[j++];
while (j <= right)
temp[k++] = arr[j++];
while (i <= m)
temp[k++] = arr[i++];
for (int i = 0; i < k; ++i)
arr[left + i] = temp[i];
}
void sort(int left, int right)
{
if (left < right)
{
int m = left + (right - left) / 2;
sort(left, m);
sort(m + 1, right);
merge(left, m, right);
}
}
int main()
{
int t;
scanf("%d", &t);
for(int w=0;w<t;w++)
{
scanf("%d", &n);
for(int i=0;i<n;i++)
scanf("%d", &arr[i]);
res=0;
sort(0, n - 1);
printf("%lld\n",res);
}
return 0;
}
Related
Given an array of N numbers (not necessarily sorted). We can merge any two numbers into one and the cost of merging the two numbers is equal to the sum of the two values. The task is to find the total minimum cost of merging all the numbers.
Example:
Let the array A = [1,2,3,4]
Then, we can remove 1 and 2, add both of them and keep the sum back in array. Cost of this step would be (1+2) = 3.
Now, A = [3,3,4], Cost = 3
In second step, we can 3 and 3, add both of them and keep the sum back in array. Cost of this step would be (3+3) = 6.
Now, A = [4,6], Cost = 6
In third step, we can remove both elements from the array and keep the sum back in array again. Cost of this step would be (4+6) = 6.
Now, A = [10], Cost = 10
So, total cost turns out to be 19 (10+6+3).
We will have to pick the 2 smallest elements to minimize our total cost. A simple way to do this is using a min heap structure. We will be able to get the minimum element in O(1) and insertion will be O(log n).
The time complexity of this approach is O(n log n).
But I tried another approach, and wasn't able to find the cases where it fails. The basic idea was that the sum of two smallest elements that we will choose at any time will always be greater than the sum of the pair of elements chosen before. So the "temp" array will always be sorted, and we will be able to access the minimum elements in O(1).
As I am sorting the input array and then simply traversing the array, the complexity of my approach is O(n log n).
int minCost(vector<int>& arr) {
sort(arr.begin(), arr.end());
// temp array will contain the sum of all the pairs of minimum elements
vector<int> temp;
// index for arr
int i = 0;
// index for temp
int j = 0;
int cost = 0;
// while we have more than 1 element combined in both the input and temp array
while(arr.size() - i + temp.size() - j > 1) {
int num1, num2;
// selecting num1 (minimum element)
if(i < arr.size() && j < temp.size()) {
if(arr[i] <= temp[j])
num1 = arr[i++];
else
num1 = temp[j++];
}
else if(i < arr.size())
num1 = arr[i++];
else if(j < temp.size())
num1 = temp[j++];
// selecting num2 (second minimum element)
if(i < arr.size() && j < temp.size()) {
if(arr[i] <= temp[j])
num2 = arr[i++];
else
num2 = temp[j++];
}
else if(i < arr.size())
num2 = arr[i++];
else if(j < temp.size())
num2 = temp[j++];
// appending the sum of the minimum elements in the temp array
int sum = num1 + num2;
temp.push_back(sum);
cost += sum;
}
return cost;
}
Is this approach correct? If not, please let me know what I am missing, and the test cases in which this algorithm fails.
SPOJ Link for the same problem
The logic seems very solid to me... all the computed sums will never be decreasing and therefore you only need to add up either oldest two computed sums, next two elements or oldest sum and next element.
I would just simplify the code:
#include <vector>
#include <algorithm>
#include <stdio.h>
int hsum(std::vector<int> arr) {
int ni = arr.size(), nj = 0, i = 0, j = 0, res = 0;
std::sort(arr.begin(), arr.end());
std::vector<int> temp;
auto get = [&]()->int {
if (j == nj || (i < ni && arr[i] < temp[j])) return arr[i++];
return temp[j++];
};
while ((ni-i)+(nj-j)>1) {
int a = get(), b = get();
res += a+b;
temp.push_back(a + b); nj++;
}
return res;
}
int main() {
fprintf(stderr, "%i\n", hsum(std::vector<int>{1,4,2,3}));
return 0;
}
Very nice idea!
Another improvement is noting that the cumulative length of the two arrays being processed (the original one and the temporary one holding the sums) will decrease at every step.
Since the first step will use two input elements, the fact that the temporary array grows one element at each step will still not be enough for a "walking queue" allocated in the array itself to reach the reading pointer.
This means that there is no need of a temporary array and the space for the sums can be found in the array itself...
int hsum(std::vector<int> arr) {
int ni = arr.size(), nj = 0, i = 0, j = 0, res = 0;
std::sort(arr.begin(), arr.end());
auto get = [&]()->int {
if (j == nj || (i < ni && arr[i] < arr[j])) return arr[i++];
return arr[j++];
};
while ((ni-i)+(nj-j)>1) {
int a = get(), b = get();
res += a+b;
arr[nj++] = a + b;
}
return res;
}
About the error on SPOJ... I tried briefly to search for the problem but I didn't succeed. I tried however generating random arrays of random lengths and checking this solution with what finds a "brute-force" one implemented directly from the specs and I'm reasonably confident that the algorithm is correct.
I know at least one programming arena (Topcoder) where sometimes the problems are carefully crafted so that the computation gives correct results if using unsigned but not if using int (or if using unsigned long long but not if using long long) because of integer overflow.
I don't know if SPOJ also does this kind of nonsense(1)... may be that is the reason some hidden test case fails...
EDIT
Checking with SPOJ the algorithm passes if using long long values... this is the entry I used:
#include <stdio.h>
#include <algorithm>
#include <vector>
int main(int argc, const char *argv[]) {
int n;
scanf("%i", &n);
for (int testcase=0; testcase<n; testcase++) {
int sz; scanf("%i", &sz);
std::vector<long long> arr(sz);
for (int i=0; i<sz; i++) scanf("%lli", &arr[i]);
int ni = arr.size(), nj = 0, i = 0, j = 0;
long long res = 0;
std::sort(arr.begin(), arr.end());
auto get = [&]() -> long long {
if (j == nj || (i < ni && arr[i] < arr[j])) return arr[i++];
return arr[j++];
};
while ((ni-i)+(nj-j)>1) {
long long a = get(), b = get();
res += a+b;
arr[nj++] = a + b;
}
printf("%lli\n", res);
}
return 0;
}
PS: This very kind of computation is also what is needed to build an Huffman tree for entropy coding given the symbols frequency table and thus it's not a mere random exercise but it has practical applications.
(1) I'm saying "nonsense" because in Topcoder they never give problems that require 65 bits; thus it's not a genuine care about overflows, but just setting traps for novices.
Another that I think is a bad practice I saw on TC is that some problems are carefully designed so that the correct algorithm if using C++ will barely fit in the timeout limit: just use another language (and get e.g. a 2× slowdown) and you cannot solve the problem.
First of all, think simple!
When using a priority queue, the problem is easy!
In the first test case :
1 6 3 20
// after pushing to Q
1 3 6 20
// and sum two top items and pop and push!
(1 + 3) 6 20 cost = 4
(4 + 6) 20 cost = 10 + 4
(10 + 20) cost = 30 + 14
30 cost = 44
#include<iostream>
#include<queue>
using namespace std;
int main()
{
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
priority_queue<long long int, vector<long long int>, greater<long long int>> q;
for (int i = 0; i < n; ++i) {
int k;
cin >> k;
q.push(k);
}
long long int sum = 0;
while (q.size() > 1) {
long long int a = q.top();
q.pop();
long long int b = q.top();
q.pop();
q.push(a + b);
sum += a + b;
}
cout << sum << "\n";
}
}
Basically we need to sort the list in desc order and then find its cost like this.
A.sort(reverse=True)
cost = 0
for i in range(len(A)):
cost += A[i] * (i+1)
return cost
for a while now I've been trying to get this code to work to partition (as if preparing for quicksort) the indexes of substring suffixes, and while it's close I'm not getting what I'm expecting. I was wondering if a fresh set of eyes may help.
int partition(const string &S, vector<int> &indices, int low, int high, int pivotIndex)
{
int i = low;
int j = high - 1;
swap(indices[high], indices[pivotIndex]);
while (i <= j)
{
while (i < high && !lessThan(S, S[i], S[indices[high]]))
i++;
while (j >= low && lessThan(S, S[j], S[indices[high]]))
j--;
if (i < j)
{
int temp = indices[i];
indices[i] = indices[j];
indices[j] = temp;
i++;
j--;
}
}
swap(indices[high], indices[i]);
return i;
}
Indices is simply a vector of 0, 1, 2, ..., n of same size as string S.
And here's the program I wrote for lessThan just so you know what I'm working with:
bool lessThan(const string &S, int first, int second)
{
int counter = (int)S.length() - ((first <= second) ? second : first);
for (int i = 0; i <= counter; ++i)
{
if (S[first + i] != S[second + i])
{
if (S[first + i] < S[second + i])
{
return true;
}
else
{
return false;
}
}
}
if (first < second)
{
return false;
}
else
{
return true;
}
}
lessThan seems to work just fine when I test it separately, so I don't think it's the issue, but maybe it is.
Whenever I test, with say the string "abracadabra", and setting the pivotIndex to 4, I expect to get "0 1 8 3 10 5 7 4 2 9 6" as my output but I instead get "0 1 8 3 7 5 4 10 2 9 6". Close, but not quite. Can anyone spot my mistake?
(P.S. I know I could probably use substr() or some other solution to do lessThan easier, but I'm trying to do it without allocating extra memory, my focus is on the partition function)
edit: I figured it out. Complete error on my side. Check below for answer
I was an idiot, input to lessThan was supposed to be given two ints. I instead gave it two chars from S. Also swapped which lessThan call the ! was on. I think I was just up too late programming and blame this all on sleep deprivation.
Fixed Code:
int partition(const string &S, vector<int> &indices, int low, int high, int pivotIndex)
{
int i = low;
int j = high - 1;
swap(indices[high], indices[pivotIndex]);
while (i <= j)
{ //This right here
while (i < high && lessThan(S, indices[i], indices[high]))
i++;
while (j >= low && !lessThan(S, indices[j], indices[high]))
j--;
if (i < j)
{
swap(indices[i], indices[j]);
i++;
j--;
}
}
swap(indices[high], indices[i]);
return i;
}
I am still a beginner at programming and i am taking an online course (algorithms)
one of the practice questions was to count the number of inversions in a file containing 100000 numbers randomly ordered. I have tried this code on small data sets and it worked fine but when passing the actual data set it gives inversion count in negative number. Tried various solutions from different platforms but still couldn't resolve it yet.
so this is my code
#include "stdafx.h"
#include <iostream>;
#include <conio.h>:
#include <fstream>
using namespace std;
long merge(int a[], int start, int mid, int end)
int i = start;
int j = mid + 1;
int k = start;
int inversion=0;
int temp[100000];
while (i <= mid && j <= end)
{
if (a[i] < a[j])
{
temp[k++] = a[i++];
}
else
{
temp[k++] = a[j++];
inversion =inversion + (mid - i);
}
}
while (i <= mid)
{
temp[k++] = a[i++];
}
while (j <= end)
{
temp[k++] = a[j++];
}
for (int i = start; i <= end; i++)
{
a[i] = temp[i];
}
return inversion;
long Msort(int a[], int start,int end)
{
if (start >= end)
{
return 0;
}
int inversion = 0;
int mid = (start + end) / 2;
inversion += Msort(a, start, mid);
inversion += Msort(a, mid + 1, end);
inversion += merge(a, start, mid, end)
return inversion;
}
long ReadFromFile(char FileName[], int storage[],int n)
{
int b;
int count=0;
ifstream get(FileName);
if (!get)
{
cout << "no file found";
}
while (!get.eof())
{
get >> storage[count];
count++;
}
b = count;
return b;
}
int main()
{
int valuescount = 0;
int arr[100000];
char filename[] = { "file.txt" };
long n = sizeof(arr) / sizeof(arr[0]);
valuescount=ReadFromFile(filename, arr,n);
int no_Of_Inversions = Msort(arr, 0, valuescount -1);
cout << endl << "No of inversions are" << '\t' << no_Of_Inversions <<'\t';
cout <<endl<< "Total no of array values sorted"<< valuescount<<endl;
system("pause");
}
`
The issue with your code is not directly related to the input size. Rather, in an indirect way, the negative number of inversions you find is the result of an overflow in the variable inversion of the function merge.
Consider the case for your input size N = 100000. If this array of numbers is sorted in decreasing order, then all the ordered pairs in that array will be an inversion. In other words, there will be N * (N-1) / 2 inversions to be counted. As you may have noticed, that value is slightly higher than the bounds of unsigned int type. Consequently, when you try and count this value in a variable of type int, overflow occurs, leading to a negative result.
To remedy this issue, you should change the type of the variable inversion from int to long long, in functions merge and Msort. (You should also update the return type of the functions merge and Msort) Naturally, you should assign the return value of the Msort call in the main function to a variable of type long long as well. In other words, change the type of variable no_Of_Inversions into a long long as well.
I have an assignment in the university to write a recursive function in C++ that finds the length of the longest ascending consecutive sub array of an array or integers. In addition, I have a code skeleton that I must use for my code and the function must not contain loops & more function.
For example, for the array 1,2,4,6,4,21,21,22,0,1,3,5,100,7
The result will be 5 (because 0 to 100 are 5 numbers).
The skeleton is:
#include <stdio.h>
#define MAX_SIZE 1000
int get_max_series(int a[], int size);
int main() {
int i, size_array, array[MAX_SIZE];
scanf("%d", &size_array);
for (i = 0; i < size_array; i++)
scanf("%d", &array[i]);
printf("%d", get_max_series(array, size_array));
return 0;
}
int get_max_series(int a[], int size) {
// My code should be here
}
I've succeeded to write a function that counts the number of ascending pairs, but failed in reseting the counter when the pair is descending. The code is below:
#include <stdio.h>
#define MAX_SIZE 1000
int get_max_series(int a[], int size);
int main() {
int i, size_array, array[MAX_SIZE];
scanf("%d", &size_array);
for (i = 0; i < size_array; i++)
scanf("%d", &array[i]);
printf("%d", get_max_series(array, size_array));
return 0;
}
int get_max_series(int a[], int size) {
if (size == 1)
return 1;
if (a[0] < a[1])
return 1 + get_max_series(&a[1], size - 1);
return get_max_series(&a[1], size - 1);
}
I'll be happy to get some advice how to get my code work for this scenario, or change the code entirely.
Thanks !
If you don't want to use static/global variables, or a helper function, you can use the following reduction for an array of size > 1 (it will be slow, though, since it does two recursive calls):
If a[0]>=a[1] then we cannot have a[0] in the maximal ascending subarray since it violates our notion of ascendancy so we return get_max_series(a+1, size - 1) like you have on your code.
When a[0]<a[1] we have two cases:
If get_max_series(a+1,size-1)==size-1, then the whole subarray a[1],...,a[size-1] is ascending. This implies a[0],a[1],...,a[size-1] is also ascending so we can return 1 + get_max_series(&a[1], size-1) in this case.
HOWEVER if get_max_series(a+1,size-1)!=size-1 that means that the subarray a[1],...,a[size-1] isn't ascending, so the maximal subarray cannot contain both a[1] and a[size-1] (by contiguity it would have to include everything in between, which would make it non-ascending).
Therefore, you return max(1+get_max_series(&a[0], size-1), get_max_series(&a[1], size-1)).
NOTE that here you do two calls to get_max_series, so your computational cost quickly grows(basically the same inefficiencies that appear when you do the naive recursive implementation of the fibonacci function).
The function would be something like
int get_max_series(int a[], int size) {
if (size <= 1)
return size;
int max_sub = get_max_series(&a[1], size - 1);
if (a[0] >= a[1])
return max_sub;
else{
if (max_sub==(size-1))
return size;
else
return std::max(get_max_series(&a[0], size-1), max_sub);
}
}
I'm using std::max here, but if you don't want to use the algorithm library you can find the maximum of two numbers using if-else.
Here's an O(n) routine that seems to follow your rules (the variable names should help explain what's going on):
#include <stdio.h>
#define MAX_SIZE 1000
int get_max_series(int a[], int size);
int main() {
int i, size_array, array[MAX_SIZE];
scanf("%d", &size_array);
for (i = 0; i < size_array; i++)
scanf("%d", &array[i]);
printf("%d", get_max_series(array, size_array));
return 0;
}
int get_max_series(int a[], int size) {
int i = size - 1;
if (i < 2){
if (a[1] > a[0])
return a[0] = 2;
else
return a[0] = 1;
}
int max = get_max_series(a, i);
int max_up_to_i = a[i - 2];
if (a[i] > a[i - 1]){
a[i - 1] = 1 + max_up_to_i;
if (a[i - 1] > max)
max = a[i - 1];
} else {
a[i - 1] = 1;
}
return max;
}
The longest ascending subarray does not necessarily start at the beginning of the array. Therefore,
return 1 + get_max_series(&a[1], size - 1);
is incorrect. I don't see how you can salvage the approach relying on inspecting just one character, at least within a given signature. Consider finding the longest ascending sequence at the beginning of the array, then recursing into the rest, along the lines of:
int get_max_series(int a[], int size)
{
int n = get_longest_acsending_prefix(a, size);
if (n == size)
return n;
return max(n, get_longest_ascending_prefix(a + n, size - n));
}
That said, I don't see a point of recursion here.
How to count comparisons in selectionsort?
terms:
when the statements you perform to find the maximum value is 'true'
then count comparison.
The value to get the maximum value is held at the first element in the array, not at random.
I try with C
variable count position change - no work
new variable 'first' , first=sort[MAX] insert first for loop, - no work
#include <stdio.h>
int main() {
int sort[10000], i, n, MAX, temp, count;
scanf("%d", &n);
for (i = 0; i < n; i++) {
scanf("%d", &sort[i]);
}
for (MAX = 0; MAX < n; MAX++)
for (i = MAX + 1; i < n; i++) {
if (sort[MAX] > sort[i]) {
count++;
temp = sort[MAX];
sort[MAX] = sort[i];
sort[i] = temp;
}
}
printf("%d ", count);
return 0;
}
Sample Input
10
0 7 1 6 7 7 6 6 5 4
Sample Output
17
EDIT: new code:
#include <stdio.h>
#define SWAP(x, y, temp) ( (temp)=(x), (x)=(y), (y)=(temp) )
int count = 0;
void selection_sort(int list[], int n) {
int i, j, least, temp;
for (i = 0; i < n - 1; i++) {
least = i;
for (j = i + 1; j < n; j++) {
if (list[j] < list[least]) {
least = j;
count++;
}
}
SWAP(list[i], list[least], temp);
}
}
int main() {
int list[10000], i, n;
scanf("%d", &n);
for (i = 0; i < n; i++) {
scanf("%d", &list[i]);
};
selection_sort(list, n);
printf("%d", count);
}
how about this? why this code didn't move too?
You aren't counting the right thing, this code
if(sort[MAX]>sort[i])
{
count++;
temp=sort[MAX];
sort[MAX]=sort[i];
sort[i]=temp;
}
counts the times that two numbers are swapped. But you want to count comparisons so it should be this
count++;
if(sort[MAX]>sort[i]) // this is what we are counting
{
temp=sort[MAX];
sort[MAX]=sort[i];
sort[i]=temp;
}
Another problem is that you don't give count an initial value of zero
int sort[10000],i,n,MAX,temp,count;
should be
int sort[10000],i,n,MAX,temp,count = 0;
how to count comparison selectionsort?
Your definition of the term is oddly worded, but it seems to be intended to focus on the essential comparisons of the algorithm, as opposed to comparisons performed incidentally for other purposes, or inside library functions. That is, in the implementation you present (whose correctness I do not evaluate), you're to count each evaluation of sort[MAX]>first, but not MAX<n or i<n.
You appear to be using variable count for that purpose, but you are counting only comparisons that evaluate to true. My interpretation of the problem, based both on the wording presented and on my general expectations for such a problem, is that every evaluation of sort[MAX]>first should be counted, regardless of the result. That would be achieved by lifting the expression count++ out of the if block, but leaving it inside the inner enclosing for loop.
Of course, as #john observes, you do need to initialize count to 0 before beginning to sort. You might luck into getting that by accident, but the initial value of a local variables without an initializer is indeterminate (at least) until a value is assigned.
i try with c variable count position change - no work
new variable 'first' , first=sort[MAX] insert first for loop, - no work
Even with the misplacement of your increment to count, if your sort were in fact working then you would expect to see some counts for most inputs. That you don't is a good sign that your sort in fact does not work correctly. I would suggest outputting also the the sorted results so that you can debug the details of the sort algorithm.
You could abstract out the comparison into a function or macro that also increments a counter. The macro approach could be
#define GT(x,y,counter) (counter++, (x) > (y) ? 1 : 0)
...
if ( GT( sort[MAX], sort[i], count ) == 1 )
{
// perform swap
}
whereas the function approach would be
int gt( int x, int y, int *counter )
{
(*counter)++;
if ( x > y )
return 1;
return 0;
}
...
if ( gt( sort[MAX], sort[i], &count ) == 1 )
{
// perform swap
}
You are counting the number of swaps, not the number of comparisons.
Here is a corrected without a global variable and a few extra checks:
#include <stdio.h>
#define SWAP(x, y, temp) ((temp) = (x), (x) = (y), (y) = (temp))
int selection_sort(int list[], int n) {
int count = 0;
int i, j, least, temp;
for (i = 0; i < n - 1; i++) {
least = i;
for (j = i + 1; j < n; j++) {
count++;
if (list[j] < list[least]) {
least = j;
}
}
SWAP(list[i], list[least], temp);
}
return count;
}
int main() {
int list[10000], i, n, count;
if (scanf("%d", &n) != 1 || n > 10000)
return 1;
for (i = 0; i < n; i++) {
if (scanf("%d", &list[i]) != 1)
return 1;
}
count = selection_sort(list, n);
printf("%d\n", count);
return 0;
}
Not however that your algorithm will always perform the same number of comparisons for any set of n values: n * (n - 1) / 2 comparisons, and since you do not test of i != least, it will perform n - 1 swaps.