알고리즘문제/백준

백준 1181 단어정렬(자바)

indeep 2023. 4. 1. 17:02

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에러가 발생한다. 그것을 잡아주려고 추가했다.

 

 

반응형