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

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

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

UWCSSA提醒您:

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

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

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

登录后可回复主题

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

x
【 NO.1 至少在两个数组中出现的值】7 l) @0 D4 W8 E4 z/ U9 S

, t4 `, |* b; q- S' w/ b+ t) f解题思路
. R9 z) T% k7 k( Y2 ^签到题。
& N  V  S( F6 a% t: K  l- o' ?
& I3 L) Q4 r+ ?) h( S代码展示  y* I* N# E. C2 y8 ?) z7 d- u
) V, w/ D' [* c% [
class Solution {
& m) ^: A; n/ S' H. b! q/ S   public List<Integer> twoOutOfThree(int[] nums1, int[] nums2, int[] nums3) {
/ N+ e6 O8 N- _7 c8 x: W       int[] count1 = new int[200];
( v. w$ x# [" X) y       int[] count2 = new int[200];
8 L8 F6 \* N, @       int[] count3 = new int[200];
* E1 G' V$ f) y" R0 l; |0 }       for (int n : nums1) {
- \$ P8 |% D; s- [) q  s           count1[n] = 1;
: a/ H& x- K  C# C' \! Y( S      }, ?; m: J( j, w* o
       for (int n : nums2) {3 V0 ~: X1 j# s" a) j
           count2[n] = 1;/ D/ n4 a- M* g( b* [  ^8 ]
      }
" c! D: H$ }4 y( [/ x$ Y       for (int n : nums3) {
3 O  v* ~2 S9 n# _8 p' l           count3[n] = 1;
' [7 c# I/ m4 E2 O      }) Y% y& g, r, G: c
       List<Integer> result = new ArrayList<>();2 J; I! `; {& F- n+ a1 v1 t
       for (int i = 0; i < 200; i++) {# Z# w, Y& @5 ?
           if (count1[i] + count2[i] + count3[i] >= 2) {5 I& X. l+ E; g) e' i6 }
               result.add(i);
; O+ k- @+ @  f' I3 A. t          }' N; k: \; p& S: H* ]
      }. D: N! g4 ^) {/ f( x- n, O0 e
       return result;
! I2 B: X/ P4 z! y/ G8 C( a  }
0 K0 ?& p! ^+ t# P% d}
8 `( }$ Q7 E' C% V0 ^
* C0 b; C4 ]# \; _$ G【 NO.2 获取单值网格的最小操作数】# i% u& U' w( A% S# u% ?
9 M9 z' ]0 x+ b0 L& l
解题思路
% C& G$ E. K; I. ~网格可以转换成一维数组,然后排序。+ |# E# |/ x' @: }
  s' o3 Q' O5 S. Y6 P
不返回 -1 的条件就是:任意两个元素的差都是 x 的整倍数,我们只需要检查相邻元素即可。3 j) d5 Q4 Z8 u. Z  C4 |7 W; ~0 n4 N
4 U' A5 U- ~8 Z1 U; P  w
然后枚举最终的唯一值,可以利用前缀、后缀和快速计算出把所有数字变成该值的操作次数。8 G+ C/ j8 k+ Y5 J/ K& t. d
! w. p6 ~2 p! i( M2 q0 ?% [
代码展示* B& o+ o& c) Q* u9 \4 r, F1 g
5 a. h( d, D  _* f/ g$ v
class Solution {+ m1 ?# w$ E$ c* x4 ^
   public int minOperations(int[][] grid, int x) {$ Z; r* T0 X0 W% c6 j3 }9 X( B
       int[] arr = new int[grid.length * grid[0].length];
, A( q1 n* y( u0 ^       for (int i = 0; i < grid.length; i++) {4 X) u( o: F/ P* ]" M% T+ E5 \: w
           for (int j = 0; j < grid[0].length; j++) {- N/ `+ w: y: H6 E5 ^0 g% @
               arr[i * grid[0].length + j] = grid[i][j];
. o& H$ N* y2 l2 Q( f: Y          }( u: b" T4 K4 z5 X$ f, D
      }3 d7 D7 w; y5 M0 q
       Arrays.sort(arr);* H3 f$ y- t9 x
       for (int i = 1; i < arr.length; i++) {
3 e* l, p+ P4 D$ r5 h: n           if ((arr[i] - arr[i - 1]) % x != 0) {' e5 u; T  e0 P, {  E3 R
               return -1;
( D. M! ]1 n! C8 r' l7 Y0 S          }4 p7 m! \0 c+ B' C7 `' |9 ?
      }
+ }! l& s) v0 D: v! R/ s7 M' l       int suffixSum = Arrays.stream(arr).sum();9 z* I2 u5 M. t, f" V) a3 `8 {
       int prefixSum = 0;: v* n3 e6 {3 y; }' v) w! V$ y
       int result = suffixSum / x;
* h! n' x8 T' P( W" X" W% U% Z: x5 j       for (int i = 0; i < arr.length; i++) {; I6 j/ A5 [- n2 \
           suffixSum -= arr[i];3 w. t3 Z+ K1 G$ g: ]. u
           result = Math.min(result, calc(prefixSum, suffixSum, i, arr.length - i - 1, arr[i], x));; U& j7 A7 y- D5 c' V
           prefixSum += arr[i];8 m' t$ m  |$ }
      }5 k0 l/ ]+ l6 Y5 Z" Y& `! K1 K0 O
       return result;
) c8 Q# y7 t% m$ r( Z4 s5 [  }
7 ?4 ~& p3 z" y& h' o  q8 C6 ^* [( s, R
   private int calc(int prefixSum, int suffixSum, int prefixNum, int suffixNum, int target, int step) {* L/ d5 R) V% L; Y% ]" \: d0 f
       return (prefixNum * target - prefixSum) / step + (suffixSum - suffixNum * target) / step;
! w* w3 w, x/ Y4 F4 U4 g  }  {" l8 \  |" N: q+ A
}) I/ w1 m# G! H- f

8 ]' B- O2 A4 R* N6 n【 NO.3 股票价格波动】6 X7 z* i$ t( f' V* x. z; @' f

