Incorrect output for the second smallest integer - c++

I'm having trouble finding the second smallest integer in my array. The array is unsorted (it's what's in the data.txt file), so I know that might be part of the problem, I'm not sure how to fix this in the simplest way. Afterwards I have to remove that integer from the array, move every number over and reprint the array, if anyone could help I'd really appreciate it.
const NUM = 10;
int Array[NUM];
ifstream infile;
infile.open("Data.txt");
for (int i = 0; i < NUM; i++)
{
infile >> Array[i];
cout << Array[i] << endl;
}
int Min = Array[0];
int Next = 0, SecondMin = 0;
for (int k = 0; k < NUM; k++)
{
if (Min > Array[k])
Min = Array[k];
}
for (int m = 2; m < NUM; m++)
{
Next = Array[m];
if (Next > Min)
{
SecondMin = Min;
Min = Next;
}
else if (Next < SecondMin)
{
SecondMin = Next;
}
}
cout << "The second smallest integer is: " << SecondMin << endl;

You don't have to loop over the array twice to find the second smallest number. As long as you're keeping track of both the smallest and the second smallest, you should be able to find them both with a single loop.
There are a couple of other problems with this code:
Your check for end of file should probably be if (!infile.eof())
You don't need to check if (i < NUM) inside your loop. i will always be less than NUM due to the constraint on the loop.
If for some reason the number of items in the file is less than NUM, the rest of the items in the array will have undefined values. For instance, if there were only nine items in the file, after reading the file, Array[9] would have whatever value happened to be in that spot in memory when the array was created. This could cause problems with your algorithm.
I assume that this is some sort of homework problem, which is why the use of an array is required. But keep in mind for the future that you'd probably want to use a std::vector in this sort of situation. That way you could just keep reading numbers from the file and adding them to the vector until you reached the end, rather than having a fixed number of inputs, and all of the values in the vector would be valid.

Related

Did a competitive-like problem right but need help on improving its efficiency

