Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
Note: Part of the article content and pictures from the network, if there is infringement please contact me (homepage public number: small siege lion learning front)
By: Little front-end siege lion, home page: little front-end siege lion home page, source: Nuggets
GitHub: P-J27, CSDN: PJ wants to be a front-end siege lion
Copyright belongs to the author. Commercial reprint please contact the author for authorization, non-commercial reprint please indicate the source.
Topic describes
Give you n non-negative integers A1, A2… Each number represents a point in the coordinates (I, ai). Draw n vertical lines in the coordinates, and the two endpoints of vertical line I are (I, AI) and (I, 0). Find the two lines that together with the X-axis will hold the most water.
Note: You cannot tilt the container.
Max ((i-j)*min(a[I],a[j])), I > j.
We find that when a[j]>=a[I], min value is a[I], so the smaller j is, the better. Those js satisfying a[j]>=a[I] can constitute an answer value ANS1, ans1 is not necessarily equal to the final answer. What if a[j]<a[I]? Reverse the array and do it again! Let’s call this ans2, so Max (ans1,ans2) is the answer.
So we just need the smallest j, such that a[j]>=a[I].
Solution 1: line segment tree.
The line tree maintains the interval Max. If the left interval Max >=a[I], the left is recursed, otherwise the right is recursed.
let ls = x= > (x << 1), rs = x= > (x << 1 | 1)
let nd = new Array(200010).fill(0)
function build(x, l, r, a) {
if (l === r) {
nd[x] = a[l - 1]
return
}
let mid = (l + r) >> 1
build(ls(x), l, mid, a)
build(rs(x), mid + 1, r, a)
nd[x] = Math.max(nd[ls(x)], nd[rs(x)])
}
function query(x, l, r, v) {
if (l === r) return l
let mid = (l + r) >> 1
if (nd[ls(x)] >= v) return query(ls(x), l, mid, v)
return query(rs(x), mid + 1, r, v)
}
var maxArea = function(a) {
const n = a.length
let solve = (a) = > {
build(1.1, n, a)
let ans = 0
for (let i = 0; i < n; ++i) {
let idx = query(1.1, n, a[i]) - 1
if (idx > i) continue
ans = Math.max(ans, a[i] * (i - idx))
}
return ans
}
let ans = solve(a)
a.reverse()
ans = Math.max(ans, solve(a))
return ans
};
Copy the code
Solution 2: sort + suffix min
Bind values and subscripts together and sort them in ascending order, or at will if they are the same. Let’s call that b array.
Find the first subscript IDx greater than or equal to A [I], then min(b[IDx ~n-1][1]) (0-indexed) is obtained. Hence the suffix min.
var maxArea = function(a) {
const n = a.length
let lower_bound = (a, x) = > {
let l = 0, r = a.length
while (l < r) {
let mid = (l + r) >> 1
if (a[mid] >= x) r = mid
else l = mid + 1
}
return l
}
let solve = (a) = > {
let b = a.map((v, i) = > [v, i])
b.sort((x, y) = > x[0] ^ y[0]? x[0] - y[0] : x[1] - y[1])
let val = b.map(v= > v[0]), mn = b.map(v= > v[1])
for (let i = n - 2; ~i; --i) mn[i] = Math.min(mn[i], mn[i + 1])
let ans = 0
for (let i = 0; i < n; ++i) {
let idx = lower_bound(val, a[i])
ans = Math.max(ans, a[i] * (i - mn[idx]))
}
return ans
}
let ans = solve(a)
a.reverse()
ans = Math.max(ans, solve(a))
return ans
};
Copy the code
Thank you for reading, I hope to help you, if there is a mistake or infringement of the article, you can leave a message in the comment area or add a public number in my home page to contact me.
Writing is not easy, if you feel good, you can “like” + “comment” thanks for your support ❤