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

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

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

UWCSSA提醒您:

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

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

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

登录后可回复主题

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

x
【 NO.1 至少在两个数组中出现的值】- o( T: {* c7 ~& d+ _: H7 A2 D7 ?4 s

: _. Q% b5 }+ Z1 @" G$ d% Q解题思路
- F" G* {; ~5 W) T签到题。' Q. M' {. `! X7 w& w9 V# _

; n5 |7 U1 Q, r0 a7 B1 K代码展示, G- j7 k1 L) v
3 z) ~- S, J8 t( c. G
class Solution {
: U3 n; @- g0 K7 h/ ~+ z# I/ S   public List<Integer> twoOutOfThree(int[] nums1, int[] nums2, int[] nums3) {2 _, D9 K6 S" n, V
       int[] count1 = new int[200];
# `( j6 p% g) I# V' _3 t9 J       int[] count2 = new int[200];
3 k" J; b9 J% D" e2 O+ y       int[] count3 = new int[200];  `1 r% d( \  Z% w
       for (int n : nums1) {$ \, d3 ?- W* W% t
           count1[n] = 1;/ n  Z8 B0 j  g* c
      }/ M6 M) Z  q6 x) W7 D
       for (int n : nums2) {
! U0 L, v9 s0 h           count2[n] = 1;4 `2 T. Y5 ]5 G$ C
      }' ]0 r. a6 ]# a! C" I
       for (int n : nums3) {
" I% x$ m* U9 z4 s# [           count3[n] = 1;
1 \- }0 [, Z* x  t1 ^      }
4 K: U& h: [1 A/ ~       List<Integer> result = new ArrayList<>();3 C* j7 |6 }7 n
       for (int i = 0; i < 200; i++) {
" O  t! U  M3 {8 D           if (count1[i] + count2[i] + count3[i] >= 2) {
6 }! _8 |2 ~  z7 p. v               result.add(i);; v9 B+ d/ c5 v" f+ S; o
          }& Y& S8 V4 T7 F0 o) K
      }
. ~4 E. b$ d2 T  q8 T* m       return result;
3 H' L8 r; l; @. ~& ~  }
+ {2 b2 G0 X; `2 X. n( q}  R( b0 M  C5 S8 p5 ?3 B

  a- ?" I- N3 Q, i9 j【 NO.2 获取单值网格的最小操作数】
: ?/ \) R- I. N; O* W; ?" c8 t- j! S3 Q! [: _0 T
解题思路
$ R$ r) _: s3 O1 S网格可以转换成一维数组,然后排序。- {( T# F( b& \! h  ~
" a( d) m( |& Z1 ^3 r, `
不返回 -1 的条件就是:任意两个元素的差都是 x 的整倍数,我们只需要检查相邻元素即可。1 {: b$ D3 ~6 T

: a* w+ w8 Z: |然后枚举最终的唯一值,可以利用前缀、后缀和快速计算出把所有数字变成该值的操作次数。' f$ R$ a; z* ?+ V$ L4 V- E2 K
( H( f, p% D) l: i$ M. C" ~$ `4 _' h! g
代码展示
# t9 U9 |6 s$ B# _
6 C" V% P! B0 O! Wclass Solution {
5 v& g  Y) R3 q; P9 B: ^5 f   public int minOperations(int[][] grid, int x) {% H0 u! g/ v+ V% P+ j5 Z9 G" n
       int[] arr = new int[grid.length * grid[0].length];
: z4 x  H* Z8 M, {! ^% w       for (int i = 0; i < grid.length; i++) {' [4 E( y% k# e; N( Q. ]
           for (int j = 0; j < grid[0].length; j++) {, Y$ O8 }- U9 R$ D6 r8 R0 M
               arr[i * grid[0].length + j] = grid[i][j];7 T% K4 v8 A  p2 t5 C
          }& `/ g4 F2 n- Z" }2 G2 c/ P
      }
, S  K0 {+ m2 o3 [' l: B       Arrays.sort(arr);
5 l* m/ u2 c3 P( a) X+ m0 L       for (int i = 1; i < arr.length; i++) {. X, U$ \$ L1 D9 H1 V
           if ((arr[i] - arr[i - 1]) % x != 0) {
$ z: H4 }' K  N. ~. w$ u               return -1;3 z, v6 z' G( B) ]
          }
  B" Q6 p' `) Q+ y* e      }% B6 F. l1 f6 G1 z" t8 l# ?
       int suffixSum = Arrays.stream(arr).sum();
/ v6 v. X" a, l' N5 ^1 _6 d       int prefixSum = 0;0 t) v) {( a1 F+ @) J! j
       int result = suffixSum / x;
$ m- T/ m8 M* y7 D" I* h       for (int i = 0; i < arr.length; i++) {7 ^- W1 z; F/ y
           suffixSum -= arr[i];3 U8 S- Z9 X' b4 m3 V
           result = Math.min(result, calc(prefixSum, suffixSum, i, arr.length - i - 1, arr[i], x));
6 _1 h) ?7 X* V, A! q/ b/ b+ i" _           prefixSum += arr[i];4 }- `" B0 c4 l$ t- E" q
      }
