這是我的資料,試圖解決以下難題
#ID Date GroupId Code Days Lift wt
#100 03-01-2020 LM100 500 30 5 kg
#100 03-15-2020 LM100 500 30 3 kg
#100 04-10-2020 LM100 500 20 20 kg
#100 05-15-2020 LM100 500 30 5 kg
想要計算資料中每個 ID 的最長持續時間和最高提升。
讓我們在第一條記錄中說,ID 100 從 3 月 1 日開始,在接下來的 30 天內每天舉重 5 公斤。但在 3 月 15 日,ID100 也開始在接下來的 30 天內舉起 3 公斤。所以從 3 月 15 日到 3 月 30 日,ID 100 每天舉重 8 公斤。所以這就是資料連接的方式。
我想不出為此寫任何邏輯。
任何人都可以為此提出任何想法或邏輯嗎?
Update:
更多關于資料的定義
人從 3 月 1 日開始在接下來的 30 天(即到 3 月 30 日)每天舉重 5 公斤。但從 3 月 15 日開始,他又開始了一項每天舉重 3 公斤的常規訓練,持續了接下來的 30 天(即直到 4 月 14 日)。所以從 3 月 15 日到 3 月 30 日,第 1 和第 2 套路是重疊的,這就是他每天舉重 5 3 = 8 公斤的原因。這就是一個人的資料
uj5u.com熱心網友回復:
由于這似乎是一項學校作業,所以我會有點含糊地讓您弄清楚細節。
定義記錄類來表示您的輸入。添加一個超出您在問題中提到的額外成員欄位:可能的結束日期。通過創建一個LocalDate開始日期的物件來計算這個,然后呼叫plusDays傳遞你的days計數來獲取結束日期。
record LiftSpan ( int participantId, LocalDate start, int days, LocalDate end, int groupId, int code, int lift, String unitOfWeight ) {}
確定整個日期范圍的第一個和最后一個日期。您忽略了在您的問題中準確定義最后日期,因此我將不得不將其留給您來確定。
從第一次約會開始。在整個范圍內回圈每一天。對于該范圍內的每一天,搜索該LiftSpan范圍包含第 n 個日期的物件串列。如果只有一個物件覆寫該日期,則繼續回圈。當您找到多個匹配項時,請記錄從第一個日期到該日期的記錄。用 計算經過的天數ChronoUnit.DAYS。復制重量和代碼的相應欄位。然后用此日期替換您對第一個日期的跟蹤。日復一日地繼續前進,積累更多的LiftSpan物件。超過整個日期范圍時停止回圈。
優化是可能的。如果您對原始物件集進行排序,那么您可以比較它們的日期而無需逐日進行。這種替代方法還消除了重復搜索整個串列的需要。但是對于初學者程式員來說,上面首先描述的方法會更合適。
uj5u.com熱心網友回復:
您可以通過以下方式開始。
主要是你需要在某處計算和存盤聚合結果,這里使用了key-value資料結構。聚合后,根據您的條件獲取結果。
在這種情況下,這只是一個簡單的場景,基于一個人做一些提升模式(幾天有 2 個模式)。結果應該是升力最大的那一天。后者只是根據您的要求進行調整。(每個人的最長天數等)
public class TestLift
{
static List<Record> list = new ArrayList<>();
//default sort by data
static Map<Date, Double> map = new TreeMap<>();
public static void main(String args[])
{
run();
}
public static void run()
{
list.add(new Record(new GregorianCalendar(2022,0,10).getTime(),3,10));
list.add(new Record(new GregorianCalendar(2022,0,12).getTime(),3,20));
for(int i=0;i<list.size();i )
{
//till no. of days
for(int j=0;j<list.get(i).days;j )
{
Date d=list.get(i).date;
Calendar c = new GregorianCalendar();
c.setTime(d);
//add extra days
c.add(Calendar.DATE, j);
d=c.getTime();
//System.out.println(i ":" j "=" d);
if(map.get(d)==null)
{
map.put(d, list.get(i).lift);
}
else
{
//add extra
map.put(d,map.get(d) list.get(i).lift);
}
}
//look over aggregate map and find max lift
for(Date d:map.keySet())
{
System.out.println(map.get(d) " kg at :" d);
}
System.out.println("###after add new record###");
}
Date result = Collections.max(map.entrySet(), Map.Entry.comparingByValue()).getKey();
System.out.println("\nresult=" map.get(result) " kg at :" result );
}
static class Record
{
public Date date;
public int days;
public double lift;
public Record(Date date, int days, double lift)
{
this.date=date;
this.days = days;
this.lift = lift;
}
}
}
輸出
//computing aggregate step by step
10.0 kg at :Mon Jan 10 00:00:00 EET 2022
10.0 kg at :Tue Jan 11 00:00:00 EET 2022
10.0 kg at :Wed Jan 12 00:00:00 EET 2022
###after add new record###
10.0 kg at :Mon Jan 10 00:00:00 EET 2022
10.0 kg at :Tue Jan 11 00:00:00 EET 2022
30.0 kg at :Wed Jan 12 00:00:00 EET 2022
20.0 kg at :Thu Jan 13 00:00:00 EET 2022
20.0 kg at :Fri Jan 14 00:00:00 EET 2022
###after add new record###
result=30.0 kg at :Wed Jan 12 00:00:00 EET 2022
uj5u.com熱心網友回復:
資料中的每一個ID都是完全獨立的。
由于要求計算最大值 ID,因此我將使用從ID到堆的映射Map<Integer, <LocalDate, Integer>PriorityQueue>。這應該是一個最小堆LocalDate,其中一個預先計算Integer兩端的重量變化。也就是說,每個條目添加兩個<LocalDate, Integer>,一個是正權重,后一個是相反的。
當一個人讀完所有的記錄后,對于每一個ID,我們可以計算出最大提升的日期范圍。如果兩個日期范圍的權重相同,則選擇后一個(稍微簡單一些)。我們跟蹤當前最大權重、當前最大日期范圍和當前權重;說,,,,,。max_ start_ 雖然不是空的,但彈出堆會導致, :endcurrentdateweight
- 如果
weight > 0:如果weight current >= max超過,那么start = date,max = current weight。 - 如果
weight < 0:如果weight == max那么end = date。 current = weight
我認為,這將在O(n log n).
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/422802.html
標籤:
