원인으로 두가지가 있습니다.
10!*10만큼의 시간 복잡도가 발생합니다. if(!answer.contains(target)){
answer+=target;
dfs(location+1, level, answer);
answer = answer.substring(0,answer.length()-1);
}
10!*10만큼의 시간 복잡도가 발생합니다. for(String str : word.split("")){
String indexNumber = answer.charAt(alphabetList.indexOf(str))+"";
changedNumber += indexNumber;
}
따라서 제 풀이는 여러 곳에서 많은 곳에서 시간 초과를 발생할 수 있는 부분이 발견되었습니다.
이 문제의 경우 시간 제한이 2초이며 그러면 최대 2억번의 연산이 발생할 수 있습니다. 그러나 저는 이미 3억을 2번이나 사용하고 있는 상황이라서 이 부분을 고쳐야겠다고 생각했습니다.
일단 위 문제에 따라서 ArrayList를 사용하지 않기로 했습니다.
for(int i=0;i<10;i++){
if(!visited[i]){
visited[i]=true;
map.put(usedAlphabet[location],i);
dfs(location+1, level,map);
map.remove(usedAlphabet[location]);
visited[i]=false;
}
}
Set<String> set = new HashSet<>();
Map<String,Integer> map = new HashMap<>();
int wordCount = Integer.parseInt(br.readLine());
for(int i=0;i<wordCount;i++){
wordTokenList.add(br.readLine().split(""));
Arrays.stream(wordTokenList.get(i)).forEach(v->set.add(v));
}
int level = set.size();
usedAlphabet = set.toArray(String[]::new);
dfs(0,level,map);
static void dfs(int location , int level, Map<String , Integer> map){
if(level==location){
int sumResult = makeSum(map);
if(max<sumResult){
max = sumResult;
}
return;
}
for(int i=0;i<10;i++){
if(!visited[i]){
visited[i]=true;
map.put(usedAlphabet[location],i);
dfs(location+1, level,map);
map.remove(usedAlphabet[location]);
visited[i]=false;
}
}
}
static int makeSum(Map<String,Integer> map){
int sum =0;
for(String[] tokens : wordTokenList){
int wordNum = 0;
for(String token : tokens){
wordNum*=10;
wordNum += map.get(token);
}
sum+= wordNum;
}
return sum;
}
ArrayList의 시간복잡도
add : O(1)
remove : O(n)
get : O(1)
Contains : O(n)
iterator.remove : O(n)
import java.io.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Main {
static List<String> wordList = new ArrayList<>();
static List<String> alphabetList = new ArrayList<>();
static Integer max = Integer.MIN_VALUE;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
// N개의 단어로 이루어져 있다
// 각 단어 알파벳 대문자
// 대문자를 0부터9까지의 숫자 하나로 바꿔서 N개의 수를 합하는 문제
// 같은 알파벳은 같은 숫자로
// 두 개 이상의 알파벳이 같은 숫자로 바뀌어서는 안된다
// 주어진 단어
// 몇 개의 알파벳이 등장하는가?
// 각 알바펫에 숫자를 부여하고
// 그 합을 최대로 하는 그 값을 정하기
int wordCount = Integer.parseInt(br.readLine());
Set<String> wordSet = new HashSet<>();
for(int i=0;i<wordCount;i++){
String enterWord = br.readLine();
wordList.add(enterWord);
// 알파벳이 들어가는 과정
for(String c : enterWord.split("")){
wordSet.add(c);
}
}
int level = wordSet.size();
alphabetList = new ArrayList<>(wordSet);
dfs(0,level,"");
System.out.println(max);
}
static void dfs(int location , int level, String answer){
if(level==location){
int sumResult = makeSum(answer);
if(max<sumResult){
max = sumResult;
}
return;
}
for(int i=0;i<10;i++){
String target = Integer.toString(i);
if(!answer.contains(target)){
answer+=target;
dfs(location+1, level, answer);
answer = answer.substring(0,answer.length()-1);
}
}
}
static int makeSum(String answer){
int sum =0;
for(int i=0;i<wordList.size();i++){
// 단어 꺼내기
String word = wordList.get(i);
String changedNumber = "";
// 단어 알파벳으로 분리
for(String str : word.split("")){
String indexNumber = answer.charAt(alphabetList.indexOf(str))+"";
changedNumber += indexNumber;
}
sum+= Integer.parseInt(changedNumber);
}
return sum;
}
}
import java.io.*;
import java.util.*;
public class Main {
static List<String[]> wordTokenList = new ArrayList<>();
static String[] usedAlphabet ;
static boolean[] visited = new boolean[10];
static Integer max = Integer.MIN_VALUE;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
// N개의 단어로 이루어져 있다
// 각 단어 알파벳 대문자
// 대문자를 0부터9까지의 숫자 하나로 바꿔서 N개의 수를 합하는 문제
// 같은 알파벳은 같은 숫자로
// 두 개 이상의 알파벳이 같은 숫자로 바뀌어서는 안된다
// 주어진 단어
// 몇 개의 알파벳이 등장하는가?
// 각 알바펫에 숫자를 부여하고
// 그 합을 최대로 하는 그 값을 정하기
Set<String> set = new HashSet<>();
Map<String,Integer> map = new HashMap<>();
int wordCount = Integer.parseInt(br.readLine());
for(int i=0;i<wordCount;i++){
wordTokenList.add(br.readLine().split(""));
Arrays.stream(wordTokenList.get(i)).forEach(v->set.add(v));
}
int level = set.size();
usedAlphabet = set.toArray(String[]::new);
dfs(0,level,map);
bw.write(Integer.toString(max));
bw.flush();
bw.close();
}
static void dfs(int location , int level, Map<String , Integer> map){
if(level==location){
int sumResult = makeSum(map);
if(max<sumResult){
max = sumResult;
}
return;
}
for(int i=0;i<10;i++){
if(!visited[i]){
visited[i]=true;
map.put(usedAlphabet[location],i);
dfs(location+1, level,map);
map.remove(usedAlphabet[location]);
visited[i]=false;
}
}
}
static int makeSum(Map<String,Integer> map){
int sum =0;
for(String[] tokens : wordTokenList){
int wordNum = 0;
for(String token : tokens){
wordNum*=10;
wordNum += map.get(token);
}
sum+= wordNum;
}
return sum;
}
}