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

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

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

UWCSSA提醒您:

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

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

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

登录后可回复主题

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

x
【 NO.1 至少在两个数组中出现的值】7 l% ?$ [7 `2 ^# `, E

  e& ?8 F2 D. }! e$ h" a3 g解题思路
5 G4 f5 A7 s' K( {. `( B& @/ o) ?签到题。  `) d* ~. \5 M8 I1 W

& q) [, }* b8 {6 h* n, M代码展示# L$ w* ]1 }3 L. n' T

, L+ C, N. ^) T& u; L9 W  pclass Solution {5 ?& [$ `+ }4 Q
   public List<Integer> twoOutOfThree(int[] nums1, int[] nums2, int[] nums3) {
( I: z( ~$ w' e+ G       int[] count1 = new int[200];- e$ a7 d# x: b) E
       int[] count2 = new int[200];
$ B0 {4 N( ~2 F( R7 F       int[] count3 = new int[200];% |+ L" ?5 @$ K$ Q0 \" s
       for (int n : nums1) {
0 D3 @4 F3 E% A; u& Y" _  {           count1[n] = 1;* H! D* o9 m* R5 W- O  p5 M+ d1 |
      }
6 T' F! A& g# ~5 o       for (int n : nums2) {
( D. A- \6 D7 ?) D  f$ y% z           count2[n] = 1;, \+ X, _1 K3 T& M
      }, v2 `, k+ @. f
       for (int n : nums3) {
3 ?) G" O* p7 m0 d9 r           count3[n] = 1;. c; k& e6 D9 @- h
      }
$ Y$ C# P8 ~  S9 S( t5 N  k0 Y       List<Integer> result = new ArrayList<>();
3 r4 |/ d% Y, C. d       for (int i = 0; i < 200; i++) {# l8 w; T0 b3 S+ D; s! x
           if (count1[i] + count2[i] + count3[i] >= 2) {- D# d' w5 V" l2 D/ o* z8 a
               result.add(i);- Q6 {- M# Z' k: K  \' y; s1 k: J
          }
* j& g  a( k: x+ |      }
" G: Z- [9 s% C1 S/ s       return result;, l  p% P- s, h  \6 M
  }
6 _8 d$ S3 @+ R- f" b}- {0 O  z5 {0 e$ u9 {

/ N4 V! w* [/ _4 k2 l8 @【 NO.2 获取单值网格的最小操作数】/ P( ^" S& Q# u7 y; S! o: s% {8 u
: r* A+ K4 d2 m# `  N
解题思路
# r8 V( j# L. Z- O" D$ Q网格可以转换成一维数组,然后排序。2 p8 H: O: F5 L/ R* B! Z6 t5 |

5 ]0 r$ M0 L% T$ Y$ A; A" [0 v8 F不返回 -1 的条件就是:任意两个元素的差都是 x 的整倍数,我们只需要检查相邻元素即可。! p( [5 [9 L* i9 C# W
7 |1 i' {  k8 W& `* }, c
然后枚举最终的唯一值,可以利用前缀、后缀和快速计算出把所有数字变成该值的操作次数。
: L: M8 j6 [# n0 K" T. f! U/ Q- p% B- W5 o
代码展示6 j9 _; W2 L2 g$ P; T6 p% K

* I' G, P2 ]% B! G3 `( [* Yclass Solution {' `! r0 v) D- a8 k: c% ^% J4 P
   public int minOperations(int[][] grid, int x) {# n( c  D, a5 A3 q- ~
       int[] arr = new int[grid.length * grid[0].length];
( N9 P$ g% T+ n! ~6 \       for (int i = 0; i < grid.length; i++) {
6 e- K2 C2 ^* O, z  U( i& J" a           for (int j = 0; j < grid[0].length; j++) {
8 \: D& |8 I9 ?: `8 E* i               arr[i * grid[0].length + j] = grid[i][j];7 S+ o7 w! O3 c0 @
          }( K6 k9 v7 B7 X& ?- M9 w
      }
1 d2 @. _# p% r1 B1 o       Arrays.sort(arr);4 |  V+ V. ~; w( F. [5 Q9 }
       for (int i = 1; i < arr.length; i++) {3 }# f, ?% R& R: }8 j
           if ((arr[i] - arr[i - 1]) % x != 0) {: O1 c1 S9 i+ ?7 O' o$ f
               return -1;+ \" C* w4 y4 ?. f7 _4 |6 h" J
          }; I- z: h5 |, E& U% Q
      }) T6 V! ?' A7 T
       int suffixSum = Arrays.stream(arr).sum();: m6 J9 D) @$ f* E7 M1 q
       int prefixSum = 0;% j( {, y6 X% b
       int result = suffixSum / x;
3 `. q1 `8 E; B8 B       for (int i = 0; i < arr.length; i++) {
6 D- L- k, S1 z" Y. j           suffixSum -= arr[i];
& f6 a9 m1 e1 J# }! |- H/ l1 g& ^3 D           result = Math.min(result, calc(prefixSum, suffixSum, i, arr.length - i - 1, arr[i], x));
6 ]* l8 u4 k* B5 z. G1 u5 W           prefixSum += arr[i];
) ^/ r4 D$ ]1 [4 a% x  l! H  I      }
- i/ L# d& r5 ~       return result;
$ e& u  J# Q7 O  |  }9 [9 ]) |  z9 E