7 M# Q4 s( i# c1 u% z6 l$ r       return result;9 f% f4 \* f  a
  }
8 {& Y% e0 `+ c8 d$ h& J+ J8 [% g4 ^
   private int calc(int prefixSum, int suffixSum, int prefixNum, int suffixNum, int target, int step) {
2 C& T1 k& X! r9 h9 ]/ a7 s       return (prefixNum * target - prefixSum) / step + (suffixSum - suffixNum * target) / step;! w, j* Q; ]6 x, ^  c
  }
' H0 S6 P! K5 R! I* g5 {5 _}
6 j4 ?7 ?+ t: r1 n# K% H2 I1 p8 {4 ^* U
【 NO.3 股票价格波动】
+ T- ^; X0 Q2 o' k6 r2 `7 J) s
& O& }; b. V) i  n% V  }1 L! b1 o解题思路
. j, ?  G* z. _使用两个 TreeMap 即可,一个储存时间戳到价格的映射,一个储存价格出现了多少次。, s1 m0 w* V! g. F9 t
  D$ q8 u% Y6 v* u0 M9 }
代码展示: l) R- C9 v2 X% r: t( D- n
% t% L% H9 x  M  E
class StockPrice {" a5 \+ o3 c, l1 O9 ?

% }4 C$ O6 W: s% {$ p' @   TreeMap<Integer, Integer> timestampToPrice;: p% V! ]9 G4 W, X! ~
   TreeMap<Integer, Integer> priceCount;
+ E+ {( u; ]; Y
* V9 J, [2 }' @9 r/ w# L) d   public StockPrice() {
: d* E: w1 ^$ h       timestampToPrice = new TreeMap<>();
: \% l& R8 [5 u7 W' t: f0 {       priceCount = new TreeMap<>();6 y, J: w1 m0 t7 p' p. [
  }0 D8 @6 ~' V: Y; r
5 w7 T3 s2 ^  K& j* p! x
   public void update(int timestamp, int price) {. g+ F0 }! i( j5 |2 ~& g
       if (timestampToPrice.containsKey(timestamp)) {- B6 @2 b$ r- p
           int oldPrice = timestampToPrice.get(timestamp);1 F/ `8 z& T7 G
           int count = priceCount.get(oldPrice);
/ U+ O* C+ q$ j2 B$ r# u           if (count == 1) {
" r7 |$ i0 {$ h6 f. _' k: U: C               priceCount.remove(oldPrice);
7 N7 J+ h9 Y( a% c: v6 X          } else {
0 Z; T5 W* l1 O5 O               priceCount.put(oldPrice, count - 1);( s4 Q8 `# n" m
          }( o; x5 z( Z; B- @' b
      }
1 {3 e; R3 m+ k# L       timestampToPrice.put(timestamp, price);4 x6 e5 h2 x" |( E# _
       priceCount.put(price, priceCount.getOrDefault(price, 0) + 1);
4 T5 c$ g7 V+ _# v; T0 b: z  }
/ K2 u. l2 R% c: A# [9 w1 S9 ]; O9 i3 K$ V
   public int current() {* ^5 r& W& B' a" c, k# I
       return timestampToPrice.lastEntry().getValue();; M  G$ N6 F) u8 s& l# v3 f
  }" y( Y; D+ |: l+ m3 ?! l* h

/ c7 d2 U$ m: h' k; A$ D   public int maximum() {
5 I0 [# S+ {8 l5 d       return priceCount.lastKey();# V5 P$ n6 [+ F& w# O4 _# x2 C
  }% h6 }  T1 S& F! d9 x8 N

4 k: A: d! r+ }6 S   public int minimum() {3 Y( r) s( ~8 E' C
       return priceCount.firstKey();+ E$ l& o, }, l+ Q2 l1 x
  }
; O0 O3 u& X; A, {6 q}1 S1 U( n8 V8 y  d# V3 \; ~

2 a* M2 J; I. N$ c/ B  _1 Y, ^【 NO.4 将数组分成两个数组并最小化数组和的差】
& y, ^7 v# n2 j% @/ f+ n1 y2 m% d2 B' N0 b/ m
解题思路
9 l$ m, g4 A+ j! a% J' N7 K3 r" p/ }3 X" M9 Z  A  j
枚举 + 双指针,具体思路见代码注释。1 p5 b  S$ j# ~& W7 Y4 q

# ]) q# N6 ~0 C6 w" K7 t代码展示
4 k/ b) l) v( p- U/ j% W
) y5 O8 R$ D. k; kclass Solution {9 l+ b, o& c( W
   public int minimumDifference(int[] nums) {4 J: Q% ~( L; S  n" U
       int half = nums.length / 2;
; u% H0 _2 C( q$ Y, p, K       int[] half1 = Arrays.copyOf(nums, half);  y% G. E6 d9 n, Q! T% S* G
       int[] half2 = new int[nums.length - half];7 U/ `3 F/ Z5 t* n- j/ T
       System.arraycopy(nums, half, half2, 0, half2.length);
2 n8 G$ y& m7 ^) }       // sums1[i] 表示从 half1 中选出 i 个数字得到的和的所有情况,并且从小到大排序
0 o+ I/ d3 ~. R# R& G, ^/ w8 P       List<List<Integer>> sums1 = getSums(half1);
; M, j" ~6 [, X% c       List<List<Integer>> sums2 = getSums(half2);& i# }- X! g' ~8 t( f3 O
       int sum = Arrays.stream(nums).sum();
' [: P1 @0 _& ^- ]% B4 z; ]       int result = 0x3f3f3f3f;
" y/ ~: d4 Z) B, k7 v/ D       // 枚举从 half1 中选出 select 个,则需要从 half2 中选出 half - select 个  b# D& ?2 b* i: e) h: N
       for (int select = 0; select <= half; select++) {
8 C- q: r2 Y+ P* Z! [' }. N           List<Integer> half1Sums = sums1.get(select);
8 @/ T5 D- ]7 S' J! {           List<Integer> half2Sums = sums2.get(half - select);
  _7 U& h; N8 U9 }( q' [4 i           // 从 half1Sums 和 half2Sums 中各选出一个数字,使得它们的和最接近 sum / 2* {5 ]+ G9 x' `" I! ]4 J+ O+ Y
           int i = 0, j = half2Sums.size() - 1;
5 g6 F% V2 t9 \# q# b$ ~           result = Math.min(result, Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2));4 R/ l5 J" _) p3 l0 e( D; v
           for (; i < half1Sums.size(); i++) {2 U8 c# d& n& E/ ^
               while (j > 0 && Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j - 1)) * 2) <= Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2)) {+ i0 X* C+ a3 p7 v' z+ U6 k
                   j--;
/ j8 Z, M- P$ Z) V( z; U% \% A' Q  k              }
& d% P. L% D0 M9 M3 p               result = Math.min(result, Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2));$ M0 B' T+ b6 B' V( Z
          }
' p5 W& {; V: ~" t( Y) t      }
& _: `- R3 d. I- |" R6 Y) V       return result;; C! E5 n  R$ x- ^8 z- [
  }4 r( ~1 w8 G% @; f( o! F
5 }9 [& s$ r- k6 |
   // getSums 求出 nums 的所有子集的和
' e8 C7 `* b2 e2 }/ i, a   // 返回 List<List<Integer>> sums  y# `1 r& I9 H' a: I! n' H
   // 其中 sums[i] 表示 nums 的所有大小为 i 的子集的和
5 V9 T! k# }7 J9 U1 z   // 去重并排序: ?7 H; h4 F) {% t% C
   private List<List<Integer>> getSums(int[] nums) {
5 p* h0 F+ J  i# d1 c       int n = nums.length;6 q+ l1 n2 L5 o% R% n7 v0 Y% t( M
       List<Set<Integer>> set = new ArrayList<>();
: b; P: R5 Y; r( [$ h; p       List<List<Integer>> sums = new ArrayList<>();, L* D: T' i3 b4 O+ E% R
       for (int i = 0; i <= n; i++) {7 s* m4 l! I! _# J
           sums.add(new ArrayList<>());
8 z0 h# S0 a2 ?7 t1 ?           set.add(new HashSet<>());3 x9 d: @- z! t
      }
6 J; g" H2 \4 B7 Q; w       for (int i = 0; i < (1 << n); i++) {
/ W; m4 n* p( X2 |           int sum = 0;) {* Y- Z; r7 X! [
           int num = 0;! b) n* l, h  B0 U1 q, Z
           for (int j = 0; j < n; j++) {
4 {! S: p( g% w( H& S$ d! |2 _- r               if ((i & (1 << j)) != 0) {
5 q# x: N  t1 n2 C8 G' ]                   sum += nums[j];; }: [6 Y, H( q5 j3 A" d
                   num++;
# @, ?8 ?2 C, F! u2 j$ Z" u              }& o( W9 _# P3 M( U5 b8 y4 e" l
          }0 x4 v# m# {* L3 Z, m
           if (!set.get(num).contains(sum)) {
5 a0 r. }& I( t" ?               set.get(num).add(sum);7 B: k, |8 }: O: q: C9 J! K
               sums.get(num).add(sum);
3 W1 H! S. i7 p, V$ l          }
- Y5 X+ i' e- C8 I      }/ k3 |- k8 K( D- O8 _9 G
       for (int i = 0; i < n; i++) {
# F6 D; F0 }9 g           Collections.sort(sums.get(i));
! N8 k* x( Z0 q7 T      }; z0 k; C6 x7 i% K- p4 P7 Y
       return sums;* g5 e# w- u. f( k. ?) o7 A' H
  }
. Q' `( K, T- m& Z' }& }7 P" n}
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

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