0 f% ^' Q$ B* l* u解题思路
, ?! E9 S8 i" i, F使用两个 TreeMap 即可,一个储存时间戳到价格的映射,一个储存价格出现了多少次。( D2 y+ {3 U' S' r8 `7 O

: z: S) E/ \! n, a) Z代码展示+ s. P8 Q; t: n+ y1 H  U

! t# K( U( `  [: |2 Zclass StockPrice {
) U3 J5 q! Z% x/ D0 y4 n2 o; u& g) c2 l
   TreeMap<Integer, Integer> timestampToPrice;
- g; n2 b7 g0 f0 G6 g% S- _$ i   TreeMap<Integer, Integer> priceCount;
* W) z, l; h9 N6 I- V$ b. A
. t  N7 @9 O( r' C   public StockPrice() {4 ^6 F; x1 G/ C2 w! g* l
       timestampToPrice = new TreeMap<>();
+ l* A8 L! ~) {; R; S8 D  j: g       priceCount = new TreeMap<>();9 T2 }& R, b* M$ \9 ^
  }
$ l7 Q# w: H9 C( X8 ^
, s- N! B) s; `   public void update(int timestamp, int price) {
, `. \, `) |# C8 _; x5 \' ~       if (timestampToPrice.containsKey(timestamp)) {/ r; A2 G% T% c' x0 q$ y" I
           int oldPrice = timestampToPrice.get(timestamp);4 q% h2 @0 A* `, k/ H3 A0 P" o
           int count = priceCount.get(oldPrice);
% t4 A% U2 K# f$ N5 ?' S           if (count == 1) {7 M0 X$ n, P' e1 M
               priceCount.remove(oldPrice);
$ v) b" {  |1 |% |* N          } else {- j2 |2 t) h$ x1 j: h' K* F7 S
               priceCount.put(oldPrice, count - 1);
" ~0 w- H  o4 M' m6 a7 a6 r          }( `: F( g# s2 V
      }
, _" ?- r$ ^4 s: S" n       timestampToPrice.put(timestamp, price);
6 H- K7 p1 q! }! y4 L- l, v       priceCount.put(price, priceCount.getOrDefault(price, 0) + 1);, z3 r  F/ F3 V: o8 A6 ]+ I" a
  }
