找回密码
 注册账号
置顶:如何加入2024届新生微信群

[吹水聊天] 上岸算法LeetCode Weekly Contest 262解题报告

上岸算法 回复:0 | 查看:3117 | 发表于 2021-10-10 21:06:08 |阅读模式 |复制链接

UWCSSA提醒您:

警惕网络诈骗与盗号,不要在他人发送的网站中输入密码,换汇或付款时请小心诈骗。

为了避免个人信息泄漏,建议在帖子中使用不常用的邮箱,或使用私信发送联系方式(点击对方的头像,然后“发送消息”)。

帖子通过审核只代表内容不违规,CSSA 不会验证内容的真实性。请谨防诈骗。

登录后可回复主题

您需要 登录 才可以下载或查看,没有帐号?注册账号

x
【 NO.1 至少在两个数组中出现的值】. c0 [, p, }% Q) ]/ h6 `
+ n. E5 n4 u# z) `! `- B: e
解题思路
& s0 G1 H! \- p4 a9 _- _. r( ?签到题。, K. S: |: u" s$ e- p5 r: g# v3 c

6 |1 u/ s) s$ G! w; ?+ ]代码展示
5 y, L( V! _0 h7 \3 Q7 Y
5 H; L- @$ v+ Bclass Solution {! K$ q; @/ c, P' s, w
   public List<Integer> twoOutOfThree(int[] nums1, int[] nums2, int[] nums3) {
! ^; M0 P( X& F5 p  c6 }4 m2 G: I       int[] count1 = new int[200];
7 d( m- H. K, X7 `4 R       int[] count2 = new int[200];
4 V9 V& P2 C7 u' J. ~; V8 c8 o       int[] count3 = new int[200];
7 M  r! u7 H: G' t5 l       for (int n : nums1) {
( _* b* f0 W2 i/ f3 [/ a           count1[n] = 1;
& G% I2 J- Z! Y      }8 _' i, q. b" Q- O
       for (int n : nums2) {/ U8 K& T& E. V, V
           count2[n] = 1;9 X* Y% y! N( J) u5 ]: v  [
      }
6 L9 v9 t: R, \$ E+ i3 U; _       for (int n : nums3) {
" o% J0 y# r2 h: R4 t           count3[n] = 1;
0 i9 O. k- f3 p3 d- l& s1 m      }9 z9 w6 D4 {' M& q6 e% I3 R
       List<Integer> result = new ArrayList<>();) q/ Y  k6 s) Z* q" x4 Z
       for (int i = 0; i < 200; i++) {
& H7 d2 e+ j! Z6 r- ~! i           if (count1[i] + count2[i] + count3[i] >= 2) {( N- ~& u. m+ U- h# ?1 m8 Y3 r, Z" H+ K
               result.add(i);+ _" M; Q4 g4 R/ q$ H0 \5 h
          }% ]) A* n% C6 m! Z7 I4 u
      }
8 `8 Y- D, o& m8 N       return result;
# ?" y6 s: j- o- G5 U/ N  }5 [2 u2 ~5 d7 _
}
& ], z- F. L* ^# K# r5 a; w9 X% B1 N
【 NO.2 获取单值网格的最小操作数】8 ^5 V; I3 g5 Q# b
0 @  K, Q5 V% O  P
解题思路
* h2 k. [1 |1 r( G; _网格可以转换成一维数组,然后排序。9 d  \& `+ g. \+ u4 @

