1531. String Compression II

  • ν˜„μž¬ λ¬Έμžμ—΄μ„ μΆ”κ°€ν•˜λŠ” 경우, μΆ”κ°€ν•˜μ§€ μ•ŠλŠ” 경우둜 λ‚˜λˆ„μ–΄ μž¬κ·€ 호좜둜 풀어보렀고 ν–ˆμ§€λ§Œ μ‹€νŒ¨.
    • μ‹œκ°„ 초과 + μ˜€λ‹΅
  • λ¬Έμžμ—΄μ˜ μ•žμͺ½ λΆ€ν„° 일뢀뢄을 μ·¨ν•˜μ—¬ ν•΄λ‹Ή λ¬Έμžμ—΄μ—μ„œ μ΅œλŒ€ k 개 만큼의 λ¬Έμžμ—΄μ„ μ‚­μ œν•œλ‹€κ³  ν–ˆμ„ λ•Œ encoding 된 길이λ₯Ό μ°¨λ‘€λŒ€λ‘œ κ΅¬ν•œλ‹€.
  • μ•žλΆ€λΆ„ λΆ€ν„° νŠΉμ • 길이 len둜 자λ₯Έ λ¬Έμžμ—΄μ— λŒ€ν•˜μ—¬ del 개의 λ¬Έμžμ—΄μ„ μ‚­μ œν–ˆμ„ λ•Œ encoding 된 길이λ₯Ό κ΅¬ν•œλ‹€.
    • λ¨Όμ € κ°€μž₯ μ‰¬μš΄ μΌ€μ΄μŠ€λŠ” ν˜„μž¬ λ¬Έμžμ—΄μ„ μ‚­μ œν•˜λŠ” κ²½μš°μ΄λ‹€.
      • ν˜„μž¬ λ¬Έμžμ—΄μ„ μ‚­μ œν•œλ‹€λ©΄ κ·Έ 값은 이전 길이 len - 1μ—μ„œ λ¬Έμžμ—΄μ„ ν•˜λ‚˜ 덜 μ‚­μ œν•œ 경우 del - 1와 λ™μΌν•œ encoding 길이λ₯Ό κ°€μ§„λ‹€ (μ™œλƒν•˜λ©΄ λ”ν•˜λŠ” λ¬Έμžμ—΄μ΄ μ—†κΈ° λ•Œλ¬Έμ—).
      • λ”°λΌμ„œ 값은 dp[len - 1][del - 1]λ₯Ό κ·ΈλŒ€λ‘œ μ“΄λ‹€.
    • κ·Έ λ‹€μŒμ€ ν˜„μž¬ λ¬Έμžμ—΄μ˜ κ°€μž₯ λ§ˆμ§€λ§‰ 문자 lastChar을 κΈ°μ€€μœΌλ‘œ λ™μΌν•œ λ¬Έμžμ—΄μ€ 남기고 λ‚˜λ¨Έμ§€λŠ” μ‚­μ œν•˜λŠ” κ²½μš°μ΄λ‹€ (제일 μ΄ν•΄ν•˜κΈ° μ–΄λ €μ› λ˜ λΆ€λΆ„).
      • λ§ˆμ§€λ§‰ λ¬Έμžμ—΄λΆ€ν„° μ—­μˆœμœΌλ‘œ μˆœνšŒν•˜λ©΄μ„œ λ§€ index l λ§ˆλ‹€ λ§ˆμ§€λ§‰ 문자 lastChar와 λ™μΌν•œ 문자의 수 (남길 것) addCount와 λ™μΌν•˜μ§€ μ•Šμ€ 문자의 수 (μ‚­μ œν•  것) delCountλ₯Ό μ„Όλ‹€.
      • νŠΉμ • index l을 κΈ°μ€€μœΌλ‘œ [0, len) ꡬ간을 λ‘κ°œλ‘œ λ‚˜λˆˆλ‹€ [0, l), [l, len).
      • (μ€‘μš”!!) 두 κ΅¬κ°„μ—μ„œ μ‚­μ œν•œ 문자의 μˆ«μžκ°€ del이 λ˜λ„λ‘ λ§Œλ“ λ‹€.
      • λ’·μͺ½ λΆ€λΆ„ [l, len)은 addCount 만큼의 λ¬Έμžμ—΄μ„ encoding ν•œ 길이가 κ²°κ³Ό 값이 λœλ‹€.
      • μ•žμͺ½ 뢀뢄은 λ‚˜λ¨Έμ§€ 남은 μ‚­μ œ 문자 수λ₯Ό μ±„μšΈ 수 μžˆλ„λ‘ μ•žμ„œ κ³„μ‚°λœ ꡬ간 [0, l)의 κ²°κ³Ό 쀑 del - delCount의 μ‚­μ œ 문자 숫자λ₯Ό κ°€μ§„ 것 dp[i][del - delCount]을 μ·¨ν•œλ‹€.
class Solution { int getCodedLength(int count) { if (count <= 1) return 1; int length = 1; while (count > 0) { ++length; count /= 10; } return length; } public int getLengthOfOptimalCompression(String s, int k) { int n = s.length(); // (sub string length, deleted character count) int[][] dp = new int[n + 1][k + 1]; for (int[] sub : dp) { // fill with maximum + 1 value Arrays.fill(sub, n + 1); } // zero length dp[0][0] = 0; for (int len = 1; len <= n; ++len) { char lastChar = s.charAt(len - 1); for (int del = 0; del <= k; ++del) { int addCount = 0, delCount = 0; for (int i = len - 1; i >= 0; --i) { if (s.charAt(i) == lastChar) ++addCount; else ++delCount; if (del - delCount >= 0) { // get result of sub string [0, i) // and add characters in sub string [i, len) int newValue = dp[i][del - delCount] + getCodedLength(addCount); dp[len][del] = Math.min( dp[len][del], newValue); } } if (del > 0) { // remove current character dp[len][del] = Math.min( dp[len][del], dp[len - 1][del - 1]); } } } return dp[n][k]; } }