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

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

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

UWCSSA提醒您:

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

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

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

登录后可回复主题

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

x
【 NO.1 至少在两个数组中出现的值】
& _4 d% j5 w8 H
) ^, ^9 U, p( _/ ^; s1 u5 c解题思路* O3 q0 W4 q' T9 [$ j) T
签到题。
$ q  h- M1 t8 a8 u2 b- j" |/ X' g. |% G  W
代码展示1 t0 W! J# \9 t4 B
# @# v. f5 J. [5 |% k# X
class Solution {
' z% C% D' f! e7 q   public List<Integer> twoOutOfThree(int[] nums1, int[] nums2, int[] nums3) {1 J# J( g* p+ d
       int[] count1 = new int[200];
3 V# O: s' w  `8 [/ ^       int[] count2 = new int[200];. O! L  a2 j! o
       int[] count3 = new int[200];
9 e5 M* k4 i2 K- r6 X. B  c       for (int n : nums1) {
3 E5 ~2 m0 R4 z/ G           count1[n] = 1;
! w9 w3 l0 h/ O% M/ z      }8 F! M. _$ i4 A: o
       for (int n : nums2) {
+ \- a9 v% {8 j           count2[n] = 1;
: m3 z4 L2 p, C1 L6 R0 u- D/ [      }, S! Y6 H* U( I) Z9 s# U, ~
       for (int n : nums3) {
' L1 [! L3 D/ ?8 D5 F           count3[n] = 1;5 h, {6 }% z, F: z
      }
" s/ h% z% Q' o* R: {8 A4 ]       List<Integer> result = new ArrayList<>();  w' z6 l; D* x  A$ L
       for (int i = 0; i < 200; i++) {; Q; M7 d; Z. H* Z! C# ^6 ]
           if (count1[i] + count2[i] + count3[i] >= 2) {
$ g4 C( H' {% S9 ?2 C               result.add(i);6 Z& }/ ]1 r6 N' S* d! ~3 J
          }
5 b) F- o" s- K( Y: `9 J      }# h/ e  V: R! q/ o/ o& g0 q: y
       return result;; o& P; ]+ v& g8 C# m
  }% D& L+ e0 u1 p/ x, q
}
8 l3 U5 K$ W! o5 k3 Y+ R: m! l1 r- `0 b1 @5 V& l% d" H
【 NO.2 获取单值网格的最小操作数】
' {( z) Y4 h: k$ d/ H) L' B, _; a. v# K5 @. Y, t4 O
解题思路5 j- f/ Y9 h5 T' d$ i- H
网格可以转换成一维数组,然后排序。6 o, y1 S$ ~- I) h9 h. ~

& {, e: A, c* ^! s/ E! q) P不返回 -1 的条件就是:任意两个元素的差都是 x 的整倍数,我们只需要检查相邻元素即可。! e9 G7 x5 K& k9 T5 [

- y0 @- C/ E8 ~/ l, \然后枚举最终的唯一值,可以利用前缀、后缀和快速计算出把所有数字变成该值的操作次数。2 e. T7 b6 f8 r& p$ `

- q! F3 I4 l: a0 ^代码展示
, p! ]! `1 f  _8 V8 N
; E4 O# a* J9 qclass Solution {
$ |# R1 G4 z& k- T   public int minOperations(int[][] grid, int x) {  U2 w2 m* o' ~0 J; W9 A
       int[] arr = new int[grid.length * grid[0].length];
' A2 w& G7 A) Q" ^       for (int i = 0; i < grid.length; i++) {
  A( t0 n" x; G( u           for (int j = 0; j < grid[0].length; j++) {
6 `. L  y+ _" d) l8 J& n               arr[i * grid[0].length + j] = grid[i][j];
6 Y$ G9 ~( Q7 Y  T          }
6 l8 f& N" n0 z4 V      }4 V5 j+ t; s/ h/ Q8 A# p' R& _
       Arrays.sort(arr);. x1 `3 @/ M/ J6 g. {& P, \6 ?
       for (int i = 1; i < arr.length; i++) {
' k1 y+ ]% N8 P  V7 }) v           if ((arr[i] - arr[i - 1]) % x != 0) {5 f" W+ t) h4 I/ ~
               return -1;, A8 O) Z  e& G' I, X) S- t
          }$ e8 Z/ q, O1 S7 f' W
      }
; e/ D5 D% r; G1 q2 U7 _  `' v       int suffixSum = Arrays.stream(arr).sum();: B2 Y$ ]% w! V+ v$ V, o
       int prefixSum = 0;0 b$ U. c# [6 Z! [
       int result = suffixSum / x;
& M  V, {. v8 ?       for (int i = 0; i < arr.length; i++) {% D* I5 M: g& X: I, q5 v
           suffixSum -= arr[i];+ p3 o6 L9 h5 w4 k$ h2 C  Q' w
           result = Math.min(result, calc(prefixSum, suffixSum, i, arr.length - i - 1, arr[i], x));
; z$ r" D, L9 f/ @           prefixSum += arr[i];
. v& S& k+ t- D4 E      }8 t- `# I( S. y1 b
       return result;( C2 V4 Q: F7 ?
  }
! Q7 o4 l2 b9 h( k. Y2 `0 x% R- e* S9 d8 m7 I3 B- v4 c: i
   private int calc(int prefixSum, int suffixSum, int prefixNum, int suffixNum, int target, int step) {
. ^4 o1 u8 \/ I$ f. `       return (prefixNum * target - prefixSum) / step + (suffixSum - suffixNum * target) / step;9 j/ O% g& f4 a7 ]
  }; I# j# ~5 D( U/ C$ ^/ j3 o
}/ z) B% g3 e* ?4 w5 B

$ j9 R& P5 e6 V【 NO.3 股票价格波动】
; R! E0 w$ r5 G) f: |% J2 u. e  x( R  l; V. ]6 V4 C# ~  }( [5 J/ r% u2 r
解题思路/ D9 z( N% B( d
使用两个 TreeMap 即可,一个储存时间戳到价格的映射,一个储存价格出现了多少次。
' |$ Z1 ~* ~( d- a8 x) ]- c
& r# ?! Y3 O' A3 S/ Y代码展示
* f2 l6 I9 z: C) W( B+ j
8 T- T1 M2 W- `" F  fclass StockPrice {
" [: b. C9 r" H2 q! u; k# F! x; u8 ^0 q# r; A" C' q. g
   TreeMap<Integer, Integer> timestampToPrice;# Y; p3 E6 X3 h" d
   TreeMap<Integer, Integer> priceCount;
( I* ~& g: Z6 a$ Z  t3 S' ]
% Y7 y# `4 x6 a$ f+ G  W, K   public StockPrice() {4 ?# J/ F: y" e3 ?6 @
       timestampToPrice = new TreeMap<>();* }! Q# V6 s' h) ?
       priceCount = new TreeMap<>();
, e8 r2 N& ?+ E1 W' Z2 C  }
& I, s8 U7 O' ?* m( f( }
$ Y9 L/ T! P8 e. Y3 {: A) @   public void update(int timestamp, int price) {
- r$ M' W* k$ F7 u7 o9 j- ?1 b       if (timestampToPrice.containsKey(timestamp)) {- L  C, x! F" X* [
           int oldPrice = timestampToPrice.get(timestamp);" v' f$ D" a- `7 e9 L" L! {( x
           int count = priceCount.get(oldPrice);- G) _- ]2 n# g6 n- {1 q2 B
           if (count == 1) {
7 {- m, r& G9 H: h4 S0 j- z" O               priceCount.remove(oldPrice);
; `. r0 S* v$ v          } else {( O  U- \8 u4 C. J
               priceCount.put(oldPrice, count - 1);+ F) \. U1 V& M, e' V  E
          }9 P: y8 S- m0 s" C8 b7 s* d; Q$ g
      }' a/ [0 E9 f& M
       timestampToPrice.put(timestamp, price);9 ]& A8 v! a8 k0 d
       priceCount.put(price, priceCount.getOrDefault(price, 0) + 1);
; E; L! ~- C) N0 H/ g- Z  }: k- \( _/ y5 z' |: A. n! y6 k
' V. E; R. M* @, A; l! P; V
   public int current() {
) ^; R4 \# ~" ^4 T$ {       return timestampToPrice.lastEntry().getValue();$ b6 p% _5 c) a  R8 B
  }" F' s- Z( u& E4 d% w
  Z+ {$ J2 K* t7 D3 M, t
   public int maximum() {: f: G* C3 J5 u
       return priceCount.lastKey();0 A" i9 F3 w. q
  }
& h: L$ G* Q* c: J, y; [8 A2 s/ t0 K5 m8 T( b
   public int minimum() {* M% E! ?; y  x7 g9 b" U1 M: t% w
       return priceCount.firstKey();; `# ~# Q1 o+ j  t+ ^+ L+ P# S6 E
  }# [2 A5 b5 [5 I. u9 F" [( s; o
}" W! e/ S# S6 V- X2 ~- c; Q/ Z. v
- R  j! V+ i" g- g0 d/ K8 z; V; N
【 NO.4 将数组分成两个数组并最小化数组和的差】
$ W  p6 x  [6 L& g- _/ x; U
9 z. Q9 j! v0 W" I) c解题思路( l! H9 B' w2 E$ L
  u. ]7 C) `9 J- r! R0 p
枚举 + 双指针,具体思路见代码注释。' {1 ?& I+ E' A$ N- m, M4 N

* B5 X/ u4 p9 G# x' l3 G( F代码展示% G. l5 S* r% w, K" }

7 }% v3 g" z& @! G7 `' gclass Solution {9 ^2 G+ m! |6 I/ Y, r$ a; U9 }
   public int minimumDifference(int[] nums) {
2 W/ u1 P( b. ~/ a6 V+ s% t       int half = nums.length / 2;
  y( F* Y0 s7 w/ d& {4 p       int[] half1 = Arrays.copyOf(nums, half);6 V  c4 {% L, h, ]* g- v0 w" t% A
       int[] half2 = new int[nums.length - half];9 g# q: m7 \+ W" K0 [" \: m
       System.arraycopy(nums, half, half2, 0, half2.length);
* H+ \3 K+ D: {       // sums1[i] 表示从 half1 中选出 i 个数字得到的和的所有情况,并且从小到大排序/ ]5 L2 A4 z2 `: |; V
       List<List<Integer>> sums1 = getSums(half1);4 @: y4 k8 B4 W5 ?" ~' y8 c
       List<List<Integer>> sums2 = getSums(half2);7 X/ D3 h, u2 ^0 b' J: ^6 Z
       int sum = Arrays.stream(nums).sum();( f# e( _' q3 {5 E9 S$ U
       int result = 0x3f3f3f3f;  G2 S! m" B, S" \) k8 p! W1 a& j
       // 枚举从 half1 中选出 select 个,则需要从 half2 中选出 half - select 个+ b* \, e9 x2 b8 r5 f6 `( T0 _
       for (int select = 0; select <= half; select++) {  @' d  A& e* x( m3 y% ?9 M
           List<Integer> half1Sums = sums1.get(select);
8 Q1 u5 j, M. X0 N           List<Integer> half2Sums = sums2.get(half - select);
, e: U8 @. B) j3 Y- [           // 从 half1Sums 和 half2Sums 中各选出一个数字,使得它们的和最接近 sum / 2
3 x' y! q6 p8 L1 R3 R% Q           int i = 0, j = half2Sums.size() - 1;2 {$ g8 U0 L$ I) F! B
           result = Math.min(result, Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2));
2 S/ x" S" A' {  i) i! g6 ?           for (; i < half1Sums.size(); i++) {
! _* `, W6 p) e8 K               while (j > 0 && Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j - 1)) * 2) <= Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2)) {
: O; N' i( K6 P                   j--;. m" m# Q" ~/ ~% a) q
              }$ K) O; g8 q; ^3 G
               result = Math.min(result, Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2));. ]/ B; S4 {& v4 ~; v
          }- e" T4 ?0 P2 L- f" p4 u) P
      }/ Q0 Q" a7 V) v4 }8 s, ~( E. X: \
       return result;2 B" A- R% X3 E2 X! B/ }
  }
1 y9 T8 s; i5 I4 m( \: G1 M
! ~( B) ^9 f  A* G6 Z( C4 D   // getSums 求出 nums 的所有子集的和
  c  s8 I& W' |0 b" u+ G$ V' Q   // 返回 List<List<Integer>> sums
) D% o$ B+ A) p7 L1 }3 H" p! K   // 其中 sums[i] 表示 nums 的所有大小为 i 的子集的和+ W6 k3 k+ W0 @2 b2 N0 b1 M
   // 去重并排序, w0 L0 z. x& d: [% N
   private List<List<Integer>> getSums(int[] nums) {
3 p# t( R* l$ c, G4 D6 y# o9 M       int n = nums.length;
' v2 t, D/ l6 _- `       List<Set<Integer>> set = new ArrayList<>();0 E% v4 j" [& t' j! c
       List<List<Integer>> sums = new ArrayList<>();
/ w4 b" w% Q1 P+ @       for (int i = 0; i <= n; i++) {$ a6 k- q( H2 c% G+ ], d0 O% ^9 f( \
           sums.add(new ArrayList<>());
) h# }* R' V; R; a- K/ Q5 {           set.add(new HashSet<>());% |. `. W9 ]7 {* z( o
      }
7 ]( [. [6 K% l/ d       for (int i = 0; i < (1 << n); i++) {
- ], M) N: B/ u/ Z7 y/ ?           int sum = 0;
) T( a, }. f% F- f           int num = 0;
  J- Z% ~- c4 }0 Q: Q; g           for (int j = 0; j < n; j++) {
1 F& @1 }3 Q) R  }# \3 _) z               if ((i & (1 << j)) != 0) {" [! Z( C  _6 z# j
                   sum += nums[j];
$ _' {9 j1 A$ a8 ^$ Q                   num++;
0 Y3 t- V& \, ?9 k              }
1 e* s7 P9 ^3 D/ [) `2 p          }. v4 l' I0 M( d! e- Y7 z- u
           if (!set.get(num).contains(sum)) {% m1 l8 v' g; g: }1 ]4 H
               set.get(num).add(sum);
3 r/ X: L! n( v5 O$ m" w               sums.get(num).add(sum);0 Q' b! @! D( ]# j! D* I
          }
, z# I5 i6 L2 @      }" ?; Y( _1 J5 L( W3 B
       for (int i = 0; i < n; i++) {' V/ `  Y2 A2 \8 \4 X
           Collections.sort(sums.get(i));9 D5 M8 h5 H: w4 S* f0 l0 A
      }
3 f, F3 _# r% j! D; a( d       return sums;
+ I. @& D2 s3 G& L3 k3 r4 F  }
4 l. R  k/ B+ J6 K}
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

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