The problem is simple. I'm given N - the number of digits in a number and then N digits of a number. I need to do exactly one digit-switch and get the highest number possible. I did do the problem right (as in gives out the right number) but it will be hitting the 1 second time restriction afaik. How do I improve on the efficiency of my program so it would go under the 1 second time restriction with N <= 10^6. New on Stack overflow so tell me if I did something wrong
with asking the question so I can fix it. Thanks. Here's my solution:
main:
int n;
cin >> n;
int a[n+1];
for(int i=0;i<n;++i)
cin >> a[i];
int maxofarray1;
bool changeHappened=false;
bool thereAreTwoSame=false;
for(int i=0;i<n;++i) //changing the two digits to make the highest number if possible
{
maxofarray1=maxofarray(a,i+1,n);
if(a[i]<maxofarray1)
{
int temp=a[a[n]];
a[a[n]]=a[i];
a[i]=temp;
changeHappened = true;
break;
}
}
for(int i=0;i<n;++i) //need to check if there are two of the same digit so I can change
//those two making the number the same instead of making it lower
for(int j=i+1;j<n;++j)
if(a[i]==a[j])
{
thereAreTwoSame=true;
break;
}
if(!changeHappened) //if the change has not been yet made, either leaving the number as is
//(changing two same numbers) or changing the last two to do as little "damage" to the number
{
if(!thereAreTwoSame)
{
int temp=a[n-1];
a[n-1]=a[n-2];
a[n-2]=temp;
}
}
for(int i=0;i<n;++i)
cout << a[i] << " ";
return 0;
maxofarray:
int maxofarray(int a[], int i,int n) //finding the maximum of the array from i to n
{
int max1=0;
int maxind;
for(int j=i;j<n;++j)
{
if(max1<a[j])
{
max1=a[j];
maxind=j;
}
}
a[n]=maxind; //can't return both the index and maximum (without complicating with structs)
//so I add it as the last element
return max1;
}
The problem in your code is complexity. I didn't fully understand your algorithm, but having nested loops is a red flag. Instead of trying to improve bits and pieces of your code you should rather rethink your overall strategy.
Lets start by assuming the digit 9 does appear in the number. Consider the number is
9...9 c ...9...
where 9...9 are the leading digits that are all 9 (possibly there are none of them). We cannot make the number bigger by swapping one of those.
c is the first digits !=9, ie its the place where we can put a 9 to get a bigger number. 9 is the digit that will make the number maximum when put in this place.
Last, ...9... denotes the last appearance of the digit 9 and digits sourrinding that. After that 9 no other 9 appears. While we increase the number by replacing c, the number will get smaller be replacing that 9, hence we have to choose the very last one.
For the general case only a tiny step more is needed. Here is a rough sketch:
std::array<size_t,10> first_non_appearance;
std::array<size_t,10> last_appearance;
size_t n;
std::cin >> n;
std::vector<int> number(n);
for (size_t i=0;i <n;++i) {
std::cin >> a[i];
for (int d=0;d<10;++d) {
// keep track of first and last appearance of each digit
}
}
size_t first = 0;
size_t second = 0;
for (int d=0;d<10;++d) {
// determine biggest digit that appeared and use that
}
std:swap( a[first],a[last] );
It is not complete, perhaps requires handling of special cases (eg number with only one digit), but I hope it helps.
PS: You are using a variable length array (int a[n+1];), this is not standard C++. In C++ you should rather use a std::vector when you know the size only at runtime (and a std::array when the size is known).
VLA (variable length arrays) are not standard. So instead of using this nonstandard feature, you might want to use a STL data type.
Given N is rather big, you also avoid stack overflow, given that VLA are allocated on the stack. And STL containers with variable length allocate on the heap.
Then, as you pointed out yourself, it makes sense to remember the index of the last occurrence of each digit, avoiding to search over and over again for a swap candidate index.
Your implementation idea is basically, to replace the first digit from the left, which has a bigger replacement to the right of it.
This is how I did it:
static void BigSwap(std::string& digits)
{
int64_t fromRight[10];
size_t ndigitsFound = 0;
for (size_t i = 0; i < 10; i++)
fromRight[i] = -1;
size_t i = digits.size() - 1;
while (ndigitsFound < 10 && i > 0)
{
if (-1 == fromRight[digits[i] - '0'])
{
fromRight[digits[i] - '0'] = static_cast<int64_t>(i);
ndigitsFound++;
}
i--;
}
for (size_t j = 0; j < digits.size(); j++)
{
char d = digits[j] - '0';
for (char k = 9; k > d; k--)
{
if (fromRight[k] != -1 && static_cast<size_t>(fromRight[k]) > j)
{
auto temp = digits[j];
digits[j] = k + '0';
digits[fromRight[k]] = temp;
return;
}
}
}
}

Why is an exception being thrown in this dynamic array?