5 T' o; B+ R% G! G1 u0 A0 C' y  o, M) T! h
   public int current() {
' A! U) {  d* q: f       return timestampToPrice.lastEntry().getValue();8 b: {- H6 m8 z
  }( g( R2 G* F. f6 b4 ?5 f4 ^

+ J  p# H8 R0 @& Z   public int maximum() {
2 t2 z0 N( P0 V; o  k( t8 t: |       return priceCount.lastKey();
# H" P4 x$ g* u* h9 u) \: A1 [* \  }" a) F, L* \; u7 }7 s) p& G
; [) x. M/ _0 w, G
   public int minimum() {( }7 ?+ B2 t8 I: M- Y/ Q5 s
       return priceCount.firstKey();, M1 N, `8 D( ~+ @% p
  }: Q2 A0 L( Q+ d) \
}- Z/ a  |2 Y6 d/ p% D8 l4 b* A) i
/ }* D+ S. H* _( k
【 NO.4 将数组分成两个数组并最小化数组和的差】8 b$ \* u  v7 Y* S( D' p1 J* _$ [" g
8 R- u( e& ?7 J" u+ P; Z
解题思路/ w8 k; v6 N( I& w& {3 j5 v
- W+ [3 T8 L- I1 H. c/ B
枚举 + 双指针,具体思路见代码注释。
* D0 i! l% K) c
0 B  j& F# w+ }代码展示
0 E) j  F3 b# g3 X( |' \. c4 P  I3 Y, G
class Solution {; F+ R+ ^: a  n' ]7 `4 }) Y5 y
   public int minimumDifference(int[] nums) {% c7 Y$ D" |, E8 U" F; @
       int half = nums.length / 2;
5 T& J% K( ?5 ~       int[] half1 = Arrays.copyOf(nums, half);
$ g+ ^8 d. B; c2 x       int[] half2 = new int[nums.length - half];9 ~/ N0 O2 D- d* |) C% R5 x
       System.arraycopy(nums, half, half2, 0, half2.length);: U: @. i; E+ g$ [
       // sums1[i] 表示从 half1 中选出 i 个数字得到的和的所有情况,并且从小到大排序, K- c# k- U2 h
       List<List<Integer>> sums1 = getSums(half1);! p9 a5 q7 K! H- G
       List<List<Integer>> sums2 = getSums(half2);6 R  f# V; t# r' \4 C
       int sum = Arrays.stream(nums).sum();! p! z1 z; s1 n3 p- G7 m
       int result = 0x3f3f3f3f;; C+ A) P1 u4 R% c" ~% q
       // 枚举从 half1 中选出 select 个,则需要从 half2 中选出 half - select 个
: a5 p: H# E& e+ f+ r: J       for (int select = 0; select <= half; select++) {( ^1 K3 b/ w. ^6 ~9 b% P9 i4 F* e
           List<Integer> half1Sums = sums1.get(select);
: _2 d9 _3 D% M) y) g; y           List<Integer> half2Sums = sums2.get(half - select);9 I; T) b' Y2 _9 H2 R- X
           // 从 half1Sums 和 half2Sums 中各选出一个数字,使得它们的和最接近 sum / 2' ]. }5 U6 p, b1 M
           int i = 0, j = half2Sums.size() - 1;" f# |' M# g4 O. E* b" r
           result = Math.min(result, Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2));9 ]* @6 v4 }( F# g  r/ c5 F3 ?
           for (; i < half1Sums.size(); i++) {
# b1 o- [4 B! j4 c0 s/ ~               while (j > 0 && Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j - 1)) * 2) <= Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2)) {; v6 G; D+ o$ D+ X1 |# @4 M" @4 ~
                   j--;/ U1 J/ P+ }  t3 X. c
              }7 \! L# o: P9 z" s8 ^" w+ c. G5 y9 I
               result = Math.min(result, Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2));0 r( x1 y, r) N4 M2 s/ [# A
          }
- Y! ~+ d0 z& {9 E6 H      }" N: H& N7 S7 ~% @
       return result;
, K3 D. c: }9 N2 p  }; d& u* N6 N4 u5 b. K# e/ k

4 Y5 _$ f# L, [' N   // getSums 求出 nums 的所有子集的和$ Y1 V! X5 g# l! Y) W9 D
   // 返回 List<List<Integer>> sums* N$ S( e; m% H  g' E
   // 其中 sums[i] 表示 nums 的所有大小为 i 的子集的和. a+ P" Y$ r9 g
   // 去重并排序
1 c9 h( t% Z! R" X' ?   private List<List<Integer>> getSums(int[] nums) {. _1 s/ \$ y/ i- f
       int n = nums.length;4 ^% \! T" z' `3 k
       List<Set<Integer>> set = new ArrayList<>();" J2 T4 M' |$ J2 W2 T# I4 B
       List<List<Integer>> sums = new ArrayList<>();4 z; R5 ?# j' u( @/ F( @) S
       for (int i = 0; i <= n; i++) {5 i+ S5 i3 |! W3 y
           sums.add(new ArrayList<>());
/ y6 N, f7 o/ j8 w; ?; y           set.add(new HashSet<>());
( j5 ?/ L5 n5 a" H1 x! R      }
9 W% \1 e+ V- k! o5 B' \7 ^       for (int i = 0; i < (1 << n); i++) {0 t* F  c9 \; y# T6 q
           int sum = 0;
0 z6 _0 W* L0 n- Z) M           int num = 0;
9 ~( F/ q. n! J" U0 S           for (int j = 0; j < n; j++) {) H  O# L/ E. E, z9 j( r
               if ((i & (1 << j)) != 0) {
, e+ {* W( P6 X& u5 Z& D# }                   sum += nums[j];
; q' v# o- c8 T                   num++;
' @; O) F  H1 Z( x5 o  i              }0 C/ q7 R2 E9 l% [+ a
          }
3 }5 ^% e7 W6 l5 R0 @" _5 I7 b           if (!set.get(num).contains(sum)) {
/ G" g( U9 r# S9 m, ^5 ~' e               set.get(num).add(sum);$ y) U  n5 G# @' J0 i& v: p% U
               sums.get(num).add(sum);
+ b9 g/ P" |( u; i! B" F7 {7 c          }
6 l6 d" c# x3 o( X- J      }% b' L- o; h/ u6 h1 N: `  E7 Y5 E) O
       for (int i = 0; i < n; i++) {% M6 {) H; W) B# v9 J
           Collections.sort(sums.get(i));; J0 P! g: M1 U
      }
* |  U+ l  N) l; _. ^1 P, d9 i9 B       return sums;; d  l7 t: m% E' Z3 T( Z7 X
  }
$ @' {* o/ @6 V+ P* D2 e}
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

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