문제


문제접근 방법
본 문제는 1부터 N까지 자연수 중에서 M개를 고른 수열(같은 수를 여러 번 골라도 된다.)을 출력하는 프로그램을 작성하는 문제로
처음 문제를 읽고 방문처리 없이 구현하면 해결이 가능하다고 생각해 아래와 같이코드를 작성하였다.
< 초기 코드 >
import java.util.*;
public class Main{
public static int num[];
public static void main(String args[]){
Scanner s=new Scanner(System.in);
int n=s.nextInt();
int m=s.nextInt();
num=new int[m];
dfs(0,n,m);
}
public static void dfs(int depth,int n,int m){
if(depth==m){
for(int i=0;i<m;i++){
System.out.print(num[i]+" ");
}System.out.println();
return;
}
for(int i=1;i<=n;i++){
num[depth]=i;
dfs(depth+1,n,m);
}
}
}
처음에는 단지 방문처리 없이 문제를 해결하는 문제인가보다라고 생각하고 위와 같이 풀이했었다.
하지만 시간초과라는 결과를 받았고 무엇이 문제인지 고민해본 결과 방문처리가 없어 모든 재귀를 다 접근하는데
이때마다 Sytem.out.print를 호출해 I/O 작업이 발생하게 되어 시간초과가 난다는 결론이었다.
예를 들어 n=7 m=7일때 나올수 있는 경우의 수는 7의 7승 823,543인데
이럴 경우 위의 코드처럼 결과 값이 있을때마다 I/O 작업이 발생되면 출력시간이 많이 걸리게 되어 시간초과가 나오는 것이다.
< 최종 코드 >
import java.util.*;
public class Main{
public static StringBuilder str=new StringBuilder();
public static int num[];
public static boolean visited[];
public static void main(String args[]){
Scanner s=new Scanner(System.in);
StringBuilder sb=new StringBuilder();
int n=s.nextInt();
int m=s.nextInt();
num=new int[m];
visited=new boolean[n+1];
dfs(0,n,m,sb);
System.out.print(str);
}
public static void dfs(int depth,int n,int m,StringBuilder sb){
if(depth==m){
str.append(sb).append("\n");
return;
}
for(int i=1;i<=n;i++){
int len=sb.length();
sb.append(i).append(" ");
dfs(depth+1,n,m,sb);
sb.setLength(len);
}
}
}
위처럼 StringBuilder를 활용해 출력값을 한곳에 저장했다가 출력하는 방식으로 문제를 해결하였다.
다만 StringBuilder에 매몰된 나머지 StringBuilder을 2번 선언해서 사용하였는데
초기 코드에 dfs 함수의 if문안의 for문에서 출력대신 StringBuilder을 사용하는것으로도 해결이 가능하다.
마무리
본 문제는 문제를 해결할때 단순히 시간복잡도 뿐만 아니라 입출력의 횟수등 여러 부분을 고려하고 계산해 문제를 접근해야한다는 것을 알려주는 좋은 문제였다. n과 m(1)에서는 StringBuilder를 활용하지 않아도 시간초과가 나지 않았었는데 이때는
입출력 호출횟수가 약 4만회 정도로 안전했지만 본 문제에서 같은 수를 허용하면서 호출횟수가 80만회가 넘어 시간초과를 유발한것을 알수 있었다.
중요한 것은 자바에서는 출력횟수가 10만을 넘어가게 되면 1초안에 해결이 힘들다는 것을 인지하고 문제를 접근해야한다는 것이다.
참고 자료
N과 M 시리즈
https://hmkang32180116.tistory.com/127
[문제 풀이] 백준 15649번 N과 M(1) JAVA _다시풀이
문제 문제접근 방법 해당 문제는 N과 M을 입력받고 1부터 N까지 자연수 중에서 중복 없이 M개를 고른 수열을 사전 순으로 출력하는 프로그램을 작성하는 문제아다. 해당문제는 DFS + 백트래킹에 대
hmkang32180116.tistory.com
https://hmkang32180116.tistory.com/132
[문제 풀이] 백준 15650번 N과 M(2) JAVA
문제 문제접근 방법 해당 문제는 1부터 N까지 자연수 중에서 중복 없이 M개를 고른 수열을 오름차순으로 출력하는문제이다.핵심은 숫자를 선택할 때, 현재 수보다 더 큰 수만 다음에 선택하도록
hmkang32180116.tistory.com
'문제풀이 > BFS_DFS' 카테고리의 다른 글
| [문제 풀이] 백준 15654번 N과M(5) JAVA (0) | 2025.05.16 |
|---|---|
| [문제 풀이] 백준 15652번 N과 M (4) JAVA (0) | 2025.05.15 |
| [문제 풀이] 백준 1260번 DFS와 BFS JAVA (0) | 2025.05.14 |
| [문제 풀이] 백준 1759번 암호 만들기 _ver 1 JAVA (0) | 2025.04.21 |
| [문제 풀이] 백준 1182번 부분수열의 합 JAVA (0) | 2025.04.18 |