題意
在一條數(shù)軸上,有n個(gè)城市,編號(hào)從0 ~ n – 1 , 約翰打算在這n個(gè)城市做點(diǎn)生意,他對(duì)Armani的一批貨物感興
趣,每個(gè)城市對(duì)于這批貨物都有一個(gè)價(jià)格prices[i]。對(duì)于城市x,約翰可從城市編號(hào)為[x - k, x + k]購(gòu)買(mǎi)貨物,然后
賣(mài)到城市x,問(wèn)約翰在每個(gè)城市最多能賺到多少錢(qián)?
樣例
給出 prices = [1, 3, 2, 1, 5], k = 2,返回 [0, 2, 1, 0, 4]。
解釋?zhuān)?i = 0,約翰可去的城市有0~2因?yàn)?、2號(hào)城市的價(jià)格比0號(hào)城市的價(jià)格高,所以賺不了錢(qián),即 ans[0] = 0。
i = 1,可去的城市有0~3,可以從0號(hào)或者3號(hào)城市購(gòu)買(mǎi)貨物賺取的差價(jià)最大,即ans[1] = 2。
i = 2,可去的城市有0~4,顯然從3號(hào)城市購(gòu)買(mǎi)貨物賺取的差價(jià)最大,即ans[2] = 1。
i = 3,可去的城市有1~4,沒(méi)有其他城市的價(jià)格比3號(hào)城市價(jià)格低,所以賺不了錢(qián),ans[3] = 0。
i = 4,可去的城市有2~4,從3號(hào)城市購(gòu)買(mǎi)貨物賺取的差價(jià)最大,即ans[4] = 4。
給出 prices = [1, 1, 1, 1, 1], k = 1, 返回 [0, 0, 0, 0, 0]。
解釋?zhuān)?所有城市價(jià)格都一樣,所以不能賺到錢(qián),即所有的ans都為0。
1.解題思路
??這是一道非常典型的線(xiàn)段樹(shù)題。之前我也做過(guò)類(lèi)似的題,Java 算法-區(qū)間求和I(線(xiàn)段樹(shù)),其實(shí)原理都是差不多的。重點(diǎn)在于構(gòu)建線(xiàn)段樹(shù),這里構(gòu)造的線(xiàn)段樹(shù),用來(lái)記錄每個(gè)區(qū)域的最小值。在最大的差價(jià)是,我只要在這個(gè)范圍找到最小值,然后求最小值就行了。
2.代碼
public int[] business(int[] A, int k) {
SegmentTreeNode node = build(A, 0, A.length - 1);
int a[] = new int[A.length];
for(int i = 0; i < a.length; i++){
SegmentTreeNode n = node;
int min = Math.max( i -k, 0);
int max = Math.min(i + k, A.length - 1);
a[i] = Math.max( A[i] - query(node, min, max), 0);
}
return a;
}
class SegmentTreeNode {
public int start = 0;
public int end = 0;
public int min = 0;
public SegmentTreeNode left = null;
public SegmentTreeNode right = null;
public SegmentTreeNode(int start, int end, int min) {
this.start = start;
this.end = end;
this.min = min;
}
}
//構(gòu)建線(xiàn)段樹(shù)
private SegmentTreeNode build(int A[], int start, int end) {
SegmentTreeNode node = new SegmentTreeNode(start, end, A[0]);
if (node.start == node.end) {
node.min = A[start];
return node;
}
int mid = (node.start + node.end) / 2;
node.left = build(A, start, mid);
node.right = build(A, mid + 1, end);
node.min = Math.min(node.left.min, node.right.min);
return node;
}
//查詢(xún)線(xiàn)段樹(shù)
private int query(SegmentTreeNode node, int start , int end) {
if(start > end) {
return 0;
}
if(node.start == start && node.end == end) {
return node.min;
}
int mid = (node.start + node.end) / 2;
if(end <= mid) {
return query(node.left, start, end);
}
else if(start > mid) {
return query(node.right, start, end);
}else {
//求最小值
return Math.min(query(node.left, start, mid), query(node.right, mid + 1, end));
}
}