알고리즘/프로그래머스 Level3

[프로그래머스,Java] Level3: 단어 변환

류창 2022. 8. 5. 16:24
반응형

문제분석:

 

목표:   begin 단어와   end 단어가 있으며,   단어는 한문자씩 바꿔가며 교체가가능하며,

End 단어로가는 최소 경로 단계를 구하세요.

 

 

이 문제는 완전 탐색이다.

 

최소 경로 단계를 구하는 문제이므로,  BFS가 좀 더 바람직한 풀이방식인것같다.

 

그런데 DFS 구현 난이도가 훨씬쉽다..

 

DFS와 BFS 둘다 구현하는 코드를 작성해보겠다.

 

 

DFS, BFS 공통부분:

 

문제의 조건중 단어가 1개만 바꿀수있으니   바꿀수있는지 검사하는 isChanged를 작성한다.

 

 

 

 

DFS 접근법:

 

DFS는 기본적으로  백트래킹을 사용하면서  Level(Depth 깊이)의 값을 표현할수가있다.

 

DFS의 백트래킹

DFS의 전략은   result의 크기를 매우크게잡아 

 

목표값을 찾으면   result의 값을 Math.Min으로 갱신을한다.

 

이러면 최소경로가 나온다.

 

하지만,  목표값을 못찾을경우도 존재하니,  result의 값이 그대로라면  return 0으로해준다.

 

매우 간단하다.

 

 

DFS 전체코드

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import java.util.*;
 
class Solution {
    
boolean[] visited;
String end;
int result=100;
    
    public int solution(String begin, String target, String[] words) {
        int answer = 0;
        
        visited= new boolean[words.length];
        
        int level=1;
        
        end = target;
     
        dfs(begin,words,level);
        
        if(result==100){
            return 0;
        }
        
        return result;
    }
    
    public void dfs(String begin, String[] words, int level){
            
            for(int i = 0; i<words.length;i++){
                if(isChanged(begin,words[i])&&!visited[i]){   
                    
                    if(words[i].equals(end)){
                         result=Math.min(result,level);
                     }
                    
                    visited[i]=true;           
                    dfs(words[i],words,level+1);
                    visited[i]=false;
                  
                }
            }
        
 
    }
    
    
    public boolean isChanged(String begin , String word){
        
        int count=0;
        
        for(int i=0;i<begin.length();i++){
            if(begin.charAt(i)!=word.charAt(i)){
                count++;
            }
            
            if(count>1){
                return false;
            }
            
        }
        
        if(count==1){
            return true;
        }
        
        return false;
        
    }
}
cs

 

 

 

BFS 접근법:

 

BFS는  Queue를 이용하여 구현을한다. (선입선출의 원리)

 

BFS는 재귀 (백트래킹)을 사용하지 않는다. 

그래서, 각 단어들의 Level(depth)를 파악하지 못한다.

 

우리 목적이 최소 Level을 탐색하는것이므로, BFS에 없는 Level를 따로 구현을해야한다.

 

Level를 표현하기위한 새로운 폼

 

BFS의 완전탐색이다.

원리는 Queue에서 원소를 하나씩 뽑고 그 원소에 관해 단어가1개바뀌는 조건이있다면 

다시 Queue넣어준다.

 

여기서 중요한데, BFS는 Depth를 파악못하니, 우리가 새로만든 Form을 통해, 

(단어, 깊이)를 함께 넣어준다.

 

 

BFS가 조금 더 빠른이유는 visited[i]=true; 작업만 있기때문이다.

 

이 문제같은경우는 백트래킹을 안해줘도 풀린다.

 

이게 무슨소리냐면, 첫 bigin 입력으로 3개의 단어가 탄생한다면,

각각 A세계선 B세계선 C세계선이 존재한다.

그 세계선마다 visited[]의 값이 각각 달라야한다.

 

하지만 이 문제는 그럴필요가없다. 

최소 경로를 구하는 문제므로, 어쨋든 그 경로를 빨리 방문하는걸 visited[]로 체크하기 때문에

 

굳이 visited[]=False로 세계선마다 독립성을 줄 필요가없는것이다.

 

 

BFS의 풀이:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import java.util.*;
 
public class StringAndIdx {
    String str;
    int idx;
    
    public StringAndIdx(String str, int idx) {
        this.str = str;
        this.idx = idx;
    }
}
 
class Solution {
    public int solution(String begin, String target, String[] words) {
        int answer = 0;
        
        boolean[] visited= new boolean[words.length];
        
        Queue<StringAndIdx> que = new LinkedList<>();
        
        que.add(new StringAndIdx(begin,0));
        int level=0;
        
        while(!que.isEmpty()){
            StringAndIdx temp =que.poll();
            begin=temp.str;
            int idx= temp.idx;
            
            
            for(int i = 0; i<words.length;i++){
                if(isChanged(begin,words[i])&&!visited[i]){
                    que.add(new StringAndIdx(words[i],idx+1));   
                      
                    System.out.println(words[i]);
                    visited[i]=true;
                    
                    if(words[i].equals(target)){
                          return idx+1;
                       }
                  
                }
            }
            
         
          
        }        
        
        
        return answer;
    }
    
 
    
    public boolean isChanged(String begin , String word){
        
        int count=0;
        
        for(int i=0;i<begin.length();i++){
            if(begin.charAt(i)!=word.charAt(i)){
                count++;
            }
            
            if(count>1){
                return false;
            }
            
        }
        
        if(count==1){
            return true;
        }
        
        return false;
        
    }
}
cs

 

반응형