Skip to content

Instantly share code, notes, and snippets.

@shawnmclean
Created November 13, 2011 23:20
Show Gist options
  • Save shawnmclean/1362902 to your computer and use it in GitHub Desktop.
Save shawnmclean/1362902 to your computer and use it in GitHub Desktop.
Count Sorted Array
public static int CountSorted<T>(this List<T> list, T item) where T : IComparable
{
//find random index of the item
int index = list.BinarySearch(item);
//if item isn't found, just return -1
if (index < 0)
return -1;
int leftEdge = findLeftEdge(list, 0, index, item, Comparer<T>.Default);
int rightEdge = findRightEdge(list, index, list.Count - 1,item, Comparer<T>.Default);
//count it by taking away the left from the right
return rightEdge-leftEdge + 1;
}
private static int findLeftEdge<T>(IList<T> list, int start, int end, T item, Comparer<T> comparer)
{
int left = start;
int right = end;
//the left or the right always move closer to each other until overlapped.
while (left <= right)
{
//calculate the midpoint between the left and right edge
int mid = (left + right) / 2;
int compareVal = comparer.Compare(list[mid], item);
if (compareVal == 0)
{
//before moving, check if its the start.
if (mid == start)
return mid;
//check to see if there is anymore to the immediate left, then move to the left
if(comparer.Compare(list[mid-1], item) == 0)
right = mid-1;
else
//return mid since there is no more to the left
return mid;
}
else
{
//check to see if there is any to the immediate right, then return that index.
if (comparer.Compare(list[mid + 1], item) == 0)
return mid + 1;
else
//else, we move back to the right
left = mid;
}
}
//no more was found, so just return the end
return end;
}
private static int findRightEdge<T>(IList<T> list, int start, int end, T item, Comparer<T> comparer)
{
int left = start;
int right = end;
//the left or the right always move closer to each other until overlapped.
while (left <= right)
{
//calculate the midpoint between the left and right edge
int mid = (left + right) / 2;
int compareVal = comparer.Compare(list[mid], item);
if (compareVal == 0)
{
//before moving, check if its the end.
if (mid == end)
return mid;
//check to see if there is anymore to the immediate right, then move to the left
if (comparer.Compare(list[mid + 1], item) == 0)
left = mid+1;
else
//return mid since there is no more to the left
return mid;
}
else
{
//check to see if there is any to the immediate left, then return that index.
if (comparer.Compare(list[mid - 1], item) == 0)
return mid - 1;
else
//else, we move back to the left
right = mid;
}
}
//no more was found, so just return the start
return start;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment