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

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

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

UWCSSA提醒您:

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

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

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

登录后可回复主题

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

x
【 NO.1 至少在两个数组中出现的值】' N: K3 c2 W, q# @
7 l/ k% b1 _8 ^" ?: g
解题思路
" Z7 W: a/ w9 A1 P8 [2 z& \4 I6 Q+ _2 q签到题。7 x1 @. r& k" p: F
0 \- B. a/ h5 Z. _
代码展示
  m: j+ N$ F$ i! b3 N$ C; x2 p
* S3 l: S* P7 Q6 e. |+ tclass Solution {
+ x6 x+ f6 o) g. Z+ U# r9 l5 k   public List<Integer> twoOutOfThree(int[] nums1, int[] nums2, int[] nums3) {
" s/ c) z( |6 E$ q* K       int[] count1 = new int[200];
+ x+ G  K7 g1 X       int[] count2 = new int[200];
7 G8 A: z7 D8 _8 W       int[] count3 = new int[200];
& k+ `; K3 N  Z' l       for (int n : nums1) {0 i$ d' t/ s  W) S" y+ T( C
           count1[n] = 1;% t8 ~' F; e6 ~( _* ^" c0 @& x
      }- {6 W6 o7 T. D  G- m
       for (int n : nums2) {. @* G7 ~3 s! j) T& \5 V, F; Q
           count2[n] = 1;
4 p. U3 b! U! p- j      }- N4 G+ a) c+ K9 u) D3 v
       for (int n : nums3) {
% j) H. [+ q+ ^0 G: B  y# k           count3[n] = 1;& e' P: h+ Z0 r
      }
  g8 W5 u( E: q/ H( v6 D       List<Integer> result = new ArrayList<>();8 Z/ {4 x& ^3 q# e4 i; d
       for (int i = 0; i < 200; i++) {: m# g( t# i1 l8 N* \9 k( Z) M$ b
           if (count1[i] + count2[i] + count3[i] >= 2) {
! I- S* s) ], L; I/ c" i& ^               result.add(i);1 }4 T$ U+ H: n$ [' y9 w1 t9 n3 ]
          }
5 K3 P" f0 z2 Z- g      }
2 V7 w) t/ e7 O( z: D8 `5 \6 @( o       return result;! V6 v$ }+ B  Y0 O4 Z
  }5 m. a  \/ {* V: W6 f
}+ U* G! G& R7 @

5 x' R/ [) l& B( P  `( C5 b' b0 P! P【 NO.2 获取单值网格的最小操作数】$ j# Y) ~; g! P. s: e# v; e

2 W* o! h+ E* }! Y8 `2 }解题思路9 J7 [# H6 X/ s% O+ t
网格可以转换成一维数组,然后排序。
3 g3 n/ N3 D9 Y/ m2 _: I- l6 G8 v$ G1 T" R
不返回 -1 的条件就是:任意两个元素的差都是 x 的整倍数,我们只需要检查相邻元素即可。
8 ^  T$ J& z% e
- A9 K: h$ ]# c; T; c5 p/ I* o然后枚举最终的唯一值,可以利用前缀、后缀和快速计算出把所有数字变成该值的操作次数。
- O5 n7 ~: `" O. f# m+ \
$ {: K9 S1 E, l& k( D6 I代码展示) D) P6 V" M: [4 k! Q8 f' d+ b

2 g7 H+ B" f; r1 e* qclass Solution {
: k) T. [+ l: X4 @- G, J# Q   public int minOperations(int[][] grid, int x) {
9 r. R" t& ^6 J1 Y* ?       int[] arr = new int[grid.length * grid[0].length];, f: ^2 o. i  X  n1 D2 u
       for (int i = 0; i < grid.length; i++) {
. Y6 S  g' @! C% W           for (int j = 0; j < grid[0].length; j++) {
, ?8 q2 @3 P  q/ c& Y9 U+ o               arr[i * grid[0].length + j] = grid[i][j];" {8 S& N8 g1 a
          }
6 {7 x: I, |9 Y6 w6 S6 [; B      }4 [, R6 t: d$ k- q3 n- h/ x6 I  e9 o
       Arrays.sort(arr);' M9 t" h2 G/ \$ @# q0 W
       for (int i = 1; i < arr.length; i++) {
( o. t( V/ n, S5 p/ x# Y) S) z           if ((arr[i] - arr[i - 1]) % x != 0) {
4 Z# @/ L: v8 ^6 q, o/ ]3 m               return -1;& O# E! |, W5 p7 g' g1 W3 E
          }5 @. X0 G; W0 I1 P4 Q
      }* z  b1 a# j5 Y3 b
       int suffixSum = Arrays.stream(arr).sum();3 j5 z3 \" A- f" I5 l" k/ e8 R/ E5 f0 O
       int prefixSum = 0;
' r9 ?! }" W& k" v       int result = suffixSum / x;
8 O5 W! L6 T& v- W# j5 b0 R! l       for (int i = 0; i < arr.length; i++) {
/ k; Q+ ?; y) @, e           suffixSum -= arr[i];! H; j" k$ W4 O) Y
           result = Math.min(result, calc(prefixSum, suffixSum, i, arr.length - i - 1, arr[i], x));
% s! W0 e* ^' a6 U  d8 s           prefixSum += arr[i];+ R* s! N" {7 }+ J0 g  T
      }
8 I) V9 p8 A! n" a8 V9 ^, Z       return result;1 w( Y& d3 i  o/ P+ N
  }1 o4 ~5 M1 j8 q1 l$ @0 m8 P

/ S1 A/ d  i2 A4 _! D3 a5 v   private int calc(int prefixSum, int suffixSum, int prefixNum, int suffixNum, int target, int step) {
& t* b; X3 \) L! B* N. \) j       return (prefixNum * target - prefixSum) / step + (suffixSum - suffixNum * target) / step;
. o: z" d0 [# Y' t* v( `# ~, D  }8 |  Q6 K* Z; F4 s2 c8 b1 O
}! k% Z- e: c. u. i! L8 P* ?: S
' }5 t  B+ P) T  X4 }  S+ ^5 c: J
【 NO.3 股票价格波动】+ M0 q! m+ s. O, Y. N" r% E" r) j
& p8 W- X. r7 i# J. T1 X) q
解题思路+ X( ?4 q4 M( [( S
使用两个 TreeMap 即可,一个储存时间戳到价格的映射,一个储存价格出现了多少次。
9 d5 ~) c0 L- C& u, j+ k7 P# K$ L5 j: |4 ?  R" W  t
代码展示
& X0 `( V3 A# M# ~. Z+ `9 f* D5 \, |
" P7 {2 T& K5 m* T, U# C, O( Iclass StockPrice {
  d6 h6 [7 n2 D$ c) d3 q9 G, p- N2 |1 h
   TreeMap<Integer, Integer> timestampToPrice;' c( R( T0 m% e; C' b. L
   TreeMap<Integer, Integer> priceCount;
, p7 m8 n2 H! e+ O2 [# F8 s/ m$ G9 A  H0 x
   public StockPrice() {
: _$ l/ x" [* q! q. U       timestampToPrice = new TreeMap<>();) w9 y& j* _/ b" H# `
       priceCount = new TreeMap<>();4 g! z1 V% n, I  c! l: @$ f
  }6 t! k/ Z& i! c; T
. u0 K! X) B8 `& U( N
   public void update(int timestamp, int price) {
/ o5 V, q9 A6 I1 [+ I       if (timestampToPrice.containsKey(timestamp)) {4 ^$ E' U3 D  Q) T5 M
           int oldPrice = timestampToPrice.get(timestamp);
  m9 X( Q* N1 ?0 p" s: v6 p- ]           int count = priceCount.get(oldPrice);
. h0 n$ r+ i* {, M! r- T( e           if (count == 1) {
+ h7 ?* o" h  m4 A+ p9 k3 m               priceCount.remove(oldPrice);
- _3 _  G' N5 h+ v" K' {% Y          } else {# l2 J2 v/ I# }( ?  Z* V: `0 b' K
               priceCount.put(oldPrice, count - 1);6 u; J: E& U* Z- H
          }' v& L; u! U. Z+ V/ n" s% L) ~
      }
+ J- p3 }( h! s% C- V7 j! T' k       timestampToPrice.put(timestamp, price);0 ^+ b0 c) x/ `# X" P
       priceCount.put(price, priceCount.getOrDefault(price, 0) + 1);
2 @8 k7 O" c' J( Z5 \/ D  }! h( W3 a. R4 D: l. O) U/ p
! o1 N* g" s$ a" p' q5 f$ y& L7 h
   public int current() {
$ u7 q% Y# E4 f1 I: m) ~       return timestampToPrice.lastEntry().getValue();+ u# [, S( j  e8 M/ R+ d+ K/ V; j
  }
7 @0 |  q! [3 S
0 U* L2 m5 J, G5 Q5 y   public int maximum() {2 v$ |9 `4 B- D- Y
       return priceCount.lastKey();
2 d2 F. W/ h* g  B  }! N; Y# y# o, j  C8 w
: k- J3 f) ?; O% F5 y' R/ P  ^# z
   public int minimum() {! @8 R% O, y6 H( f# ]
       return priceCount.firstKey();
  `9 O! T. q& @  }! W- E. f% L+ \  \! X
}
# P8 u0 ^9 Q6 T( z* l% B# U9 s1 N4 Q1 d$ Z* o, Q& h* H
【 NO.4 将数组分成两个数组并最小化数组和的差】
8 A% ^4 @# H2 {- t' s3 ~+ g8 T3 ^' [, }& y2 X3 q0 K" ?
解题思路
" N' h5 M/ |: H& r
5 j; X& o  e5 a$ ^# Z7 Y枚举 + 双指针,具体思路见代码注释。  Y# r' D, o2 F  [" c- V9 N
% m" d# d  o. ~" P7 Q
代码展示
- L+ A4 w6 Z. f& P6 s5 u! j2 M; J8 w& e+ W$ I1 d# \
class Solution {3 D9 `* K6 F% H, _  E
   public int minimumDifference(int[] nums) {
( n7 {" L5 S+ N       int half = nums.length / 2;  Z6 y/ p1 x! r% n! s8 K% p
       int[] half1 = Arrays.copyOf(nums, half);
8 `3 \7 N2 R- {7 n+ M$ f& U       int[] half2 = new int[nums.length - half];
2 y2 B! e  m# n9 w) b       System.arraycopy(nums, half, half2, 0, half2.length);- F. Y+ W' ?* n. b0 Q
       // sums1[i] 表示从 half1 中选出 i 个数字得到的和的所有情况,并且从小到大排序* ^0 h5 Z* O; m( Q$ H0 C( N
       List<List<Integer>> sums1 = getSums(half1);
9 e6 S0 _9 ]: e% I6 t6 b       List<List<Integer>> sums2 = getSums(half2);
" L. `1 x/ Z9 J- E       int sum = Arrays.stream(nums).sum();
; X4 [' o$ U2 m& f       int result = 0x3f3f3f3f;) e3 c$ J, p; ]1 k0 c: F7 |
       // 枚举从 half1 中选出 select 个,则需要从 half2 中选出 half - select 个
+ v  E# k/ A+ c. l4 ~       for (int select = 0; select <= half; select++) {
( i6 r' m3 p/ q# A0 C* w- }( E4 t           List<Integer> half1Sums = sums1.get(select);
- ^5 U0 }6 Z) h$ D3 N7 M           List<Integer> half2Sums = sums2.get(half - select);
# F/ U! @. O: u+ F* A8 m" g# J           // 从 half1Sums 和 half2Sums 中各选出一个数字,使得它们的和最接近 sum / 2
6 M9 ?/ S9 `$ G9 m9 }/ B( \( X5 c           int i = 0, j = half2Sums.size() - 1;
. ]* e; U' E; J" W3 l0 Q6 k           result = Math.min(result, Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2));) n* ^- |* N  R& |2 G  E
           for (; i < half1Sums.size(); i++) {3 M0 M3 I4 D: W0 A2 Q  Q& V
               while (j > 0 && Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j - 1)) * 2) <= Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2)) {3 x: s" O+ `; ~8 r8 n. h
                   j--;, l4 K8 ]  W8 V# ~3 n
              }! P, O, ^. F/ T
               result = Math.min(result, Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2));3 q8 g' e2 y: n% V2 t; ?# c
          }8 w: y8 x$ h  z5 d
      }
* w: ^1 j1 s( q. N' A8 z9 S       return result;
* A* [; a6 P0 X& n  }0 U. O/ |) ^. W) V( [

" b9 ^: ]: l* u  t0 R   // getSums 求出 nums 的所有子集的和
5 _  Z0 a4 Z0 V; O2 x; N8 W4 U) U: g   // 返回 List<List<Integer>> sums
1 |% m! k0 s+ d6 v! g% x1 b! M   // 其中 sums[i] 表示 nums 的所有大小为 i 的子集的和2 U8 D* _5 Y! }9 e# d) a
   // 去重并排序
* R- U, L/ B- X* a0 b; @   private List<List<Integer>> getSums(int[] nums) {
9 L; e. o3 m8 @: s/ V( R1 j; X9 c       int n = nums.length;0 P+ g+ h9 g  R+ J
       List<Set<Integer>> set = new ArrayList<>();" ]4 n/ A7 l1 F! k0 ~- |5 R
       List<List<Integer>> sums = new ArrayList<>();; P5 T% ~: u: b1 z8 O
       for (int i = 0; i <= n; i++) {+ G8 H4 o7 A- M3 b+ k6 N" ^
           sums.add(new ArrayList<>());' \- [* U7 W# v# A' _; J
           set.add(new HashSet<>());6 |( {. f0 p' e3 N8 G8 L
      }
. Q8 G3 @3 J: Z! ^% R$ R       for (int i = 0; i < (1 << n); i++) {" @. R1 K+ E& Z1 S$ X" t
           int sum = 0;  [) z/ ?) o& ~' \1 V
           int num = 0;
. r) i6 p+ K1 }: f. v3 F; J           for (int j = 0; j < n; j++) {
3 |0 O% u+ j1 u               if ((i & (1 << j)) != 0) {
# w5 m9 O) m* E$ u* q, G                   sum += nums[j];
3 {& S* h7 H0 J, q! [* ~8 ]                   num++;
$ r* E# N7 O* N# Z2 X; M              }: |3 z& Z* O  M7 G& g* L: W
          }, Q5 G+ U3 }- {' B# i8 D; {4 B
           if (!set.get(num).contains(sum)) {! r* O8 W4 v( N, b  B; M
               set.get(num).add(sum);4 C5 t: }9 _- }5 Z4 e
               sums.get(num).add(sum);3 N7 c' k6 P1 ^
          }
. V6 ~0 O* L, F2 N/ N3 W      }8 f* t! X: I9 a9 w
       for (int i = 0; i < n; i++) {1 n; c* p, m/ k2 A$ Q7 B
           Collections.sort(sums.get(i));
: R. n+ C2 \2 K. P4 N. s      }( K9 ?8 O) Y+ ?  H6 U# g
       return sums;
2 U9 I0 n( Z% T3 O8 n1 K8 P, ?  }+ x; @& H8 \$ Q' A! p1 y. f; y
}
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

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