I am having trouble understanding why this exception is being thrown. I allocated an array to receive 100 int values and want to store all odd numbers under 200 into the array (which should be 100 integer values). I'm trying to understand why my code is not working.
I have called my function to allocate an array of 100 int values. After, I created a for-loop to iterate through and store integers into the array however I created an if statement to only store odd numbers. What I can't understand is if I put my counter to 200 and use the if statement an exception is thrown, but if I don't insert the if statement and only put my counter to 100 all numbers between 1-100 stored and an exception won't be thrown.
The only thing I can think of that's causing this is when my counter is at 200 and I have the if statement to catch all odd number, somehow all numbers under 200 are being stored in the array causing the exception to be thrown.
int *allocIntArray(int);
int main() {
int *a;
a = allocIntArray(100);
for (int count = 1; count < 200; count++) {
if (a[count] % 2 == 1) {
a[count] = count;
cout << a[count] << endl;
}
}
delete[] a;
return 0;
}
int *allocIntArray(int size) {
int *newarray = new int[size]();
return newarray;
}
When I look at the program output, it only displays the odd numbers yet the exception is being thrown. That tells me my if statement is working yet something is being muddied up.
What am I missing?
Thanks for your time and knowledge.
Cause of the error
If you have an array a that was created with n elements, it is undefined behavior when trying to access an array element out of bouds. So the index MUST always be between 0 and n-1.
So the behavior of your program is undefined as soon as count is 100, since evaluating the condition in the if-clause already tries to access out of bounds.
Adjustment that does what you want
Now in addition, there is a serious bug in your program logic: If you want to add numbers that satisfy some kind of condition, you need 2 counters: one for iterating on the numbers, and one for the last index used in the array:
for (int nextitem=0, count = 1; count < 200; count++) {
if (count % 2 == 1) { // not a[count], you need to test number itself
a[nextitem++] = count;
cout << count << endl;
if (nextitem == 100) { // attention: hard numbers should be avoided
cout << "Array full: " << nextitem << " items reached at " << count <<endl;
break; // exit the for loop
}
}
}
But, this solution requires you to keep track of the last item in the array, and the size of the array (it's hard-coded here).
Vectors
You are probably learning. But in C++ a better solution would be to use vector instead of an array, and use push_back(). Vectors manage the memory, so that you can focus on your algorithm. The full program would then look like:
vector<int> a;
for (int count = 1; count < 200; count++) {
if (count % 2 == 1) {
a.push_back(count);
cout << count << endl;
}
}
cout << "Added " << a.size() << " elements" <<endl;
cout << "10th element: "<< a[9] << endl;
The problem is not how many numbers you're storing but where you're storing them; you're storing 101 in a[101], which is obviously wrong.
If the i:th odd number is C, the correct index is i-1, not C.
The most readable change is probably to introduce a new counter variable.
int main() {
int a[100] = {0};
int count = 0;
for (int number = 1; number < 200; number++) {
if (number % 2 == 1) {
a[count] = number;
count += 1;
}
}
}
I think transforming this from a search problem to a generation problem makes it easier to get right.
If you happen to remember that every odd number C can be written on the form 2 * A + 1for some A, you' will see that the sequence you're looking for is
2*0+1, 2*1+1, 2*2+1, ..., 2*99+1
so
int main()
{
int numbers[100] = {0};
for (int i = 0; i < 100; i++)
{
numbers[i] = 2 * i + 1;
}
}
You can also go the other way around, looping over the odd numbers and storing them in the right place:
int main()
{
int numbers[100] = {0};
for (int i = 1; i < 200; i += 2) // This loops over the odd numbers.
{
numbers[i/2] = i; // Integer division makes this work.
}
}

binary search array overflow c++

I'm a Computer Science student. This is some code that I completed for my Data Structures and Algorithms class. It compiles fine, and runs correctly, but there is an error in it that I corrected with a band-aid. I'm hoping to get an answer as to how to fix it the right way, so that in the future, I know how to do this right.
The object of the assignment was to create a binary search. I took a program that I had created that used a heap sort and added a binary search. I used Visual Studio for my compiler.
My problem is that I chose to read in my values from a text file into an array. Each integer in the text file is separated by a tabbed space. In line 98, the file reads in correctly, but when I get to the last item in the file, the counter (n) counts one time too many, and assigns a large negative number (because of the array overflow) to that index in the array, which then causes my heap sort to start with a very large negative number that I don't need. I put a band-aid on this by assigning the last spot in the array the first spot in the array. I have compared the number read out to my file, and every number is there, but the large number is gone, so I know it works. This is not a suitable fix for me, even if the program does run correctly. I would like to know if anyone knows of a correct solution that would iterate through my file, assign each integer to a spot in the array, but not overflow the array.
Here is the entire program:
#include "stdafx.h"
#include <iostream>
#include <fstream>
using std::cout;
using std::cin;
using std::endl;
using std::ifstream;
#define MAXSIZE 100
void heapify(int heapList[], int i, int n) //i shows the index of array and n is the counter
{
int listSize;
listSize=n;
int j, temp;//j is a temporary index for array
temp = heapList[i];//temporary storage for an element of the array
j = 2 * i;//end of list
while (j <= listSize)
{
if (j < listSize && heapList[j + 1] > heapList[j])//if the value in the next spot is greater than the value in the current spot
j = j + 1;//moves value if greater than value beneath it
if (temp > heapList[j])//if the value in i in greater than the value in j
break;
else if (temp <= heapList[j])//if the value in i is less than the value in j
{
heapList[j / 2] = heapList[j];//assigns the value in j/2 to the current value in j--creates parent node
j = 2 * j;//recreates end of list
}
}
heapList[j / 2] = temp;//assigns to value in j/2 to i
return;
}
//This method is simply to iterate through the list of elements to heapify each one
void buildHeap(int heapList[], int n) {//n is the counter--total list size
int listSize;
listSize = n;
for (int i = listSize / 2; i >= 1; i--)//for loop to create heap
{
heapify(heapList, i, n);
}
}
//This sort function will take the values that have been made into a heap and arrange them in order so that they are least to greatest
void sort(int heapList[], int n)//heapsort
{
buildHeap(heapList, n);
for (int i = n; i >= 2; i--)//for loop to sort heap--i is >= 2 because the last two nodes will not have anything less than them
{
int temp = heapList[i];
heapList[i] = heapList[1];
heapList[1] = temp;
heapify(heapList, 1, i - 1);
}
}
//Binary search
void binarySearch(int heapList[], int first, int last) {//first=the beginning of the list, last=end of the list
int mid = first + last / 2;//to find middle for search
int searchKey;//number to search
cout << "Enter a number to search for: ";
cin >> searchKey;
while ((heapList[mid] != searchKey) && (first <= last)) {//while we still have a list to search through
if (searchKey < heapList[mid]) {
last = mid - 1;//shorten list by half
}
else {
first = mid + 1;//shorten list by half
}
mid = (first + last) / 2;//find new middle
}
if (first <= last) {//found number
cout << "Your number is " << mid << "th in line."<< endl;
}
else {//no number in list
cout << "Could not find the number.";
}
}
int main()
{
int j = 0;
int n = 0;//counter
int first = 0;
int key;//to prevent the program from closing
int heapList[MAXSIZE];//initialized heapList to the maximum size, currently 100
ifstream fin;
fin.open("Heapsort.txt");//in the same directory as the program
while (fin >> heapList[n]) {//read in
n++;
}
heapList[n] = heapList[0];
int last = n;
sort(heapList, n);
cout << "Sorted heapList" << endl;
for (int i = 1; i <= n; i++)//for loop for printing sorted heap
{
cout << heapList[i] << endl;
}
binarySearch(heapList, first, last);
cout << "Press Ctrl-N to exit." << endl;
cin >> key;
}
int heapList[MAXSIZE];//initialized heapList to the maximum size, currently 100
This comment is wrong - heapList array is declared not initialized, so when you had read all data from the file, index variable n will point to the uninitialized cell. Any attempt to use it will invoke an undefined behavior. You could either: initialize an array before using it, decrement n value, since it greater than read values number by one, or better use std::vector instead of array.
You populate values for heapsort for indices 0 to n-1 only.
Then you access heaplist from 1 to n which is out of bounds since no value was put in heapsort[n].
Use
for (int i = 0; i < n; i++) //instead of i=1 to n

This sorting array code cause the last element dissapear

So, I tried to make an array using input first, then sorting it out from smallest to biggest, then display the array to monitor.
So I come up with this code :
#include <iostream>
using namespace std;
void pancakeSort(int sortArray[], int sortSize);
int main()
{
// Input The Array Element Value
int pancake[10];
for(int i=0; i<10; i++)
{
cout << "Person " << i+1 << " eat pancakes = ";
cin >> pancake[i];
}
// call pancake sorting function
pancakeSort(pancake, 10);
}
void pancakeSort(int sortArray[], int sortSize)
{
int length = 10;
int temp;
int stop = 10;
// this is where the array get sorting out from smallest to biggest number
for(int counter = length-1; counter>=0; counter--)
{
for(int j=0; j<stop; j++)
{
if(sortArray[j]>sortArray[j+1])
{
temp = sortArray[j+1];
sortArray[j+1] = sortArray[j];
sortArray[j]=temp;
}
}
stop--;
}
// after that, the array get display here
for(int x=0; x<sortSize; x++)
{
cout << sortArray[x] << " ";
}
}
but the output is weird :
enter image description here
the function is successfully sorting the array from smallest to biggest,
but there is 2 weird things :
1. The biggest value element (which is 96 from what I input and it's the 10th element after got sorted out), disappear from the display.
2. For some reason, there is value 10 , which I didn't input on the array.
So, what happened?
In the loop
for(int j=0; j<stop; j++)
{
if(sortArray[j]>sortArray[j+1])
{
temp = sortArray[j+1];
sortArray[j+1] = sortArray[j];
sortArray[j]=temp;
}
}
stop is the length of the array, and you are iterating through values of j = 0 to stop - 1. When j reaches stop - 1, the next element that is j+1 becomes stop (10 in this case). But since your array has a length of 10, sortArray[10] is not part of the array, but is referring to some other object in memory which is usually a garbage value. The garbage value is 10 in this case. When you swap sortArray[10] and sortArray[9], the garbage value becomes part of the array and the value at index 9 leaves the array. This keeps on happening till the outer loop ends.
The end result is that unless the garbage value < largest element in the array, the garbage value is pushed in the array and the greatest value of the array is put at sortArray[10] which is not part of the array. If the garbage value is greater than all the values of the array, it'll be found at sortArray[10] which is again not part of the array and your code will return the desired result.
Essentially, what you are doing is giving the function an array of 10 (or stop) elements, but the function is actually working with an array of 11 (or stop + 1) elements, with the last element being a garbage value. The simple fix is to change the conditional of the loop to j < stop - 1.
Note that if you had written this code in a managed (or a comparatively higher level) language like Java or C#, it would have raised an IndexOutOfBoundsException.
At index 9, j+1 is out of bounds. So to fix this, you only need to check till index 8
for(int counter = length-1; counter>=0; counter--)
{
for(int j=0; j<stop-1; j++)
{
if(sortArray[j]>sortArray[j+1])
{
temp = sortArray[j+1];
sortArray[j+1] = sortArray[j];
sortArray[j]=temp;
}
}
stop--;
}
Look carefully at the inner loop condition j<stop-1

Count number of ways for choosing two numbers in efficient algorithm

I solved this problem but I got TLE Time Limit Exceed on online judge
the output of program is right but i think the way can be improved to be more efficient!
the problem :
Given n integer numbers, count the number of ways in which we can choose two elements such
that their absolute difference is less than 32.
In a more formal way, count the number of pairs (i, j) (1 ≤ i < j ≤ n) such that
|V[i] - V[j]| < 32. |X|
is the absolute value of X.
Input
The first line of input contains one integer T, the number of test cases (1 ≤ T ≤ 128).
Each test case begins with an integer n (1 ≤ n ≤ 10,000).
The next line contains n integers (1 ≤ V[i] ≤ 10,000).
Output
For each test case, print the number of pairs on a single line.
my code in c++ :
int main() {
int T,n,i,j,k,count;
int a[10000];
cin>>T;
for(k=0;k<T;k++)
{ count=0;
cin>>n;
for(i=0;i<n;i++)
{
cin>>a[i];
}
for(i=0;i<n;i++)
{
for(j=i;j<n;j++)
{
if(i!=j)
{
if(abs(a[i]-a[j])<32)
count++;
}
}
}
cout<<count<<endl;
}
return 0;
}
I need help how can I solve it in more efficient algorithm ?
Despite my previous (silly) answer, there is no need to sort the data at all. Instead you should count the frequencies of the numbers.
Then all you need to do is keep track of the number of viable numbers to pair with, while iterating over the possible values. Sorry no c++ but java should be readable as well:
int solve (int[] numbers) {
int[] frequencies = new int[10001];
for (int i : numbers) frequencies[i]++;
int solution = 0;
int inRange = 0;
for (int i = 0; i < frequencies.length; i++) {
if (i > 32) inRange -= frequencies[i - 32];
solution += frequencies[i] * inRange;
solution += frequencies[i] * (frequencies[i] - 1) / 2;
inRange += frequencies[i];
}
return solution;
}
#include <bits/stdc++.h>
using namespace std;
int a[10010];
int N;
int search (int x){
int low = 0;
int high = N;
while (low < high)
{
int mid = (low+high)/2;
if (a[mid] >= x) high = mid;
else low = mid+1;
}
return low;
}
int main() {
cin >> N;
for (int i=0 ; i<N ; i++) cin >> a[i];
sort(a,a+N);
long long ans = 0;
for (int i=0 ; i<N ; i++)
{
int t = search(a[i]+32);
ans += (t -i - 1);
}
cout << ans << endl;
return 0;
}
You can sort the numbers, and then use a sliding window. Starting with the smallest number, populate a std::deque with the numbers so long as they are no larger than the smallest number + 31. Then in an outer loop for each number, update the sliding window and add the new size of the sliding window to the counter. Update of the sliding window can be performed in an inner loop, by first pop_front every number that is smaller than the current number of the outer loop, then push_back every number that is not larger than the current number of the outer loop + 31.
One faster solution would be to first sort the array, then iterate through the sorted array and for each element only visit the elements to the right of it until the difference exceeds 31.
Sorting can probably be done via count sort (since you have 1 ≤ V[i] ≤ 10,000). So you get linear time for the sorting part. It might not be necessary though (maybe quicksort suffices in order to get all the points).
Also, you can do a trick for the inner loop (the "going to the right of the current element" part). Keep in mind that if S[i+k]-S[i]<32, then S[i+k]-S[i+1]<32, where S is the sorted version of V. With this trick the whole algorithm turns linear.
This can be done constant number of passes over the data, and actually can be done without being affected by the value of the "interval" (in your case, 32).
This is done by populating an array where a[i] = a[i-1] + number_of_times_i_appears_in_the_data - informally, a[i] holds the total number of elements that are smaller/equals to i.
Code (for a single test case):
static int UPPER_LIMIT = 10001;
static int K = 32;
int frequencies[UPPER_LIMIT] = {0}; // O(U)
int n;
std::cin >> n;
for (int i = 0; i < n; i++) { // O(n)
int x;
std::cin >> x;
frequencies[x] += 1;
}
for (int i = 1; i < UPPER_LIMIT; i++) { // O(U)
frequencies[i] += frequencies[i-1];
}
int count = 0;
for (int i = 1; i < UPPER_LIMIT; i++) { // O(U)
int low_idx = std::max(i-32, 0);
int number_of_elements_with_value_i = frequencies[i] - frequencies[i-1];
if (number_of_elements_with_value_i == 0) continue;
int number_of_elements_with_value_K_close_to_i =
(frequencies[i-1] - frequencies[low_idx]);
std::cout << "i: " << i << " number_of_elements_with_value_i: " << number_of_elements_with_value_i << " number_of_elements_with_value_K_close_to_i: " << number_of_elements_with_value_K_close_to_i << std::endl;
count += number_of_elements_with_value_i * number_of_elements_with_value_K_close_to_i;
// Finally, add "duplicates" of i, this is basically sum of arithmetic
// progression with d=1, a0=0, n=number_of_elements_with_value_i
count += number_of_elements_with_value_i * (number_of_elements_with_value_i-1) /2;
}
std::cout << count;
Working full example on IDEone.
You can sort and then use break to end loop when ever the range goes out.
int main()
{
int t;
cin>>t;
while(t--){
int n,c=0;
cin>>n;
int ar[n];
for(int i=0;i<n;i++)
cin>>ar[i];
sort(ar,ar+n);
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(ar[j]-ar[i] < 32)
c++;
else
break;
}
}
cout<<c<<endl;
}
}
Or, you can use a hash array for the range and mark occurrence of each element and then loop around and check for each element i.e. if x = 32 - y is present or not.
A good approach here is to split the numbers into separate buckets:
constexpr int limit = 10000;
constexpr int diff = 32;
constexpr int bucket_num = (limit/diff)+1;
std::array<std::vector<int>,bucket_num> buckets;
cin>>n;
int number;
for(i=0;i<n;i++)
{
cin >> number;
buckets[number/diff].push_back(number%diff);
}
Obviously the numbers that are in the same bucket are close enough to each other to fit the requirement, so we can just count all the pairs:
int result = std::accumulate(buckets.begin(), buckets.end(), 0,
[](int s, vector<int>& v){ return s + (v.size()*(v.size()-1))/2; });
The numbers that are in non-adjacent buckets cannot form any acceptable pairs, so we can just ignore them.
This leaves the last corner case - adjacent buckets - which can be solved in many ways:
for(int i=0;i<bucket_num-1;i++)
if(buckets[i].size() && buckets[i+1].size())
result += adjacent_buckets(buckets[i], buckets[i+1]);
Personally I like the "occurrence frequency" approach on the one bucket scale, but there may be better options:
int adjacent_buckets(const vector<int>& bucket1, const vector<int>& bucket2)
{
std::array<int,diff> pairs{};
for(int number : bucket1)
{
for(int i=0;i<number;i++)
pairs[i]++;
}
return std::accumulate(bucket2.begin(), bucket2.end(), 0,
[&pairs](int s, int n){ return s + pairs[n]; });
}
This function first builds an array of "numbers from lower bucket that are close enough to i", and then sums the values from that array corresponding to the upper bucket numbers.
In general this approach has O(N) complexity, in the best case it will require pretty much only one pass, and overall should be fast enough.
Working Ideone example
This solution can be considered O(N) to process N input numbers and constant in time to process the input:
#include <iostream>
using namespace std;
void solve()
{
int a[10001] = {0}, N, n, X32 = 0, ret = 0;
cin >> N;
for (int i=0; i<N; ++i)
{
cin >> n;
a[n]++;
}
for (int i=0; i<10001; ++i)
{
if (i >= 32)
X32 -= a[i-32];
if (a[i])
{
ret += a[i] * X32;
ret += a[i] * (a[i]-1)/2;
X32 += a[i];
}
}
cout << ret << endl;
}
int main()
{
int T;
cin >> T;
for (int i=0 ; i<T ; i++)
solve();
}
run this code on ideone
Solution explanation: a[i] represents how many times i was in the input series.
Then you go over entire array and X32 keeps track of number of elements that's withing range from i. The only tricky part really is to calculate properly when some i is repeated multiple times: a[i] * (a[i]-1)/2. That's it.
You should start by sorting the input.
Then if your inner loop detects the distance grows above 32, you can break from it.
Thanks for everyone efforts and time to solve this problem.
I appreciated all Attempts to solve it.
After testing the answers on online judge I found the right and most efficient solution algorithm is Stef's Answer and AbdullahAhmedAbdelmonem's answer also pavel solution is right but it's exactly same as Stef solution in different language C++.
Stef's code got time execution 358 ms in codeforces online judge and accepted.
also AbdullahAhmedAbdelmonem's code got time execution 421 ms in codeforces online judge and accepted.
if they put detailed explanation to there algorithm the bounty will be to one of them.
you can try your solution and submit it to codeforces online judge at this link after choosing problem E. Time Limit Exceeded?
also I found a great algorithm solution and more understandable using frequency array and it's complexity O(n).
in this algorithm you only need to take specific range for each inserted element to the array which is:
begin = element - 32
end = element + 32
and then count number of pair in this range for each inserted element in the frequency array :
int main() {
int T,n,i,j,k,b,e,count;
int v[10000];
int freq[10001];
cin>>T;
for(k=0;k<T;k++)
{
count=0;
cin>>n;
for(i=1;i<=10000;i++)
{
freq[i]=0;
}
for(i=0;i<n;i++)
{
cin>>v[i];
}
for(i=0;i<n;i++)
{
count=count+freq[v[i]];
b=v[i]-31;
e=v[i]+31;
if(b<=0)
b=1;
if(e>10000)
e=10000;
for(j=b;j<=e;j++)
{
freq[j]++;
}
}
cout<<count<<endl;
}
return 0;
}
finally i think the best approach to solve this kind of problems to use frequency array and count number of pairs in specific range because it's time complexity is O(n).