; |) Q/ l2 C9 W1 ]5 w不返回 -1 的条件就是:任意两个元素的差都是 x 的整倍数,我们只需要检查相邻元素即可。5 i; p8 t) ^% k* F4 N& \& E2 }' e( T
; z& _+ Y5 s6 J5 Q2 R
然后枚举最终的唯一值,可以利用前缀、后缀和快速计算出把所有数字变成该值的操作次数。
2 q- o) l0 \6 c1 v# J4 f& z
0 n; E( |4 f% U5 [* z# Q# k代码展示0 U- v% M/ U+ M, q' N* H7 ]

" H' ^! T/ }) P" I8 j8 t% Bclass Solution {
) O" f6 r( P' k- ]4 R   public int minOperations(int[][] grid, int x) {" E# t( I( k+ w* q5 I0 T" q
       int[] arr = new int[grid.length * grid[0].length];- f+ @% p* O& Z
       for (int i = 0; i < grid.length; i++) {
5 I( p( Y' x" `# w. ]           for (int j = 0; j < grid[0].length; j++) {
1 O. D( o% \6 b# d( Y               arr[i * grid[0].length + j] = grid[i][j];$ y+ p, m5 B) R- J5 P5 J
          }2 u3 G8 w0 v0 ~1 u2 _* [+ D" b
      }; V8 J, P  Z8 ]2 L
       Arrays.sort(arr);  Y/ V; V" b3 A) H
       for (int i = 1; i < arr.length; i++) {
2 @- N! @. ~0 m5 O4 B+ t           if ((arr[i] - arr[i - 1]) % x != 0) {$ R7 M; m6 ]% c4 P8 N# J& r$ C
               return -1;
) c7 z7 E: D% b3 d' ^          }( ~& d' Q+ _! D1 g- Y3 f
      }- G' P- b7 F7 r# O" v( A
       int suffixSum = Arrays.stream(arr).sum();, W: V4 o  y9 @
       int prefixSum = 0;- |7 ?1 t( D  i& K& K% Q
       int result = suffixSum / x;
& v$ a: s% c* c5 ^1 f% z( K2 X       for (int i = 0; i < arr.length; i++) {' U4 b  L8 k( A, B; r/ p  G3 t2 F
           suffixSum -= arr[i];9 `2 T" e: E# g2 h& ^& e0 f$ O
           result = Math.min(result, calc(prefixSum, suffixSum, i, arr.length - i - 1, arr[i], x));, s% Q7 [$ v2 Q# B; }, g1 g: T' m
           prefixSum += arr[i];
; M& H/ e6 m$ }" h; y  l! y9 S' W" ^      }2 W+ m5 M; A- g8 E9 }
       return result;
, E( X) @) q( U; m9 E; p  }+ G& F& U: ]  b& U' L
4 K# N% Q6 i) p
   private int calc(int prefixSum, int suffixSum, int prefixNum, int suffixNum, int target, int step) {
5 }% p2 t) Y8 w& G9 O       return (prefixNum * target - prefixSum) / step + (suffixSum - suffixNum * target) / step;
7 \# m/ G2 ^. Q- U/ w- q& k- h% l  }
  L! G. r9 g1 J}
6 ?2 H2 o! D& N5 }' [8 c2 [& k. E5 k# F$ ^- f
【 NO.3 股票价格波动】
  M; J7 k. g. h! ]( J  Q: y4 Z
9 S, y( [) C0 g8 k* t; x0 ~解题思路  H  ?' f& J. H' E# X
使用两个 TreeMap 即可,一个储存时间戳到价格的映射,一个储存价格出现了多少次。) e3 j  c! Q; [9 }' ~
  i- k7 ^7 N  z2 o( x2 E5 {4 E
代码展示2 o9 |) C+ y4 n/ [0 ]+ Q, D6 S' A
  j9 X2 C2 L4 ?6 A/ V
class StockPrice {
: X* f+ ^+ ?1 B. Q, V% @
5 H9 X5 m0 O8 t   TreeMap<Integer, Integer> timestampToPrice;0 R1 Q9 p) s: U. P& ]
   TreeMap<Integer, Integer> priceCount;2 P' {+ z. v' J% {; Q- E" v4 G

3 p+ _7 l1 E; R/ Z5 X, y. h0 k6 \   public StockPrice() {) E" X# D9 E; I9 Y, b
       timestampToPrice = new TreeMap<>();& s( m2 F1 [1 \5 ?& u+ l
       priceCount = new TreeMap<>();* K' a! e0 S4 D: g& c) w( T
  }, E6 N5 f- O6 L+ w

) a/ \: W2 h+ X1 x   public void update(int timestamp, int price) {
; K* @3 m" ]: |& K4 R1 w) q       if (timestampToPrice.containsKey(timestamp)) {
7 g) B3 X6 h  A1 F2 B+ ]           int oldPrice = timestampToPrice.get(timestamp);
0 n! ~4 d! ^2 L+ |6 n! V           int count = priceCount.get(oldPrice);
- a/ D1 a0 J' ?2 |& I5 _( _) Z           if (count == 1) {& k8 {) b- G' h+ ]5 v' `7 Z- y
               priceCount.remove(oldPrice);& [# P, T4 ]; H5 p. D" c3 q* k2 d8 K) M
          } else {! E$ p. \/ ?9 E( M1 r* `( n; ^5 ]* ?
               priceCount.put(oldPrice, count - 1);7 J: [& K0 L2 V: `1 I3 f5 K, u& p
          }
; ~4 V" B: C9 V      }5 V1 C" d5 q0 O5 }+ J
       timestampToPrice.put(timestamp, price);
- F' T/ M8 V  k  {       priceCount.put(price, priceCount.getOrDefault(price, 0) + 1);/ P- \8 N! g4 f6 x4 u2 i6 g
  }! r( o0 [6 k+ Z

7 ^" o3 Z3 J: D- ~0 D9 Q+ S   public int current() {
$ B+ j7 J, ^& c; s; Z9 k4 ~       return timestampToPrice.lastEntry().getValue();
4 G* C8 t/ S9 A' f7 M; e- T  }
; M# B" ~4 S. S- w. [/ T! l& W
' D" b! s+ e# x" {& }   public int maximum() {
& W$ }: F1 N$ C7 @2 y* r( c       return priceCount.lastKey();
0 Z8 f* u$ Z/ V9 Q9 Q  }7 I4 ^" L, }& {# F* T5 q. L' I

# q4 ~0 Y* F/ V5 Z  \, U3 K6 U   public int minimum() {) ]% {. H* f9 A% P; @, |+ x
       return priceCount.firstKey();+ ?' x3 B* M& }3 E( g* }
  }
% C% z  I, b3 L}, N+ Q5 z6 h2 k* O& D1 y

+ U! i% r, {2 w9 i6 f% U) X4 K【 NO.4 将数组分成两个数组并最小化数组和的差】8 y* `6 _( ^& }% `' H4 ?# U

' J  K! P/ i  E. f* Z解题思路
- |4 h0 t! F* F: j$ o
9 ^! F( V/ b0 M5 b- r8 C4 C9 W枚举 + 双指针,具体思路见代码注释。9 o! ~1 ~. U8 Q

' G0 S2 X7 O( [  a, I代码展示
; Z( X2 ^+ q/ [$ c, l4 u
! c2 d0 h+ Y8 M- a! b4 Yclass Solution {0 d8 P  G8 K2 k3 v1 F4 r
   public int minimumDifference(int[] nums) {
% C( d9 A" w/ \- P$ r/ j* K/ e       int half = nums.length / 2;
& W; S. n! R* G# |  m8 a       int[] half1 = Arrays.copyOf(nums, half);
& N0 ?9 T: |( n1 M       int[] half2 = new int[nums.length - half];
/ {* y  |. X1 O, g# R       System.arraycopy(nums, half, half2, 0, half2.length);
) }  }3 y( l9 B       // sums1[i] 表示从 half1 中选出 i 个数字得到的和的所有情况,并且从小到大排序
2 y  D9 t2 a: \( k0 x, p! Y3 q       List<List<Integer>> sums1 = getSums(half1);
8 c) @% W# F9 v       List<List<Integer>> sums2 = getSums(half2);
( o. K# f" g1 a: e( F0 \) R       int sum = Arrays.stream(nums).sum();+ c; S+ _$ [# W4 n
       int result = 0x3f3f3f3f;4 L, C& N* D4 L) {
       // 枚举从 half1 中选出 select 个,则需要从 half2 中选出 half - select 个! B& K# L$ T2 p. u
       for (int select = 0; select <= half; select++) {2 {/ n5 l) Z, y* _* t0 `
           List<Integer> half1Sums = sums1.get(select);
8 |  ~4 L) ?/ q           List<Integer> half2Sums = sums2.get(half - select);
: ]- R4 d! o$ b% h- t; d           // 从 half1Sums 和 half2Sums 中各选出一个数字,使得它们的和最接近 sum / 2
, {: [6 [9 }( P* v6 i           int i = 0, j = half2Sums.size() - 1;" a. {3 o! `& U0 u5 n9 c
           result = Math.min(result, Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2));
* D( `% e* [3 w( ?           for (; i < half1Sums.size(); i++) {" U* g8 M1 ~3 [$ W  A/ k4 r
               while (j > 0 && Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j - 1)) * 2) <= Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2)) {
$ B8 b9 B1 J  j7 x1 B                   j--;0 d1 w4 p/ n5 _9 R2 @! H6 {4 ?9 Q8 v" f
              }6 m" ~* l2 S  P: F6 D# L
               result = Math.min(result, Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2));9 v2 E# A- \/ N6 Y
          }
; R; w4 @) ]" F6 l: O" R      }
# Y6 h6 o0 ^9 n6 _- P# d       return result;
* ^% T% J2 }" Q: R; u7 J  }
9 Y' P& S0 _% w& P2 T  j2 \; J! {+ \  H& O7 f
   // getSums 求出 nums 的所有子集的和) J, B; h0 I2 i& y" C
   // 返回 List<List<Integer>> sums3 V5 R5 Z$ x/ E2 u; T( T
   // 其中 sums[i] 表示 nums 的所有大小为 i 的子集的和1 I4 Y$ g2 V$ ]/ ]% ]
   // 去重并排序
+ o5 ]4 O. ^1 e' Z  s   private List<List<Integer>> getSums(int[] nums) {2 ?* e9 s0 a+ M- Q2 v
       int n = nums.length;( `" j! V! H% Y! `- d
       List<Set<Integer>> set = new ArrayList<>();
6 ~! p* _6 z6 p4 p& z0 S9 w0 @       List<List<Integer>> sums = new ArrayList<>();$ c) F- e( k5 h+ Y+ ~/ y( x
       for (int i = 0; i <= n; i++) {3 T- n) C- N. S6 z
           sums.add(new ArrayList<>());9 G( }. Y# [# a' n
           set.add(new HashSet<>());0 T" E! V. W" B2 S; h3 l
      }
$ B' Z9 W8 X0 A, S/ U       for (int i = 0; i < (1 << n); i++) {: F5 m& U0 T) _& f6 s
           int sum = 0;' Z; R* p. k2 Z) [, M  v" L
           int num = 0;
) u# x5 x: _6 R' `           for (int j = 0; j < n; j++) {
, P4 H! Q1 c# X0 v" R               if ((i & (1 << j)) != 0) {
9 x0 g# @* k' ?7 w0 U                   sum += nums[j];
& y( M; K" s! r' m" J                   num++;
* q+ y* J% F9 d' ^* h) z2 R              }5 t& K: ]& {- i8 H; b
          }
( g4 I$ K' `# C& i           if (!set.get(num).contains(sum)) {
1 t3 `: f  _# T- S. c6 U               set.get(num).add(sum);+ p- A8 o' g* L7 o6 @
               sums.get(num).add(sum);: v2 D. j; b4 E% ~& b9 }  \, B
          }
. H) b  Y( o. R, ~, d$ D, u  O      }
: ~6 ]6 X8 O; D       for (int i = 0; i < n; i++) {# D  Q5 m* w# f) o# n0 N8 Z
           Collections.sort(sums.get(i));
5 e5 `& H9 P. ?1 V/ Y0 P1 l      }
1 ?; u7 X! @$ b$ b       return sums;- A) f& a6 D3 k
  }
; M% u1 y* ]- l& t' }  i}
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

登录 发布 快速回复 返回顶部 返回列表