Skip to content

Commit 8e221d8

Browse files
committed
Decode Ways
1 parent 582101e commit 8e221d8

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed

β€Ždecode-ways/JisooPyo.ktβ€Ž

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.shouldBe
4+
import org.junit.jupiter.api.Test
5+
6+
/**
7+
* Leetcode
8+
* 91. Decode Ways
9+
* Medium
10+
*
11+
* idea:
12+
* Dynamic Programming
13+
* μˆ«μžλŠ” μ΅œμ†Œ ν•œ μžλ¦¬μ—μ„œ μ΅œλŒ€ λ‘μžλ¦¬κΉŒμ§€ 해석될 수 μžˆλŠ” μ—¬μ§€κ°€ μžˆλ‹€.
14+
* λ”°λΌμ„œ "1111"μ΄λΌλŠ” λ¬Έμžμ—΄μ΄ κ°€μ§ˆ 수 μžˆλŠ” Decoding 경우의 μˆ˜λŠ” λ‹€μŒ 두 κ°€μ§€κ°€ 될 수 μžˆλ‹€.
15+
* - "111"이 κ°€μ§€λŠ” Decoding 경우의수 + "1"
16+
* - "11"이 κ°€μ§€λŠ” Decoding 경우의 수 + "11"
17+
* Note.
18+
* "0"이 κ°€μ§€λŠ” Decoding 경우의 μˆ˜λŠ” μ—†λ‹€λŠ” 것.
19+
* "1"λΆ€ν„° "26"κΉŒμ§€λ§Œ λ””μ½”λ”© κ°€λŠ₯ν•œ 것.
20+
*/
21+
class DecodeWays {
22+
/**
23+
* Runtime: 17 ms(Beats: 11.98 %)
24+
* Time Complexity: O(n)
25+
*
26+
* Memory: 38.81 MB(Beats: 6.08 %)
27+
* Space Complexity: O(n)
28+
* - s의 길이만큼의 DP λ°°μ—΄(dp) ν•„μš”
29+
*/
30+
fun numDecodings(s: String): Int {
31+
val dp = IntArray(s.length)
32+
33+
// μ΄ˆκΈ°ν•­: dp[0]
34+
dp[0] = if (s[0] == '0') 0 else 1
35+
if (s.length == 1) return dp[0]
36+
37+
// μ΄ˆκΈ°ν•­: dp[1]
38+
val oneDigit = dp[0] * (if (s[1] == '0') 0 else 1)
39+
val twoDigitNumber = (s[0] - '0') * 10 + (s[1] - '0')
40+
val twoDigit = if (twoDigitNumber < 10 || 26 < twoDigitNumber) 0 else 1
41+
dp[1] = oneDigit + twoDigit
42+
43+
if (s.length == 2) return dp[1]
44+
45+
// λ‚˜λ¨Έμ§€ ν•­ 계산
46+
for (i in 2 until s.length) {
47+
// ν•œ 자리 숫자둜 ν•΄μ„ν•˜λŠ” 경우
48+
val oneDigit = dp[i - 1] * (if (s[i] == '0') 0 else 1)
49+
50+
// 두 자리 숫자둜 ν•΄μ„ν•˜λŠ” 경우
51+
val twoDigitNumber = (s[i - 1] - '0') * 10 + (s[i] - '0')
52+
val twoDigit = dp[i - 2] * (if (twoDigitNumber < 10 || 26 < twoDigitNumber) 0 else 1)
53+
54+
dp[i] = oneDigit + twoDigit
55+
}
56+
57+
return dp[dp.lastIndex]
58+
}
59+
60+
/**
61+
* early return, λ²”μœ„ μ—°μ‚°μž, λ©”μ„œλ“œλ₯Ό ν™œμš©ν•˜μ—¬ 가독성 κ°œμ„ ν•˜κΈ°
62+
*/
63+
fun numDecodings2(s: String): Int {
64+
if (s[0] == '0') return 0
65+
if (s.length == 1) return 1
66+
67+
val dp = IntArray(s.length)
68+
// μ΄ˆκΈ°ν•­: dp[0]
69+
dp[0] = 1
70+
71+
// μ΄ˆκΈ°ν•­: dp[1]
72+
val oneDigit = dp[0] * (if (s[1] == '0') 0 else 1)
73+
val twoDigitNumber = (s[0] - '0') * 10 + (s[1] - '0')
74+
val twoDigit = if (twoDigitNumber in 10..26) 1 else 0
75+
dp[1] = oneDigit + twoDigit
76+
77+
if (s.length == 2) return dp[1]
78+
79+
// λ‚˜λ¨Έμ§€ ν•­ 계산
80+
for (i in 2 until s.length) {
81+
// ν•œ 자리 숫자둜 ν•΄μ„ν•˜λŠ” 경우
82+
if (s[i] != '0') {
83+
dp[i] += dp[i - 1]
84+
}
85+
86+
// 두 자리 숫자둜 ν•΄μ„ν•˜λŠ” 경우
87+
val twoDigitNumber = (s[i - 1] - '0') * 10 + (s[i] - '0')
88+
if (twoDigitNumber in 10..26) {
89+
dp[i] += dp[i - 2]
90+
}
91+
}
92+
93+
return dp.last()
94+
}
95+
96+
@Test
97+
fun test() {
98+
numDecodings("12") shouldBe 2
99+
numDecodings("226") shouldBe 3
100+
numDecodings("06") shouldBe 0
101+
numDecodings("2101") shouldBe 1
102+
}
103+
}
104+
/**
105+
* κ°œμ„ ν•  점:
106+
* 1) κ³΅κ°„λ³΅μž‘λ„ O(1)둜 κ°œμ„ 
107+
* 배열을 λ§Œλ“€μ§€ μ•Šκ³  "μ „μ˜ 경우의 수"와 "μ „μ „μ˜ 경우의 수"λ₯Ό λ³€μˆ˜ν™”ν•˜λ©΄ 곡간 λ³΅μž‘λ„κ°€ O(1)둜 κ°μ†Œλ  수 μžˆμŠ΅λ‹ˆλ‹€.
108+
* 2) μ—°μ‚° 수 쀄이기
109+
* λ‹€λ₯Έ λΉ λ₯Έ 풀이(1ms)λ₯Ό λ³΄λ‹ˆ 두 자리 숫자둜 ν•΄μ„ν•˜λŠ” κ²½μš°μ— 숫자둜 λ³€ν™˜ν•˜μ§€ μ•Šκ³  character만 λΉ„κ΅ν•΄μ„œ
110+
* (s[i] == '1' || s[i] == '2' && s[i + 1] < '7') 10 <= x <= 26 인지 확인함. 이 경우 더 적은 연산을 μˆ˜ν–‰.
111+
*/

0 commit comments

Comments
Β (0)