인프런의 "자바(Java) 알고리즘 문제풀이 : 코딩테스트 대비" 강좌를 수강했습니다.
Q1-03. 문장 속 단어
영어 알파벳으로 이루어진 한 개의 문장이 주어지면, 그 문장 중 가장 긴 단어를 출력하는 문제.
문장은 공백으로 구분되어 있다.
길이가 가장 긴 단어가 여러 개 있다면, 앞에 위치한 단어를 출력한다.
✏️ 내가 쓴 답
가장 긴 단어의 길이를 저장할 max 변수를 0으로 초기화한다.
문자열 str을 split(" ") 메소드를 이용해 공백(" ")을 기준으로 잘라준다. 문자열 배열(String[])이 return 되므로 반복문 사용 가능
한 단어 word의 길이를 나타내는 len과 max를 비교해, 더 긴 것의 크기는 max 값에 대입하고 answer 변수에 가장 긴 단어를 저장한다.
가장 큰 정수값, 가장 작은 정수값 구하는 방식과 똑같다.
이렇게 돌려보니 정답!✅😊
import java.util.Scanner;
public class Main {
public String solution(String str) {
String answer = "";
int max = 0;
for(String word : str.split(" ")){
int len = word.length();
if(len > max){
max = len;
answer = word;
}
}
return answer;
}
public static void main(String[] args){
Main main = new Main();
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
System.out.println(main.solution(str));
}
}
💪🏻 보완하고 싶은 점
이번에 잘 푼 것 같은데 🧐 다른 방법도 있을까 ?!!
👨🏻🏫 수정한 코드
첫 번째 방법
이 방법은 나랑 똑같은 방법이다!
다만 하나 달랐던 것은 단어의 길이를 저장할 m 변수의 초기값이었는데, 쌤은 Integer.MIN_VALUE 로 저장하셨다.
Integer 범위(–2,147,483,648 ~ 2,147,483,647) 중 최소값인 –2,147,483,648 로 지정하는 것이었다.
다른 분이 0과 Integer.MIN_VALUE로 초기화 하는 게 차이가 있냐는 질문이었는데, 이 문제는 음수를 다루지 않아서 0으로 초기화 해도 상관 없다고 하셨다. 아마 음수까지 다루는 문제가 있다면 이렇게 초기화 하면 좋을 듯 하다!
또 주의할 점은 10번 째 줄 len > m 부분이 len >= m 이렇게 되면 안된다. 이러면 같은 길이의 가장 긴 단어 중 뒤에 오는 단어가 저장되어 버리므로, 문제 의도와 달라져버릴 수 있음을 주의하자.
public String solution(String str){
String answer = "";
int m = Integer.MIN_VALUE;
String[] s = str.split(" ");
for(String x : s) {
int len = x.length();
if(len > m) {
m = len;
answer = x;
}
}
return answer;
}
두 번째 방법
indexOf()와 substring() 을 이용하는 방법!
공백의 위치를 찾아서 문장을 잘라가는 식으로 진행한다.
substring(int n) : 0~n 번째 이후의 단어만 나타나도록 자른다.
substring(int beginIndex, int endIndex) : beginIndex 부터 endIndex 전 위치까지 자른다.
(8째 줄) while문에서 문장에서 indexOf()로 공백의 위치를 받는다.
(9째 줄) 변수 tmp에는 0번째부터 공백이 있는 곳까지, 즉 한 단어를 저장하고
(12~15째 줄) 위 답변과 똑같이 길이비교를 통해 단어가 answer에 저장된다.
(17째 줄) 길이비교를 끝냈으면, 문자열 중에 이미 비교를 끝낸 앞의 단어를 잘라낸다. it is time to sleep 중 첫번째 비교 후 이 문장을 통해 is time to sleep, 두번 째 비교 후 time to sleep 이런식으로 앞 단어가 잘려나간다.
그래서 while문이 계속 될 때마다 (9째 줄)에서는, 이미 비교된 단어는 잘려나간 문장의 새로 비교할 단어는 0번째 인덱스부터 시작하게 된다.
(19째 줄) while문을 반복하다 보면 마지막 sleep 단어만 남았을 땐, 공백이 존재하지 않아 while 조건문은 -1이 되어 while문을 빠져나오게 된다. 그럼 sleep 단어는 길이 비교를 하지 못하기 때문에, while 문이 끝난 후 별도로 if문을 통해 길이비교를 한다.
while문에 익숙하지 않은 나로서는 일단 for문부터 생각하고 보는데.. 신기한 풀이방식이었다!
public String solution(String str) {
String answer = "";
int m = Integer.MIN_VALUE;
int pos;
while((pos=str.indexOf(" ")) != -1){ // pos=문자열 중 공백의 포지션 ex)it is time to sleep
String tmp = str.substring(0, pos); // 문자열의 처음부터 공백 이전의 알파벳까지를 한 단어로서 tmp에 저장 ex)it
int len = tmp.length(); // tmp 단어의 길이 저장
if(len > m){
m = len;
answer = tmp;
}
str = str.substring(pos+1); // 공백 위치의 다음 위치(pos+1)부터 문자열이 다시 시작하도록 자름 ex)is time to sleep
}
if(str.length() > m) answer = str; // 마지막 단어만 남았을 때 while문에서 벗어나 길이비교가 불가능해지므로 이 줄에서 한번 더 비교 함
return answer;
}
🤓 정리
- split(String regex) 함수로 특정문자 기준으로 자른 문자열 배열을 얻을 수 있다.
- 정수형 변수를 정수 범위 내 최소, 최대값으로 초기화 할 수 있다. Integer.MIN_VALUE, Integer.MAX_VALUE
- substring()으로 문자열을 자를 수 있다. substring(int n)은 n번째 인덱스 이후로 출력, substring(int a, int b)은 a번째 인덱스부터 b-1번째 인덱스까지 출력한다.
원래부터 알고리즘 풀이 스펙트럼이 워낙 좁은 것도 있었지만.. 쉬운 문제에서도 풀 수 있는 방법이 여러가지가 될 수 있는 게 재미있었다.
꾸준히 더 진행해보도록 하자. ^^
'Study > 알고리즘' 카테고리의 다른 글
[알고리즘/인프런] String(문자열) #1-06. 중복문자제거 (2) | 2022.04.14 |
---|---|
[알고리즘/인프런] String(문자열) #1-05. 특정문자 뒤집기 (0) | 2022.04.13 |
[알고리즘/인프런] String(문자열) #1-04. 단어 뒤집기(StringBuilder) (0) | 2022.04.12 |
[알고리즘/인프런] String(문자열) #1-02. 대소문자 변환 (0) | 2022.04.06 |
[알고리즘/인프런] String(문자열) #1-01. 문자 찾기 (0) | 2022.04.05 |