👀 문제
https://leetcode.com/problems/edit-distance/
👊 도전
1. 설계
- DP를 이용한다.
2. 구현
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
*
* @author HEESOO
*
*/
class Solution {
public int minDistance(String word1, String word2) {
int m=word1.length();
int n=word2.length();
int[][] dp=new int[m+1][n+1];
for(int i=0;i<=m;i++) dp[i][0]=i; // 초기화
for(int j=0;j<=n;j++) dp[0][j]=j;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
// i, j 문자가 같으면 변경 필요 없음
if(word1.charAt(i-1)==word2.charAt(j-1)) dp[i][j]=dp[i-1][j-1];
else{ // 다른 경우
int insert=dp[i][j-1];
int delete=dp[i-1][j];
int replace=dp[i-1][j-1];
dp[i][j]=Math.min(insert, Math.min(delete, replace))+1; // 셋 중 가장 작은 값+1(이번에 수행한 것)
}
}
}
return dp[m][n];
}
}
3. 결과
🤟 성공 🤟
4. 설명
- DP를 이용한다
- word1는 i, word2는 j로 문자를 체크한다.
- dp[i][j]: word1의 i번째, word2의 j번째를 바꿀 때, 최소 횟수(이전까지의 횟수에 누적)
- i, j는 1부터 시작한다. 따라서 charAt()을 쓸 때는 -1해야한다.
- 빈 문자열과 word를 비교할 수도 있으므로 m+1, n+1로 배열을 선언하여 0~m 또는 n까지 체크할 수 있게 하였다.
- i==0 또는 j==0인 곳은 해당 word와 빈 문자열을 비교하는 것과 같다. 따라서 내 word와 같게 계속 삽입하면 되므로 그 횟수로 초기화한다.
- i와 j를 변경하는 세 가지 방법 insert, delete, replace 중, 처음부터 현재 i, j까지를 고려했을 때, 가장 적은 횟수가 드는 것을 선택하고, 여기에 지금 수행한 것(셋 중 하나)를 +1한다.
- insert: i 자리에 알파벳을 추가하므로, j는 i+1에서 체크한다. 다시말하면 j-1과 i를 체크하는 것과 같으므로 dp[i][j-1]이다.
- delete: i를 삭제하는 것이므로 j는 i+1와 비교한다. 즉, j-1과 i를 비교하는 것과 같으므로 dp[i][j-1].
- replace: i를 j로 바꾸는 것이므로 이전의 i-1, j-1을 그대로 가져오면 된다. dp[i-1][j-1].
- 셋 중 가장 작은 값을 Math.min()을 두 번 사용함으로써 뽑고, 여기에 현재 수행한 횟수 1을 더한다.
- 마지막 dp[m][n]에 최종으로 min 값이 들어있다.