기초 언어 학습 주가 끝나고, 프로그래밍 기초 주차가 시작되었다.
오늘부턴 지금까지 배운 개념들을 토대로 팀원들과 알고리즘 문제를 풀어보는 과정으로 학습을 진행했다.
난이도는 프로그래머스 코딩테스트 lv1에 있는 문제들로 구성되어 있었다.
팀에서 2명씩 짝지어서 함께 문제를 풀어보았다.
오늘 풀어본 문제를 돌아보면서 헷갈렸던 부분이나 유용한 함수에 대해서 정리해보고자 한다.
2016년
인자로 주어진 날짜에 해당하는 요일을 계산하는 문제였다.
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.TextStyle;
import java.util.Locale;
class Solution {
public String solution(int a, int b) {
LocalDate date = LocalDate.of(2016,a,b);
DayOfWeek dayOfWeek = date.getDayOfWeek();
return dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.US).toUpperCase();
}
}
LocalDate.of(년,월,일); 로 기준일을 설정하여 참조변수에 할당하고, getDayOfWeek() 함수를 통해 지정한 날짜의 요일을 가져왔다. 그리고 getDisplayName() 함수로 요일을 어떻게 나타낼건지(TextStyle), 어떤 언어로 나타낼건지 지정해주었다.
LocalDate.of(int year, int, month, int dayOfMonth) - 원하는 날짜를 선택하여 LocalDate 타입으로 반환
date(LocalDate 타입 참조변수).getDayOfWeek() - 해당 날짜의 요일을 반환
dayOfweek(요일).getDisplayName(TextStyle.길이, Locale.US) - 날짜를 원하는 포맷으로 변경. 길이와 날짜 변경 가능.
Date 함수를 직접 사용해본적이 없는데, LocalDate 클래스도 유용하게 사용할 수 있다는 것을 알게 되었다.
나누어 떨어지는 숫자 배열
인자로 주어지는 배열과 숫자로, 배열 내 요소 중 숫자로 나눌 수 있는 값만 배열에 담아 반환하는 문제이다.
import java.util.ArrayList;
import java.util.Arrays;
class Solution {
public int[] solution(int[] arr, int divisor) {
int cnt = 0;
ArrayList<Integer> list = new ArrayList();
for (int i = 0; i < arr.length; i++) {
if(arr[i]%divisor == 0){
list.add(arr[i]);
cnt++;
}
}
int[] answer = new int[list.size()];
if(cnt == 0){
return new int[]{-1};
}else{
for (int i = 0; i < list.size(); i++) {
answer[i] = list.get(i);
}
}
Arrays.sort(answer);
return answer;
}
}
처음에는 answer로 담아 보낼 값을 배열에 추가하고자 했는데, 배열의 길이가 매 번 유동적일 수 밖에 없기 때문에 ArrayList를 사용하게 되었다.
수박수박수박수박수박수?
주어진 인자 값으로 수, 박을 반복적으로 출력하는 문제이다.
class Solution {
public String solution(int n) {
String answer = "";
for (int i = 0; i < n; i++) {
answer += i%2==0 ? "수" : "박";
}
return answer;
}
}
짝수와 홀수 문제를 풀었던 방식으로, 나머지 값에 따라 수,박을 판별하여 answer에 추가되도록 했다.
완주하지 못한 선수
인자로 주어지는 참석자와 완주한 선수의 리스트를 비교하여, 완주하지 못한 선수(1명 고정)를 구하는 문제이다.
import java.util.HashMap;
class Solution {
public String solution(String[] participant, String[] completion) {
String answer = "";
HashMap<String, Integer> map = new HashMap<>();
for(String player : participant)
map.put(player, map.getOrDefault(player,0) + 1);
for(String player : completion)
map.put(player, map.get(player) - 1);
for(String key : map.keySet()) {
if(map.get(key) == 1) {
answer = key;
}
}
return answer;
}
}
처음에 접근할 때는 배열을 List로 바꾸고, 참석자 명단과 완주자 명단을 비교하여 탈락자를 뽑아내고자 했다. (반복문, 조건문 사용)
Test 결과는 성공적으로 산출되었으나, 제출 시 통과가 되지 않았다.
ArrayList의 remove 를 사용하는 등 시도해보았지만 결국 풀지 못했다.
구글링해보니, 문제 출제 의도 자체가 Hash를 사용하도록 유도하는 문제여서 통과가 되지 않았던 것 같다.
풀이를 보니 HashMap 을 사용해서 key에 이름을, value에는 숫자를 주었다.
For문을 총 2번 돌려 참석자 명단과 완주자 명단을 HashMap에 등록한다.
특이한 점은 getOrDefault 메서드를 사용했다는 점이다. 참석자 명단을 HashMap에 넣을 때, player가 있을 경우 해당 player의 value(숫자), 없으면 0을 반환하되, +1을 더하도록 했다.
for문이 종료되면, participant 에 있던 참석자 모두의 value는 1로 입력이 된다.
다음으로 완주자 명단을 put하게 되는데, 완주자 명단의 player의 value를 -1씩 하도록 했다.
결국 완주자 명단에 있는 player의 value는 0이 된다.
참석자 명단에는 있으나, 완주자 명단에는 없는 player의 경우, value가 1로 남아있어 조건문을 통해 탈락자를 뽑아낼 수 있다.
HashMap을 좀 더 다양한 용도로 사용할 수 있다는 것을 알게 되어 의미 있는 문제였다고 생각한다.
이상한 문자 만들기
여러 단어로 이루어진 문자열을 짝수번째 알파뱃은 대문자로, 홀수번째 알파뱃은 소문자로 바꿔주는 문제이다.
class Solution {
public String solution(String s) {
String answer = "";
String[] strArray = s.split("");
int sNum = 0;
for (int i = 0; i < strArray.length; i++) {
if(strArray[i].equals(" ")){
answer += " ";
sNum=0;
continue;
}
if(sNum%2 == 0){
strArray[i] = strArray[i].toUpperCase();
sNum++;
}else if(sNum%2 != 0){
strArray[i] = strArray[i].toLowerCase();
sNum++;
}
answer += strArray[i];
}
return answer;
}
}
초반에 방향을 잡을 때, " " 공백을 구분자로 문자열을 나누어 나누어진 문자열을 차례대로 반복하여 바꿔주고자 했다. 나눠진 문자열을 ToCharArray로 한글자씩 가져와 index값을 토대로 대문자와 소문자로 바꾸어주었다.
Test는 성공적으로 수행이 되었는데, 제출 후 채점을 진행하니 전부 실패로 떠서 당혹스러웠다.
접근 방법이 잘못된 것 같아 처음부터 다시 진행했고, 이번에는 split의 구분자를 아무것도 주지 않은 채로 s의 문자열 전체를 문자열 배열로 만들어 사용했다. 띄어쓰기가 있는 경우에는 index를 추기화 해주고 answer에 공백을 추가하도록 했다. 이번에는 성공적으로 채점 결과가 나왔다.
채점 기준이 어디에 있는지는 모르겠지만, 문제 설명 같은 곳에 제한 사항을 통해 풀이 방법을 유도해준다면 좋지 않을까 하는 생각이 든다.
자릿수 더하기
public class Solution {
public int solution(int n) {
int answer = 0;
String str = n + "";
for (int i = 0; i < str.length(); i++) {
answer += (str.charAt(i)-'0');
}
return answer;
}
}
자연수 뒤집어 배열로 만들기
class Solution {
public int[] solution(long n) {
String str = n + "";
int[] answer = new int[str.length()];
for (int i = 0; i < str.length(); i++) {
answer[str.length()-1-i] = str.charAt(i) - '0';
}
return answer;
}
}
정수 내림차순으로 배치하기
주어진 정수를 내림차순으로 정렬하는 문제이다.
import java.util.Arrays;
import java.util.Collections;
class Solution {
public long solution(long n) {
String s = n + "";
String [] strArr = s.split("");
Arrays.sort(strArr,Collections.reverseOrder());
String str = String.join("",strArr);
return Long.parseLong(str);
}
}
처음에 주어진 정수를 문자열 배열로 변환하고, 변환한 문자열을 다시 숫자형 배열로 변환하여 sort를 진행하려고 했었는데 생각보다 형변환에 애를 먹었던 것 같다.
그러던 와중에 Arrays.sort 자체가 문자로 적힌 숫자에도 적용된다는 사실을 뒤늦게 알게 되어서.. 쉽게 해결이 되었다.
Arrays.sort(배열, Collections.reverseOrder()); ➞ 내림차순 정렬
String.join(구분자, 배열); ➞ 문자열 배열을 문자열로 변환
느낀 점
이전에 풀었던 문제는 프로그래머스 lv.0 이였는데, 난이도가 올라가다보니 한 문제를 푸는데 시행착오가 많이 발생했던 것 같다. 오늘 문제를 풀면서. 배우는 것과 직접 사용하는 건 다르구나 하는 깨달음을 얻을 수 있었다.
특히, 기본형 타입과 배열 간의 형변환이 어렵게 느껴졌다.
내장 함수 사용에도 구글링을 많이 했는데, 자주 사용하는 내장 함수들은 용도 별로 체크해두고 자주 보면서 익숙해질 수 있도록 해야겠다.
'항해99' 카테고리의 다른 글
항해99 - 3주차 WIL (0) | 2023.01.30 |
---|---|
항해 99 - 2023.01.28 TIL (0) | 2023.01.28 |
항해 99 - 2023.01.26 TIL (0) | 2023.01.26 |
항해 99 - 2023.01.25 TIL (0) | 2023.01.25 |
항해99 - 2주차 WIL (0) | 2023.01.22 |