[英]Find the lowest and highest NUMBERS in a collection
我有一個List<BigDecimal>
集合,其中包含(為了簡單起見) BigDecimal
價格。 我想處理集合並得到:
我最初的想法是使用后視法來解決這個問題,以確定數字是在上升還是下降趨勢中移動。 當趨勢發生變化時——確定之前的數字中哪些是“最高”或“最低”價格,然后將它們添加到尊重的List<BigDecimal> lowestPrices
和List<BigDecimal highestPrices
collections。例如,前 3 個點是向上的-trend,但是 4 號將趨勢變為下降趨勢。 所以現在可以確定更改前數字的min/max
(0,1,2) 並獲取價格。
我不完全確定這是否是一種幼稚的方法,所以我想知道 java 中是否有解決此問題的最佳方法? 也許圖書館已經可以做到這一點? (最好不要重新發明輪子)
您正在尋找局部最大值(/最小值)。
只需查看當前點是否大於(/小於)其前后的點:
對於局部最大值:
list.get(i) > list.get(i - 1) && list.get(i) > list.get(i + 1)
對於局部最小值:
list.get(i) < list.get(i - 1) && list.get(i) < list.get(i + 1)
偽代碼:
for (int i = 1; i < list.size()-1; ++i) {
if (local maximum) {
// Add to list of local maxima
} else if (local minimum) {
// Add to list of local minima
}
}
並根據需要處理這兩個端點。
(您也可以使用 (List)Iterators 以對非隨機訪問列表更有效的方式執行此操作,例如LinkedList
;但原理是相同的)。
我決定嘗試實現這一點,盡管我確信我的實現可以改進。 這個想法就像你說的那樣,跟蹤趨勢並在趨勢發生變化時記錄局部最小值或局部最大值。 還有兩個額外的細節需要考慮:首先,最初我們沒有趨勢向上或向下,但第一個值是最小值或最大值,因此除了增加或減少之外,我們還有第三種趨勢可能性:早期; 其次,在循環結束后,我們必須添加最后一項作為最小值或最大值,具體取決於我們完成時趨勢的方向。 請注意,如果價格列表為空,它永遠不會添加 null,因為在這種情況下,趨勢永遠不會從早期發生變化。
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Map;
import java.util.List;
public class Partition {
public static void main(String[] args) {
List<String> values = List.of("10.99", "15.99", "19.99", "12.99", "24.99",
"21.99", "17.99", "11.99", "22.99", "29.99", "35.99", "27.99", "20.99");
List<BigDecimal> prices = values.stream().map(BigDecimal::new).toList();
Map<Extrema, List<BigDecimal>> part = new Partition().partitionExtrema(prices);
System.out.format("Minima: %s%n", part.get(Extrema.MINIMA));
System.out.format("Maxima: %s%n", part.get(Extrema.MAXIMA));
}
public Map<Extrema, List<BigDecimal>> partitionExtrema(List<BigDecimal> prices) {
Trend trend = Trend.INCHOATE; // intially we don't know if we're going up or down
List<BigDecimal> maxima = new ArrayList<>();
List<BigDecimal> minima = new ArrayList<>();
BigDecimal previous = null;
for (BigDecimal current : prices) {
int direction = previous == null ? 0 : current.compareTo(previous);
if (direction > 0) {
if (trend != Trend.DECREASING) {
minima.add(previous); // switching from decreasing to increasing
}
trend = Trend.INCREASING;
}
if (direction < 0) {
if (trend != Trend.INCREASING) {
maxima.add(previous); // switching from increasing to decreasing
}
trend = Trend.DECREASING;
}
previous = current;
}
if (trend == trend.INCREASING) {
maxima.add(previous);
} else if (trend == trend.DECREASING) {
minima.add(previous);
}
return Map.of(Extrema.MINIMA, minima, Extrema.MAXIMA, maxima);
}
}
public enum Trend {
INCREASING,
DECREASING,
INCHOATE
}
public enum Extrema {
MAXIMA,
MINIMA
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.