No.1 人口最多的年份& r# h& A y9 [) b9 Q
2 D* t* C+ B5 Z$ p8 r
解题思路
, ^, u+ H4 i$ ~; i5 a6 o$ M& i: L( R' }8 w! z% \7 s) B6 c$ [
数据范围比较小,直接枚举统计即可。. u+ i! ` t' I0 H' g6 H: w
: d. j6 B, S# M: X2 Y4 U
代码展示9 c$ q$ y) R4 d! f5 B
- 6 O6 m: e* k* ]) q2 W! y
- class Solution {
w/ T+ X: o* h4 a ~: f* h - public int maximumPopulation(int[][] logs) {
* w* q' ?8 F( \8 ~ - int[] population = new int[2051];
* d, A: a* E# w4 ^ - for (var log : logs) {
) X8 w& ~6 s3 U/ k% f* | - for (int i = log[0]; i < log[1]; i++) {% o8 z- G; x9 c' m( D, Z
- population++;
/ B- w( E' M1 |+ O4 C$ Z, G - }; I; w: V, j9 K n8 l
- }. ?8 ` E9 Q+ ~, H
- int res = 1950;
3 L) Q ]- G$ G/ H" w7 e/ M p - for (int i = 1951; i <= 2050; i++) {
/ J/ |& u' I5 P& \0 }3 f' I- a* W - if (population > population[res]) {. X; I* w. O# i# U% E6 f! n
- res = i;
7 a' J$ A l9 h" ` - }; @- J; `7 N0 d2 q; _+ y4 _
- }# ~- J, M1 h( E
- return res;6 a5 i$ J8 O% j! z( x+ o: m* O- }! j
- }
9 P9 r* l' V" y; [6 }. s - }
复制代码 ; @% ?, g8 r! w
. }. v; i" J& b) ^ X; fNo.2下标对中的最大距离
, m0 b# G; [# @7 ?9 F
4 `% E0 [7 b; }解题思路
& A- ]9 f0 S: P* D ?1 d1 W& ?8 ^4 ~% w
输入的两个数组都是单调的,可以使用双指针。5 F5 Z! O5 ^4 t
% q: Y/ O* t6 `) ~: n3 Q( U2 c3 v代码展示3 z; M& _: W* Z8 a6 Q
* M- d1 G' p3 o+ |
- class Solution {7 n; t: G0 h- x2 T! E
- public int maxDistance(int[] nums1, int[] nums2) {
% j6 \1 J. I+ C! H: [2 F, w - int n = nums1.length, m = nums2.length;
. @2 b$ ]9 p2 G# ^ R - int res = 0;
" n" T- R! T3 m$ A6 i0 ?1 h - for (int i = 0, j = -1; i < n; i++) {5 W& `# j9 O) b" A# {4 [
- while (j + 1 < m && nums1 <= nums2[j + 1]) {
& m8 P# A$ M6 x' v0 o4 m - j++;
7 a: x& r- d" N; E - }6 Y$ M0 }* I! H! l) V1 O5 q
- res = Math.max(res, j - i);
6 p% d' `. i7 y3 {7 ], I9 @$ g - }' |5 g$ {% S( W
- return res;
( |9 ?& g% h0 [. s - }* N4 C f( @# ]0 `
- }
复制代码 ! r4 L% {( @8 U+ W/ d7 X( Q
No.3 子数组最小乘积的最大值6 o4 b7 B8 k; k* x
% R; e& s( T" r0 r解题思路
0 M( \/ R1 G! }" c9 \" j1 O' v2 x2 b( c6 n1 O, P) z5 w
单调栈的变形,可以先去做一下最大矩形回顾一下单调栈。5 `" s2 b) V6 [* W0 X7 B9 i! j
7 M( t* v5 E0 o当子数组的最小值确定时,肯定是数组越长越好,所以我们需要知道每个元素左右第一个比它小的元素的位置,以在枚举每个元素作为子数组最小值时,这个子数组最大可以是多大。
! G z( {( I# F2 p1 [
& ? w- j- a- b: V代码展示
Q: q9 E! u/ U B! j1 U4 f) }0 W* ~4 b: R9 a. v; Z
- class Solution {
: H: p( Y1 @, i, E3 i - public int maxSumMinProduct(int[] nums) {
: v9 S8 u& @+ f% }: p& c - int n = nums.length;
! H4 x+ }7 b( _$ w - long[] preSum = new long[n + 1];
0 K8 z/ j5 E d: H, O6 P* Y H8 e - for (int i = 1; i <= n; ++i) {4 Z: x4 ^' J3 H P6 B
- preSum = preSum[i - 1] + nums[i - 1];
! @0 a2 {4 ?/ k, n6 B6 `! H3 W" R& p - }( x2 I$ r4 Z) U4 j% I" M# ?
- / }! g; K) ?: F2 m
- int[] l = new int[n];. A5 r; K8 U: I
- int[] r = new int[n];
* F1 j m2 ^% V) k7 z0 Y - Arrays.fill(r, n - 1);
5 q8 u) ^" o& d' A) q6 c1 p4 U
( B1 q/ T3 N1 B% `- LinkedList<Integer> stack = new LinkedList<>();
/ {7 h/ @! k3 a/ D3 F - for (int i = 0; i < n; i++) {; v' P, T; f. K" [5 s- C5 o
- while (!stack.isEmpty() && nums[stack.peekFirst()] > nums) {
; [* Y5 i6 p4 q1 Q' y3 | - r[stack.pollFirst()] = i - 1;4 G6 Q) V/ C9 E
- }( K9 i, L# l, B0 Q0 F/ K# q
- stack.addFirst(i);
9 p" s% g: x" Z6 Q X6 g% ] - }/ H4 g3 z$ _# ^' y$ ?
- stack = new LinkedList<>();4 M; v: j/ ~2 L; ?
- for (int i = n - 1; i >= 0; i--) {# W% Y; J* O0 G3 k& f- p# H
- while (!stack.isEmpty() && nums[stack.peekFirst()] > nums) {/ ^( s P; e' t7 T3 G1 t6 k
- l[stack.pollFirst()] = i + 1;7 b1 D* ~- G3 w, r
- }# B! u' d K( Z9 W3 Y- A# X/ V
- stack.addFirst(i);: [& L& m; f9 I3 Y# T
- }
3 x f' n" \6 |
( a2 E. t+ D' D3 o0 h- long res = 0;4 K* y. h; X" P3 p5 c1 D& j7 L
- for (int i = 0; i < n; i++) {* c+ ]: r" z! Y% N! |$ o
- res = Math.max(res, (preSum[r + 1] - preSum[l]) * nums);
# T9 S- ^$ K/ ]& p6 m3 b& O; w1 \) B - }
9 r+ @# V: m9 _5 e - * K4 a" b( H( s; b
- return (int) (res % 1000000007L);7 W- N, q2 D! Y( P/ m8 O( S
- }
5 o" x. c& D5 Y' E8 m8 {/ b1 q$ j - }
复制代码 - O. Q! ^2 o' l- h. [' c5 I/ X. s
No.4 有向图中最大颜色值
9 i$ d S* a( ?2 }3 ?. ?; v* J/ s2 G
; _4 x# x8 {5 S) k' y2 k8 @解题思路
?* e# C" _* D* P$ k$ u9 H# V- A: m3 z2 A" f
先判断图中是否有环,有环直接返回 -1.
8 G2 p, Y$ M$ F! e( ?2 \3 g: s2 a: Y& p! i/ d# k' X" x2 F+ X/ B
无环的话则使用动态规划求解。
$ x: t% Y2 _' M2 M+ f; v$ z
0 [7 ]8 E# B: L0 R/ b4 p代码展示4 n9 f# m. I7 M# `; S* [
! j- L7 Z! x5 X- class Solution {( R9 P6 C# a' \$ |* K5 |
- public int largestPathValue(String colors, int[][] edges) {
% @! e3 s0 w: Q; e - // 建图5 V2 q% v( A( I. W
- int n = colors.length();
+ O) K) \( h# R9 p* u+ l2 T k0 X4 l - Node[] nodes = new Node[n];& I0 C+ a/ _9 K( U# i
- for (int i = 0; i < n; i++) {, ~$ O$ F- d0 x2 w5 b
- nodes = new Node();3 L" ]* j0 l0 S. A5 I( c
- }
" u' n/ g. ^- g" Y/ R. q, H - for (int[] e : edges) {
8 C1 l8 K) z% g, w4 }* p - nodes[e[0]].nei.add(nodes[e[1]]);: L+ M# U; ^+ |# q" a1 b
- }
0 y2 [' g& \4 D' r - // 判环/ {% \& l7 {. S% L5 \0 s
- for (Node node : nodes) {
' e# ?4 A6 V5 ]7 I8 A6 k - if (findCircle(node)) {
& n6 Z- A, p/ D* ^7 x/ N8 P - return -1;
! y9 H8 d. `9 Q. N2 a - }0 J1 \! a6 c3 |, D" e) @
- }
6 @0 a& u7 N1 L" Q& c) z5 c, D- O$ K - // 动态规划2 I. L9 d# g% y' w/ {) l# s
- int best = 0;
" b; k% G8 h7 h - for (int i = 'a'; i <= 'z'; i++) {
* q2 X6 {4 Y" c6 d - for (int j = 0; j < n; j++) {# {+ B4 e, |6 H& ]2 s9 G$ ^& W
- nodes[j].dp = -1;
) l& E6 i' P ~; i# F; e( R - nodes[j].val = colors.charAt(j) == i ? 1 : 0;
5 ]! Z2 @0 {/ n' v: G4 y- D - }9 ?8 |- B7 k! H, @* @9 [0 [
- for (int j = 0; j < n; j++) {. t. ^; X4 H$ W! b4 W; U
- best = Math.max(best, dp(nodes[j])); w- ]# k* i5 X m$ j+ Q
- }4 K/ ?; e% A' Q Q( D2 d+ I
- }; W. B4 @+ h+ }0 z z; i2 Y
- return best;
8 f( _1 @5 m$ R, e5 E# } - }
M1 b/ N- a* p- K; h( @0 K
+ s H V2 _, k% X7 B4 W* k- public int dp(Node cur) {2 G2 h. \- |4 n. ~4 F( \
- if (cur.dp == -1) {
, m1 o& D- ?+ O8 K - cur.dp = 0;
* h1 e+ Z" H9 O3 }$ v& f& u - for (Node node : cur.nei) { `, D5 m; D# y4 d# `# @; ^
- cur.dp = Math.max(cur.dp, dp(node));
$ X% F+ [2 X. }" l/ M# r - }9 Z4 i( F' X* ?5 M7 S) i1 }# v! V w5 _
- cur.dp += cur.val;
5 v$ d5 L7 o7 Z/ J8 s) |9 P& q; G3 I - }
7 z) _6 {( E1 U9 @ - return cur.dp;# H) B' {* H4 Q' l. Z+ |9 h' `' P& D
- }, Y6 X0 c ~/ r- }% H
- , i, O% {6 Z: P$ {1 `+ C
- // 精简版的 Tarjan 算法:
; u7 ^$ s/ m* n$ {! C- l - // 仅用作判环,而无需求出强连通分量3 s1 [) }) p% M7 P/ a# Z
- // 所以并不需要真正使用栈,只需要一个标志位即可
. J# o# x2 w2 i - boolean findCircle(Node cur) {
. c- g& B E& g8 v+ B8 V% s - if (cur.vis) {
9 ?8 y! Q7 r% T! e1 } - return cur.stk;
2 G- e( ~9 m ^: j" q - }
& E& L% L* |, z- w. Z# t - cur.vis = cur.stk = true;
]3 H& O% @1 k0 U5 p3 K5 `# O, @ - for (Node node : cur.nei) {. @( I# `2 f# I( w& N
- if (findCircle(node)) {
: o. b# E: v% M0 P: \# D! t - return true;
" Y5 n8 ^" W$ a8 G1 W5 @ - }5 \4 i$ W5 F+ k. m+ h" r2 D
- }; |& |- ^$ [ ?8 W) D( E
- cur.stk = false;+ M, U5 w; E% o' e+ I, t
- return false;
- }9 X }+ @9 }% L - }
5 D: a5 C& j1 A" ~ - }0 X9 ^- P& M: A8 Q. }6 n8 H, _
4 y. Z* R6 f/ d& N- class Node {! d4 b- f6 [. e' _' d6 u
- int val, dp;/ I% s5 i% I: p8 d$ _* J& G( L
- boolean vis, stk;
4 J9 |/ o* V& k0 j - List<Node> nei;
7 y! j# ~1 s, w6 [3 }3 F1 _1 Z% e - 0 u; E2 ~4 S3 @
- Node() {7 Y& Y$ {$ v. f; x7 l5 S
- dp = -1;, ~( Y5 o/ {9 f a) d, h; h$ f
- nei = new ArrayList<>();6 Y- C/ f; y' b/ C
- }
7 {: b& U6 a( T- l! a) z - }
复制代码 - Z6 _( Q/ L" S, j
7 [# I/ |5 N# V$ H+ i* d" W |