Input array is something like:
[0,0,1,2,4,7,9,6,4,4,2,1,0,0,0,0,0,3,5,5,10,3,2,1,4,5,7,7,12,11,8,4,2,
1,1,1,2,4,9,4,2,2,0,1,3,6,13,11,5,5,2,2,3,4,7,11,8...]
As we can see there are hills and valleys in an array with repeating (possibly) minimum values for same valley. I extended This (addresses arrays with distinct elements) idea to find solution to above as:
/// <summary>
/// Returns index array where valley lies
/// </summary>
/// <param name="arraySmoothed"></param>
/// <returns></returns>
private static List<int> GetValleys(List<int> arraySmoothed) {
List<int> valleys = new List<int>();
List<int> tempValley = new List<int>();
bool contdValleyValues = false;
for (int i = 0; i < arraySmoothed.Count; i++) {
// A[i] is minima if A[i-1] >= A[i] <= A[i+1], <= instead of < is deliberate otherwise it won't work for consecutive repeating minima values for a valley
bool isValley = ((i == 0 ? -1 : arraySmoothed[i - 1]) >= arraySmoothed[i])
&& (arraySmoothed[i] <= (i == arraySmoothed.Count - 1 ? -1 : arraySmoothed[i + 1]));
// If several equal minima values for same valley, average the indexes keeping in temp list
if (isValley) {
if (!contdValleyValues)
contdValleyValues = true;
tempValley.Add(i);
} else {
if (contdValleyValues) {
valleys.Add((int)tempValley.Average());
tempValley.Clear();
contdValleyValues = false;
}
}
}
return valleys;
}
This method gets stuck at ...7,9,6,4,4,2,1,0,0,0,0,0,3,5,5,10,3... where it throws out three minima, but there should be one (the middle 0 among five). Complexity is not the issue for me, will worship O(n). I just want a generic solution. Any hint/help will be appreciated.