https://www.acmicpc.net/problem/1181
1181번: 단어 정렬
첫째 줄에 단어의 개수 N이 주어진다. (1 ≤ N ≤ 20,000) 둘째 줄부터 N개의 줄에 걸쳐 알파벳 소문자로 이루어진 단어가 한 줄에 하나씩 주어진다. 주어지는 문자열의 길이는 50을 넘지 않는다.
www.acmicpc.net
실버 5라 만만하게 봤는데 1시간 넘게 걸리고 결국 gpt의 도움을 받았다.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
public class Main {
static List<String> word;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
word = new ArrayList<String>();
for (int i = 0; i < N; i++) {
word.add(sc.next());
}
Collections.sort(word); // 우선 사전순으로 정렬
for(int i=0; i<word.size()-1; i++) {
if(word.get(i).equals(word.get(i+1))) { // 같으면
word.remove(i); // 중복제거
}
}
Collections.sort(word, new Comparator<String>() { // 길이순 오름차순
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
});
for(int i=0; i<word.size(); i++) {
System.out.println(word.get(i));
}
}
}
처음에 코드를 이렇게 구상했다.
가장 처음에는 String 배열을 생성해서 단어를 받고 중복을 제거했는데
중복을 제거한 자리가 비어있고 처리하기 까다로워서 중간에 list로 바꿨다.
1. 우선 사전순으로 정렬
[but, cannot, hesitate, i, im, it, more, no, wait, wont, yours]
그러면 이렇게 출력이 나온다.
2. 길이 오름차순으로 정렬
[i, im, it, no, but, more, wait, wont, yours, cannot, hesitate]
그러면 이렇게 출력이 나온다.
여기까지 해보고 제출을 했으나 13% 넘어가니깐 틀렸습니다가 출력됐다.
1시간 동안 고민하고 질문게시판도 가봤지만 정확히 어디가 문제인지 모르겠어서 chat gpt의 도움을 받았다.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
public class baek_1181_단어정렬_실버5 {
static List<String> word;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
word = new ArrayList<String>();
for (int i = 0; i < N; i++) {
word.add(sc.next());
}
Set<String> set = new HashSet<>(word);
word = new ArrayList<>(set);
Collections.sort(word, new Comparator<String>() { // 길이순 오름차순
@Override
public int compare(String o1, String o2) {
if (o1.length() == o2.length()) {
return o1.compareTo(o2);
}
return o1.length() - o2.length();
}
});
for(int i=0; i<word.size(); i++) {
System.out.println(word.get(i));
}
}
}
우선 hashset을 사용했다.
HashSet은 Set 인터페이스를 구현한 클래스 중 하나로, 객체들을 중복 없이 저장하는 데 사용이 된다.
Set<String> set = new HashSet<>(word);
word = new ArrayList<>(set);
이 부분의 의미는 word에서 중복된 요소를 제거하고 String타입인 set에 담은 것이다.
그걸 다시 word안에 담아주는 방식이다.
기존에 문제점은 중복을 제거하면서 i번째랑 i+1번째가 같으면 i번째를 제거하는데 그러면 i+1번째가 i번째로 당겨지게 된다. 하지만 바로 for문을 다시 돌아서 i는 ++이 돼서 이전에 당겨진 i번째는 건너뛰게 되는 문제가 생긴다.
(이 글을 작성하면서 한 가지 아이디어가 떠올라서 바로 실행했더니 Hashset을 안 쓰고도 동작을 성공했다)
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
public class baek_1181_단어정렬_실버5 {
static List<String> word;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
word = new ArrayList<String>();
for (int i = 0; i < N; i++) {
word.add(sc.next());
}
Collections.sort(word); // 우선 모음순으로 정렬
for(int i=0; i<word.size()-1; i++) {
boolean flag = true;
while(flag==true) {
if(i!=word.size()-1&&word.get(i).equals(word.get(i+1))) { // 같으면
word.remove(i); // 중복제거
}else {
flag=false;
}
}
}
Collections.sort(word, new Comparator<String>() { // 길이순 오름차순
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
});
for(int i=0; i<word.size(); i++) {
System.out.println(word.get(i));
}
}
}
for문 안에 boolean으로 flag를 하나 세우고 i가 size-1이 아닐 때 동작하도록 조건을 추가했다.
이러면 중복으로 제거돼도 flag가 그대로 true여서 while을 돌면서 다시 중복을 제거한다.
또 if문에 i != word.size()-1을 추가한 이유는 중복이 마지막번째에 있으면 i+1을 보는 순간 indexoutofbounds에러가 발생한다. 그것을 잡아주려고 추가했다.
'알고리즘문제 > 백준' 카테고리의 다른 글
백준 19949 영재의 시험(자바) (0) | 2023.04.04 |
---|---|
백준 2252 줄 세우기(자바) (0) | 2023.04.03 |
백준 2606 바이러스(자바) (0) | 2023.04.03 |
백준 1197 최소 스패닝 트리 (자바) (0) | 2023.04.02 |