詳細**可以fork下github上leetcode專案,不定期更新。題目摘自leetcode:
思路:該開始使用了for迴圈中加入了stack的結構,但發現這種思路很難逼近答案。正確的思路應該為:
for
**如下:
public listmerge(listintervals) else
}//合併到一半的區間最後需要統一加上
ans.add(new interval(start,end));
return ans;
}
思路:
可以跟著上一題的思路來,類似於插入排序,找到適當的位置,把newintervals插入到指定位置,在它之前的所有區間可以直接add,與它相交的需要更新interval。**如下:
public listinsert(listintervals, interval newinterval)
intervals.add(i, newinterval);
int start = intervals.get(target).start;
int end = intervals.get(target).end;
for (int j = target; j < intervals.size(); j++)else
}ans.add(new interval(start,end));
}
還有一種更聰明的做法,在篩選區間時有一定的技巧。
a. intervals[i].end < newinterval.start 可以直接排除
b. intervals[i].start > newinterval.end 可以直接排除
中間區間的更新都是與newinterval有交集,所以更新:
交集中的最小start和交集中的最大end即可
**如下:
public listinsert(listintervals, interval newinterval)
ans.add(newinterval);
while (i < intervals.size()) ans.add(intervals.get(i++));
return ans;
}
一種樸素的做法,時間複雜度為o(
nlogn)
,可以參考summary range的思路。
思路:
不管三七二十一,把資料全部新增到set集合中來(沒有維護大小關係),惰性做法,當要返回區間時,開始計算,對nums進行排序,連續的值可以合併成乙個區間。
**如下:
public
class
summaryranges
public
void
addnum(int val)
public listgetintervals()
listans = new arraylist<>();
for (int i = 0; i < num.length; i++)
return ans;
}}
這種做法相當糟糕,在加入val時,並沒有維護它的順序,導致每當getintervals為了更好的合併都需要排序一次,這題還可以參考第二題的思路,每當加入乙個元素時,不斷維護該list。時間複雜度可以降到o(
n)。**如下:
public
class
summaryranges
public
void
addnum(int val)
int i = 0;
while (i < ans.size() && newinterval.start > ans.get(i).end + 1) tmp.add(ans.get(i++));
while (i < ans.size() && newinterval.end + 1 >= ans.get(i).start)
tmp.add(newinterval);
while (i < ans.size()) tmp.add(ans.get(i++));
ans = tmp;
}public listgetintervals()
public
static
void
main(string args)
}
上述**的複雜度為o(
n),主要原因在於查詢操作中,需要遍歷ans list,找到合適的兩個斷點,才進行區間更新。
換句話說,我們完全可以在乙個有序的list中進行二分查詢,只需要找到符合:
a. ans.get(i).end + 1 >= newinterval.start
b. ans.get(i).start <= newinterval.end + 1
條件a的查詢很簡單,二分查詢有序list中的end,就能找到待插入的位置i
條件b的查詢可以轉換成:
ans.get(i).start > newinterval.end + 1
因此,也可以二分查詢有序list中的start,能找到終止位置i
但上述**使用了arraylist,實施二分查詢較複雜,但至少給了我們乙個o(log n)的思路。
支援二分查詢,且同時支援o(log n)的插入的資料結構還有tree,所以我們可以實現乙個bst,來做查詢和插入的操作。
如何表達val 和 區間的關係?
treemap這種資料結構能夠完美表達。
構建思路:
就一條,遇到合併的情況,把區間start高的,合併到start低的區間上。
如:[1,1],[2,2] -> [1,2] (刪除第二個區間,修改第乙個區間的end)
**如下:
treemaptree;
public
summaryranges()
public
void
addnum(int val)
else
if (h != null && val == h - 1)
else
if (l != null && tree.get(l).end + 1 >= val)
else
}
查詢,刪除,插入的時間複雜度均為o(
logn
) ,完美的結構。
演算法5 7 區間檢索
間隔搜尋問題給出了一系列的範圍,而測試的時間間隔,尋找和測試間隔交叉間隔。為了解決問題,須要專門編寫乙個類,這個類的介面例如以下 public inte ce intervalst,value 每乙個節點中有兩個值。第乙個值是區間的起點和終點,第二個值是該節點以及子節點中最大的區間終點。為了簡化問題...
7620 區間合併
7620 區間合併 總時間限制 1000ms 記憶體限制 65536kb 描述 給定 n 個閉區間 ai bi 其中i 1,2,n。任意兩個相鄰或相交的閉區間可以合併為乙個閉區間。例如,1 2 和 2 3 可以合併為 1 3 1 3 和 2 4 可以合併為 1 4 但是 1 2 和 3 4 不可以合...
4975 區間翻轉
小q和tangjz正在乙個長度為n的序列a 1,a 2,a n上玩乙個有趣的關於區間翻轉的遊戲。小q和tangjz輪流行動 小q先手。每次行動方玩家需要選擇乙個長度為4x 2或4x 3的區間 l,r 1 l r n 其中x是該玩家自行選擇 的非負整數,然後將a l,a a a r翻轉,例如1 3 2...