No.1 人口最多的年份9 n& n5 g$ r4 i' @) w
) w3 l1 f% u9 J5 E8 h4 }8 `
解题思路) l5 o- u2 ]5 z* v3 a& [, E
3 C/ a6 G/ c7 @+ s9 h数据范围比较小,直接枚举统计即可。4 B8 f0 [1 t0 s! \* D5 X% t& l+ G
$ `# P& T2 s/ k( c0 g9 }% I7 j
代码展示; K; g2 k, d; w8 q+ h# }6 i
- ) Q+ Q4 ?: j0 V) f- o1 }0 n7 K
- class Solution {+ P6 X& i' M0 t& o9 y! j
- public int maximumPopulation(int[][] logs) {
: r8 B9 u/ m, Q1 z# } - int[] population = new int[2051];
# A/ {! A1 p' C) j' ~$ V - for (var log : logs) {* E ~- [5 h- w) u
- for (int i = log[0]; i < log[1]; i++) {7 `1 N4 q' @7 z9 Y& e
- population++;
# k4 C( Y& y/ [: C9 Z1 d5 l7 ?: t, l - }
! k. ~6 ~9 u1 J8 F2 D% ^ - }
R$ P: o! W2 _3 E8 Y3 Y3 y - int res = 1950;1 R' a" V7 r: ]# @
- for (int i = 1951; i <= 2050; i++) {& B2 A/ W9 s- \- ]
- if (population > population[res]) {
0 y& }, E8 x. M# f( G+ l Y; l( A - res = i;
% o5 t g$ C2 I( A& s5 _/ C9 H7 E2 E - }
0 P: `' l$ p g! F$ D; G - }" ?" w T. }* j, ?0 }4 q& c
- return res;
- K+ J( V. a* @# w6 [+ n - }) [# {0 t3 o: e1 q2 Y
- }
复制代码
. i/ C; H, d9 D- k8 f6 p# {4 O7 F# |' v
No.2下标对中的最大距离
2 A0 V( L" Q p8 j+ V
( `1 l% x/ T1 s& |解题思路
8 y0 W& r' \* M! I4 B
# c% R7 w; y% \2 o9 {6 w输入的两个数组都是单调的,可以使用双指针。* W3 ?5 p' ^- b! I. ]+ x
# d" _, k5 D' U- A' w& z# C( `5 Z
代码展示5 \0 V9 d% Q; E- B3 C' R/ \
, z( P1 m0 {4 b4 X* d
- class Solution {6 Y) g/ [8 `/ i$ x- @3 s. U
- public int maxDistance(int[] nums1, int[] nums2) {2 C, Q* r/ U+ k1 n2 a
- int n = nums1.length, m = nums2.length;
G9 L, A7 n$ g' F5 B# G; T - int res = 0;
4 `$ w4 }+ w) E( ^6 Y9 B9 R* A - for (int i = 0, j = -1; i < n; i++) {
9 G d! s' ?. O3 U - while (j + 1 < m && nums1 <= nums2[j + 1]) {
, e+ i: V: F, Z4 l - j++;
% W( P6 Z$ y% o4 ]7 R/ @9 i7 S - }
, F8 l8 c& n; i; y% ] - res = Math.max(res, j - i);' ], o3 D/ P* |! P% l9 y' d
- }
, [, q H) d2 I8 a- a - return res;0 J$ J& h. | [' ^& ~, S5 W
- }
3 i, P# j9 V; r/ g( W/ V, @" n p6 b - }
复制代码 + K3 M4 j7 ]% U
No.3 子数组最小乘积的最大值
; j* u" Y" Q6 z: i: f0 |$ R" m: X) C% Q- X, t! E# b7 t
解题思路
5 t; [/ G7 N' o8 }# t8 C0 P/ j2 `1 ]6 v, `' Z
单调栈的变形,可以先去做一下最大矩形回顾一下单调栈。' G: a2 l. y9 R, W) c- |( D
. [/ ^( |2 K8 O8 H" L- `1 @
当子数组的最小值确定时,肯定是数组越长越好,所以我们需要知道每个元素左右第一个比它小的元素的位置,以在枚举每个元素作为子数组最小值时,这个子数组最大可以是多大。! w- |( A, J8 u: x2 K2 O
. E" }8 U% W6 }6 r. F; K/ z% l
代码展示 s) W% G9 X% g _7 V! l
3 M& \4 [' L# K: K1 i
- class Solution {0 [' G' H# |5 g+ _! h: `
- public int maxSumMinProduct(int[] nums) {
: T, ^0 E7 W( Z- X# F/ T - int n = nums.length;. s3 p; [9 M# V- j/ _7 K
- long[] preSum = new long[n + 1];
0 b. }4 {$ O3 f7 g' {" `, O - for (int i = 1; i <= n; ++i) {
$ {, h& K- c$ L- S9 q3 q - preSum = preSum[i - 1] + nums[i - 1];
* s: Q! Z7 J2 T: u' p( F/ B2 _ - }
4 V( e0 ~& Z! u" G - ! k* V, C$ r: @% I
- int[] l = new int[n];1 h; {( }( B1 M& x, L& V
- int[] r = new int[n];; Q* R9 n0 ]) R5 ?
- Arrays.fill(r, n - 1);, u" m4 N$ o ~: {
" E% w1 k. e! h. K0 t- LinkedList<Integer> stack = new LinkedList<>();
0 @. Q6 _( S3 c0 }: B7 Y3 d - for (int i = 0; i < n; i++) {
8 W/ B! {6 u1 R& R$ V7 S d# j - while (!stack.isEmpty() && nums[stack.peekFirst()] > nums) {
% p ?( C) M# ?1 Q- E/ V# w* I - r[stack.pollFirst()] = i - 1;0 v, C! X8 M% J/ e) X
- }
5 l) U4 ]/ N! a: z; W0 p7 `& G - stack.addFirst(i);
% L0 u j q& g7 _ - }7 b0 F R, ]$ \
- stack = new LinkedList<>();
7 V, q, u1 ?/ F% [1 O - for (int i = n - 1; i >= 0; i--) {
% u U$ F* X' |! N1 c - while (!stack.isEmpty() && nums[stack.peekFirst()] > nums) {
+ G% L3 H1 u* g8 U+ `2 d* j$ b - l[stack.pollFirst()] = i + 1;
! p2 v' @7 [( [5 A! ^ - }
; }* y1 e# D2 [$ {0 J2 W - stack.addFirst(i);1 K2 O* Y5 g( `! @7 E: J4 O
- }! m- I, y% \8 _" w# c# f5 x( V
- ( g2 D/ ?0 ]& s" g
- long res = 0;
5 N( n/ ^" c% C; o! }+ m8 d - for (int i = 0; i < n; i++) {
4 R& [, h- P$ ~9 m3 R# N; v5 M - res = Math.max(res, (preSum[r + 1] - preSum[l]) * nums);
& L) ~$ w& [ F) R7 S - }
2 s2 ]; i4 |( A4 ]+ o8 `
# u5 P5 H% u* y- return (int) (res % 1000000007L);* B7 V% T% l+ l: n) x" p
- }. I' I. C- v9 {( l U. s0 x+ ?8 o
- }
复制代码
2 o2 @8 m0 D1 W8 f. X/ h/ I. V$ |& ONo.4 有向图中最大颜色值
* I0 D3 X2 r+ j H b; B7 |+ e. q* m, `
解题思路' P# `) Y; W7 g6 q4 v
! ]4 _' Z% u: C# ?9 G d先判断图中是否有环,有环直接返回 -1.) R# j( t! Q0 M( \
; E9 } b. R( l) W" Y& E
无环的话则使用动态规划求解。
+ R9 I, ?$ b! r' q3 M2 Q
/ l1 ^; B+ N9 T; i: B$ M* s' d代码展示
: M2 i4 Z- E6 ~( b+ V4 I' Q, n0 l: h
- class Solution {1 z- g" e" c7 Q% @8 {
- public int largestPathValue(String colors, int[][] edges) {8 q6 C6 Y9 K% S j
- // 建图3 s% w s0 \2 ?2 h
- int n = colors.length();: u7 {6 A" l8 t# `2 b2 k
- Node[] nodes = new Node[n];! t9 O+ A7 j& @$ f
- for (int i = 0; i < n; i++) {% S" T/ `0 K% t( U3 X3 `; i* G# b
- nodes = new Node();
* G/ S& _% i/ M/ O# i& v" a - }# t4 T+ K# t, R4 P; [
- for (int[] e : edges) {+ h8 d. o( A7 O) B* I+ }7 ]1 B) Z
- nodes[e[0]].nei.add(nodes[e[1]]);
) j* |" n/ \ v: g. j; h - }
& }' H1 ]1 A* h) k - // 判环
( {1 f _& ^* t( d, h1 v - for (Node node : nodes) {
: V) u2 g; x. z1 W; W- Z0 v - if (findCircle(node)) {6 }( X) h. g5 R4 ?
- return -1;
3 P1 R+ P" j" Y8 x/ {2 i$ ?6 D' b1 v - }
8 f% y3 t0 T* O8 R$ S0 o) n - }
1 |/ O; @2 s$ Y7 R. u3 j - // 动态规划
, \; l* _ C; y5 y% b' A - int best = 0;$ \8 v: J# r9 ?) Q) _' r3 G% _
- for (int i = 'a'; i <= 'z'; i++) {
/ o- Q J$ g; d7 G2 k - for (int j = 0; j < n; j++) { x' P. s( V8 [# Q6 r
- nodes[j].dp = -1; K8 ^' \ [9 b) V2 I+ _
- nodes[j].val = colors.charAt(j) == i ? 1 : 0;, r" l& h! b. u+ n) z( M- x' M
- }& F5 _& q. ]- f/ ]9 h# D( t
- for (int j = 0; j < n; j++) {
$ l# B' f. H) \% p - best = Math.max(best, dp(nodes[j]));# {3 F& J: E+ m8 b1 H
- }
$ L7 B9 \0 A3 _8 B4 s9 M - }* m# X) Q# ?( g. u# s- q8 h. p- a
- return best;0 O' }9 G( f" E, s! g4 k% |
- }' S. W# ]! L$ }9 X
3 m9 S( L/ L, h. W8 ]6 _( F: d# `- public int dp(Node cur) {" g1 }& `6 J8 n( J6 f; H0 i
- if (cur.dp == -1) {8 A2 k# t7 T6 W1 F1 x. a
- cur.dp = 0;
% b9 i# X, L4 R s - for (Node node : cur.nei) {
! t% Y l% Q9 k( {+ R1 o3 T1 _ - cur.dp = Math.max(cur.dp, dp(node)); l4 i0 H3 m4 g% F3 F9 L
- }
( L; i) ~ O4 S+ l! S - cur.dp += cur.val;
: L0 B: E& }& V" q/ W - }
" x* @2 X; T6 _5 W K: o8 B- i - return cur.dp;
7 B/ N( {: L K! M/ {+ m - }6 a4 ~) J/ f- E
- 1 I0 h" N, F8 O* u
- // 精简版的 Tarjan 算法:( ~ p3 l' w' Q' X. z
- // 仅用作判环,而无需求出强连通分量
$ a m1 z) Q5 _ - // 所以并不需要真正使用栈,只需要一个标志位即可# Y7 O1 I5 W# |$ ?- a
- boolean findCircle(Node cur) {
% x# T7 W$ {2 i/ \2 ^ U - if (cur.vis) {; x& z7 Z, m8 H7 b* o
- return cur.stk;! O! D0 D7 w; d2 q2 V9 k$ @
- }5 h9 J6 _1 q p: p
- cur.vis = cur.stk = true;
, h- F9 b, h/ j - for (Node node : cur.nei) {
5 { O: C7 g$ ~ ` M - if (findCircle(node)) {# \: L. M% R3 P% ?% E+ ~+ E
- return true;1 |$ k! I% [* o# l
- }( Z. O5 K- N A3 B1 J
- }, D- ?3 b' J* a
- cur.stk = false;7 f! B4 M! v2 a& S/ ?3 K% e7 t$ d
- return false;5 q! D" z+ p: `7 `. z- P7 ~
- }$ O2 g. v1 O4 O" B8 D
- }
9 x% A. |8 e/ @
+ p/ W! `6 U# g; E& f- class Node {
. T% Y8 {9 \( }( q- X% m8 V" X - int val, dp;, E$ p# `" ?: b" n
- boolean vis, stk;
8 k+ t5 a% |5 q3 v% ~9 N - List<Node> nei;! `' O8 v( U( V' q3 J
- / m' V6 j6 v. k) `8 A
- Node() {
7 z+ z6 u5 T/ I& n$ O, c3 P* X - dp = -1;
. S' V& s9 S- v - nei = new ArrayList<>();9 o1 n7 X9 l8 [* j$ G; L
- }4 G3 N: E" P0 ~$ p7 \- d
- }
复制代码
# G9 k9 x" F L2 j% K( M
9 ?. v. h I5 F& z |