I\'m having trouble writing a method that returns true if the elements of an array (numbers) are in sorted order, ascending or descending, and false, if they are not in any
An array with 2 (or less) elements is sorted,
{0,0} is sorted asc & desc, {0,1} asc, {1,0} desc, {1,1} asc & desc.
It is possible to use one loop, but it seems faster to separate cases.
For an array with more than 2 elements,
if the first element is less than the last element,
check: a[i] <= a[i + 1].
Below I use "ai <= (ai = a[i])", compare the old value of ai with the new
value of ai, each element is read once.
using System;
class Program
{
static void Main()
{
int i = 512; int[] a = new int[i--]; while (i > 0) a[i] = i--; //a[511] = 1;
Console.WriteLine(isSorted0(a));
var w = System.Diagnostics.Stopwatch.StartNew();
for (i = 1000000; i > 0; i--) isSorted0(a);
Console.Write(w.ElapsedMilliseconds); Console.Read();
}
static bool isSorted0(int[] a) // 267 ms
{
if (a.Length < 3) return true; int j = a.Length - 1;
return a[0] < a[j] ? incr(a) : a[0] > a[j] ? decr(a) : same(a);
}
static bool incr(int[] a)
{
int ai = a[0], i = 1, j = a.Length;
while (i < j && ai <= (ai = a[i])) i++; return i == j;
}
static bool decr(int[] a)
{
int ai = a[0], i = 1, j = a.Length;
while (i < j && ai >= (ai = a[i])) i++; return i == j;
}
static bool same(int[] a)
{
int ai = a[0], i = 1, j = a.Length - 1;
while (i < j && ai == a[i]) i++; return i == j;
}
static bool isSorted1(int[] numbers) // 912 ms accepted answer
{
bool? ascending = null;
for (int i = 1; i < numbers.Length; i++)
if (numbers[i - 1] != numbers[i])
{
bool ascending2 = numbers[i - 1] < numbers[i];
if (ascending == null) ascending = ascending2;
else if (ascending.Value != ascending2) return false;
}
return true;
}
}
A short version.
static bool isSorted(int[] a)
{
if (a.Length < 3) return true; int i = a.Length - 1, ai = a[i--];
if (ai > a[0]) while (i >= 0 && ai >= (ai = a[i])) i--;
else if (ai < a[0]) while (i >= 0 && ai <= (ai = a[i])) i--;
else while (i >= 0 && ai == a[i]) i--; return i < 0;
}