- T6 U" `6 k% B$ o" g6 Y1 C   private int calc(int prefixSum, int suffixSum, int prefixNum, int suffixNum, int target, int step) {
. N, L/ x* X* c9 ^+ P       return (prefixNum * target - prefixSum) / step + (suffixSum - suffixNum * target) / step;5 z' u' U0 C/ R6 g7 B2 b9 P4 B
  }- [7 H+ s7 ?, t1 T1 l, C9 K9 u, A0 f
}5 T. Z3 R  S4 v2 i( O: e
& ~8 E, u/ f9 j
【 NO.3 股票价格波动】
4 e& g. D3 f1 T+ v
1 s/ ]) x4 y  k" Z解题思路. b& ^* g1 D. b. Q
使用两个 TreeMap 即可,一个储存时间戳到价格的映射,一个储存价格出现了多少次。
% p5 l6 r; ~3 L7 R: z1 F. K0 r9 v' ^3 L9 I
代码展示* U: t6 i" [0 N) ^2 ?% n
/ W, Z1 Q* F4 W4 d$ x: I
class StockPrice {# O# W0 ^# k' ?- c  E. z' R4 T

3 ?) z* w( J# j6 o   TreeMap<Integer, Integer> timestampToPrice;
; @+ v( K, E0 |   TreeMap<Integer, Integer> priceCount;' W- r% ]6 C4 T- Y+ E4 T1 Q

' D0 S/ _( ?7 {9 z   public StockPrice() {
; h  j0 q/ S" V: `6 {+ I% j1 c! f       timestampToPrice = new TreeMap<>();$ C. _2 u2 ~9 |# }" i
       priceCount = new TreeMap<>();
6 n( ~, C4 v! G& g  }
1 f1 v2 F2 r# ?
/ c: b( u( a- r% ?0 p) E+ a   public void update(int timestamp, int price) {; ~0 d. b' ?# n8 g
       if (timestampToPrice.containsKey(timestamp)) {
3 J. E* l4 W5 o& k           int oldPrice = timestampToPrice.get(timestamp);7 }! G& i+ t1 G+ e
           int count = priceCount.get(oldPrice);+ L& x5 N1 {" W# Q' L8 a- K
           if (count == 1) {( A" z* ]: p& g+ S2 e# S
               priceCount.remove(oldPrice);
( @# ?. ~1 R# ~6 Z2 w1 W9 m          } else {
' {" Y0 Q, s# i               priceCount.put(oldPrice, count - 1);
; N  R% m8 l1 l, {* u          }' N! T4 g3 e5 z' U) U  D
      }+ M; N, ?' N" z) H% |3 T8 u0 D
       timestampToPrice.put(timestamp, price);
+ n! _0 T8 n/ n2 p4 N: ^       priceCount.put(price, priceCount.getOrDefault(price, 0) + 1);
, Y/ V: a% ~# z/ W7 C7 o  }6 L, Q- T( ~  d; J- t! ?) e

6 V) l8 Z" e  G! p% f2 `   public int current() {3 j$ o5 L- u5 R! E
       return timestampToPrice.lastEntry().getValue();
, o7 t- F; [9 s1 N' w; O  }( D; q9 U' k+ u9 I. f

" C1 t  u3 E+ N- s( o   public int maximum() {
0 j: K8 Z3 Z1 D) Q+ C- q0 c       return priceCount.lastKey();$ t: X* a( g; P- ^
  }
* Z# [' [) B3 L+ S3 o8 ?
* k, D/ [7 r& g6 l$ V& }' L$ s/ k   public int minimum() {
. L6 @  k4 v/ ?$ F       return priceCount.firstKey();1 d* \& j; C2 J' M$ P) g6 T5 W
  }
) F% A; ]+ k  \- \8 ?}
, L2 a0 z( R- X' i! k) e( @; @5 s$ k4 k
【 NO.4 将数组分成两个数组并最小化数组和的差】1 I/ @7 N4 _0 ?

5 w3 X) t% Z5 q+ ~) V解题思路
6 v' U) q7 B' Q" ~3 W$ z9 y- O  I4 D2 k, z7 E* S
枚举 + 双指针,具体思路见代码注释。
# \* f% ]- m8 d
9 L8 t1 g* b  U7 s6 w8 W% X* S代码展示
0 Y' y  j% K% B9 _( h
: q/ d9 D: N* hclass Solution {4 ]# [/ p9 Y8 V: c5 L" k
   public int minimumDifference(int[] nums) {
8 n6 ?" {8 `) I& ~       int half = nums.length / 2;3 S% N% F* _. e' {- o' h2 F
       int[] half1 = Arrays.copyOf(nums, half);' \& @9 g9 Y" B- W* T/ Y
       int[] half2 = new int[nums.length - half];7 T' o1 c2 A% |( |% U9 J
       System.arraycopy(nums, half, half2, 0, half2.length);
2 @% Y' W2 P+ Y/ S1 K9 X       // sums1[i] 表示从 half1 中选出 i 个数字得到的和的所有情况,并且从小到大排序
! I7 ^7 g* g- n( z4 z0 R! _6 z; y$ A       List<List<Integer>> sums1 = getSums(half1);1 q, F0 g8 D) v3 e# ?
       List<List<Integer>> sums2 = getSums(half2);  R7 a* e/ n9 X! k5 O/ e) h
       int sum = Arrays.stream(nums).sum();% n* a0 }6 l% R6 T0 H' u
       int result = 0x3f3f3f3f;: }0 O' e- G( g4 ~2 b. k
       // 枚举从 half1 中选出 select 个,则需要从 half2 中选出 half - select 个0 F' b, ^$ f0 m4 s
       for (int select = 0; select <= half; select++) {
& u, L1 ~5 Y; u' a0 h7 [           List<Integer> half1Sums = sums1.get(select);/ [" H! B/ P# e3 S6 U$ y, I( `4 d
           List<Integer> half2Sums = sums2.get(half - select);
* [! p0 u% h7 V, l+ L           // 从 half1Sums 和 half2Sums 中各选出一个数字,使得它们的和最接近 sum / 2/ o+ I& t- V" m6 `0 E
           int i = 0, j = half2Sums.size() - 1;8 Y7 W9 d8 E+ n7 W: S/ \7 ?  I* x; F
           result = Math.min(result, Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2));
4 C1 _2 i+ g. T           for (; i < half1Sums.size(); i++) {( J, s# W3 j4 H' B& T3 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)) {
/ t1 |& Q# I. i; p9 J                   j--;. E, i3 p0 Z7 [$ H: m
              }, G) I' _2 L- K" N1 @
               result = Math.min(result, Math.abs(sum - (half1Sums.get(i) + half2Sums.get(j)) * 2));
! U# B. [7 x& A- V' w# q: ^3 `; @          }
7 H( ]; M" z. w' C( p' B      }
3 [, c& H9 v- J* g6 A! c. s5 p       return result;
$ _2 H  w# P+ C* Q$ n0 _' E. m! F( X  }( m0 e6 @- H- M) z9 z( h

  y; l, ?9 c: H+ Y* m6 g. N   // getSums 求出 nums 的所有子集的和& E2 u+ c0 P% k! j
   // 返回 List<List<Integer>> sums) m1 v  o! h5 A' J! o
   // 其中 sums[i] 表示 nums 的所有大小为 i 的子集的和
2 S& |$ B9 f' ~5 b   // 去重并排序
! e0 a3 L6 G/ l; ]1 F) y   private List<List<Integer>> getSums(int[] nums) {
( {3 |' Y5 p: ?8 J! n' D       int n = nums.length;
7 F. G8 W0 ^" Z0 t- u& O% H% X       List<Set<Integer>> set = new ArrayList<>();
; H# G7 J! O9 b       List<List<Integer>> sums = new ArrayList<>();) C+ J4 B3 S, K) a
       for (int i = 0; i <= n; i++) {
7 M: e( v1 @6 u+ I# E+ T( [           sums.add(new ArrayList<>());, w4 g1 U- P2 O# v/ M. S
           set.add(new HashSet<>());
4 j% H) n# _8 s9 Y, [% ]      }
. p4 s) k5 W4 t0 E4 d3 A       for (int i = 0; i < (1 << n); i++) {
0 j  i+ b6 D2 s7 L           int sum = 0;
' ], E7 C. Z6 A1 F0 a) \           int num = 0;9 X8 t8 Q% r5 W
           for (int j = 0; j < n; j++) {# @5 {+ u+ B) V0 b
               if ((i & (1 << j)) != 0) {
; c* ?( b. H9 K( |+ l                   sum += nums[j];# P+ \( Q# y; {' k
                   num++;
0 C9 \6 d, {. x! [6 W: I" L              }( d' _: A' r$ j* g: L8 j
          }
8 W2 W6 h% i7 A# ^           if (!set.get(num).contains(sum)) {
/ ]8 Q: v! S& l: A+ b               set.get(num).add(sum);
. \! J3 T& V9 H' \  ]# h& V               sums.get(num).add(sum);8 S# R( W3 o3 {9 J2 ?
          }, s, b$ Z  Z1 q! \) K% p. H
      }
8 k/ H. Z& T  p) J       for (int i = 0; i < n; i++) {
, Z/ {6 q  _' ^8 Q4 [           Collections.sort(sums.get(i));
# X2 h; e) O8 L' [      }
6 y( o8 E9 n0 M4 K& W       return sums;
. U7 r. Q: I3 y$ ]2 T$ W# w  }; \/ l/ K* m4 C$ I  L
}
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

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