21.01.17 ~ 21.01.19

📌 자연수 뒤집어 배열로 만들기

초기 코드

class Solution {
    public int[] solution(long n) {
        int[] answer = {};
        
        return answer;
    }
}

내가 작성한 코드

class Solution {
    public int[] solution(long n) {
       
        String str = Long.toString(n);
        int[] answer = new int[str.length()];
        //str to integer, 반복해서 하나씩 넣기
        for (int i = 0; i < str.length(); i++) {
            answer[i] = Integer.parseInt(String.valueOf(str.charAt(str.length() - 1 - i))); //(1)
        }
       
        return answer;
    }
}

long -> string -> integer를 거쳐야 했다. (1)에서 parseInt까지는 저번에 썼던 기억이 있는데, string의 한 글자만 골라서 int로 바꾸는 방법이 생각 안나서 검색해봤다. str.charAt(index)로 char 형식의 한 글자만 구하고, String.valueOf(한 글자)로 그 글자의 형식을 str로 바꾼다. 그러면 그 str를 integer로 표현할 수 있게 되는 거였다.
배열 맨 앞에는 숫자의 맨 마지막 숫자가 들어가야 하니까 인덱스는 str.length() - 1 - i로 잡았다.

다른 사람의 풀이

class Solution {
  public int[] solution(long n) {
      int length = Long.toString(n).length();
        int[] answer = new int[length];

        for (int i = 0; i < length; i++) {
            answer[i] = (int) (n % 10);
            n /= 10;
        }

        return answer;
  }
}

여기서는 아예 length라는 변수를 선언해뒀다. 그리고서 answer 배열에 순서대로 어떻게 담냐면, n을 10으로 나눈 나머지를 담아서 12345 중 5를 담는다. 그리고 n /= 10을 하면 1234.5에서 몫만 표시하니까 1234가 된다. 이 과정을 반복하면 123,12,1이렇게 n의 자릿수가 줄어들고 answer에 일의 자리 수부터 하나씩 저장된다. 형 변환보다는 숫자의 특성을 고려한 풀이도 있구나!


📌 문자열 내림차순으로 배열하기

초기 코드

class Solution {
    public String solution(String s) {
        String answer = "";
        return answer;
    }
}

내가 작성한 코드

import java.util.Arrays;
import java.util.Collections;
class Solution {
    public String solution(String s) {
        String answer = "";
        String[] temp = new String[s.length()];
        for (int i = 0; i < s.length(); i++) {
            temp[i] = Character.toString(s.charAt(i));
        }
        Arrays.sort(temp,Collections.reverseOrder());
        for (String ch : temp ) {
            answer += ch;
        }
        return answer;
    }
}

위에서 풀었던 문제처럼 charAt으로 그 자리에 있는 글자를 꺼내서 string으로 변환한 뒤 배열에 담았다. 배열에서는 sort 기능이 있으니까 그걸 사용하고자 굳이 배열에 담았다.

다른 사람의 풀이 (python)

def solution(s):
    return ''.join(sorted(s, reverse=True))

python을 쓰면 문자열도 형변환 없이 정렬할 수 있구나!
이래서 문자열 문제가 나오면 무조건 python으로 풀 수 있게 공부하라는 건가 싶었다.


📌 부족한 금액 계산하기

초기 코드

class Solution {
    public long solution(int price, int money, int count) {
        long answer = -1;
        return answer;
    }
}

내가 작성한 코드

class Solution {
    public long solution(int price, int money, int count) {
        long answer = -1;
        long sum = 0; //(1)
        for (int i = 1; i <= count; i++) {
            sum += price * i;
        }
        
        answer = (money < sum) ? sum - money : 0;
        return answer;
    }
}

원래는 (1)에서 sum 변수를 int로 선언했었다. 어차피 price도 i도 int형이니까 별 문제 없을거라고 생각해서 그렇게 썼는데 채점해보면 어떤 케이스에서 틀렸다고 나왔다. 알고리즘 자체는 틀린 게 절대 없다고 생각해서 검색해보니까 나처럼 했다가 변수를 long으로 바꿨더니 모든 테스트 케이스에서 통과했다고 하더라. 아마 저기서 solution 함수 자체가 long 타입을 반환하는 거라서 몇몇 테스트 케이스에서 값이 오버되는 것 같다고 하는 걸 봤다. int보다는 long이 폭이 더 넓으니까 다음에도 좀 고민해보고 타입을 선택하기로 함..


📌 두 정수 사이의 합

초기 코드

class Solution {
    public long solution(int a, int b) {
        long answer = 0;
        return answer;
    }
}

내가 작성한 코드

class Solution {
    public long solution(int a, int b) {
        long answer = 0;
        if (a == b) {
            answer = a;
        }
        else {
            int min = Math.min(a,b);
            int max = Math.max(a,b);
            for (int i = min; i <= max; i++ ) {
                answer += i;
            }
        }
        return answer;
    }
}

a와 b가 같은 경우를 고려해서 무조건 if문으로 검사를 해야한다고 생각했다. 결과적으로 채점에서 틀리진 않았지만, 다른 사람의 풀이를 보니까 Math.min과 Math.max를 쓰면 굳이 두 수가 같은 경우를 고려하지 않아도 된다고 하더라. 그래서 고쳐봤다.

내가 수정한 코드

class Solution {
    public long solution(int a, int b) {
        long answer = 0;
        int min = Math.min(a,b);
        int max = Math.max(a,b);
        for (int i = min; i <= max; i++ ) {
            answer += i;
        }
        return answer;
    }
}

다음에도 Math 함수를 쓰게 된다면 같은 수를 비교하는 경우에는 둘 중 하나가 알아서 출력된다는 점을 생각하기


📌 다트 게임

초기 코드

class Solution {
    public int solution(String dartResult) {
        int answer = 0;
        return answer;
    }
}

다른 사람의 풀이

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.ArrayList;

class Solution {
    public int solution(String dartResult) {
        int answer = 0;
        int idx = 0;
        Matcher matcher = Pattern.compile("([0-9]0?)([SDT])([*#]?)").matcher(dartResult); //(1)
        ArrayList<Integer> scores = new ArrayList<>();
        
        while (matcher.find()) {
            int type = matcher.group(2).equals("S")? 1 : matcher.group(2).equals("D")? 2: 3;
            int option = matcher.group(3).equals("*")? 2 : matcher.group(3).equals("#")? -1: 1;
            int score = (int)Math.pow(Integer.parseInt(matcher.group(1)),type) * option;
            
            scores.add(idx,score);
            
            if (idx > 0 && option == 2) {
                scores.set(idx - 1, scores.get(idx - 1) * option);
            }
            idx++;
        }
        for (int score : scores) {
            answer += score;
        }
        return answer;
    }
}

아무리 생각해도 수 많은 if문과 else if문을 써야한다는 생각밖에 안 들어서 좋은 코드를 공부하는 셈치고 서치하기로 꽤 빨리 결정했다.
(1) 정규식을 활용할 때 사용할 수 있는 Matcher와 Pattern을 사용했다.

✏️ 정규식 활용
import할 때 다른 클래스랑 조금 다르다. regex가 중간에 필요하더라.

import java.util.regex.Pattern;
import java.util.regex.Matcher;

Pattern 패턴이름 = Pattern.compile("정규식 입력");
-> 정규식을 선언
Matcher 매처이름 = 패턴이름.matcher("검사할 문자열");
-> 정규식과 일치하는 지 검사하고자 하는 문자열 저장
match.find();
-> 정규식과 매치된 값이 있다면 true, 없다면 false 반환
match.group();
-> 정규식과 문자열을 비교해 매치된 값을 반환

정규식 안에 쓴 숫자, 대소문자, 선택사항 등 외우고 있었는데 많이 까먹은 걸 새삼 실감했다..
while 반복문은 매치된 값이 있는 (true) 동안 반복한다.
2번째 원소를 분류해서 type에 저장하고, 3번째 원소를 분류해서 option에 저장한다. 이를 토대로 score에 라운드 최종 점수를 저장한다. 이때 어차피 경우의 수는 3가지로 정해져 있어서 삼항연산자로도 충분히 간결히 가능했다.
그 점수를 scores 배열에 담아둔다.
만약 첫 라운드가 아님 && 옵션이 Double 이라면 scores 배열에서 그 앞라운드의 점수도 2배 처리 해준다.
while로 각 라운드의 점수를 모두 구하고 나면 answer에 그 점수를 누적해서 총 점수를 반환한다.

다른 사람의 풀이 (python)

def solution(dartResult):
    point = []
    answer = []
    dartResult = dartResult.replace('10','k') #(1)
    point = ['10' if i == 'k' else i for i in dartResult]
    
    i = -1 #(2)
    sdt = ['S', 'D', 'T']
    for j in point:
        if j in sdt : #몇 제곱 되는지 검사
            answer[i] = answer[i] ** (sdt.index(j)+1)
        elif j == '*' : # 스타상이면 두배
            answer[i] = answer[i] * 2                
            if i != 0 : #첫 라운드 점수가 아니면(=앞 라운드 점수가 있으면)
                answer[i - 1] = answer[i - 1] * 2
        elif j == '#' : #아차상이면 -1배
            answer[i] = answer[i] * (-1)
        else: #j가 숫자면 answer에 포인트 삽입, 후에 if 조건에 따라 값 변화
            answer.append(int(j))
            i += 1
    return sum(answer)

(1) 주어지는 배열은 원소끼리 구분이 되지 않는다. 10이라고 구별하지 않고 1,0으로 나눠서 구별하면 안되니까 미리 10을 k로 치환해두는 방법을 썼다.
(2) 여기서 선언한 i는 answer 배열의 원소를 불러올 인덱스로 사용된다. 초기화 값이 -1인 이유를 한참 고민했는데, 아래 반복문의 else 구문에서 순수하게 맞춘 점수를 우선 삽입해두고 point 배열을 돌아가면서 적절하게 제곱을 하거나 배수를 적용하기 때문이다. 첫 반복에서는 당연히 j가 숫자(포인트)이기 때문에 else 구문을 타고 answer[0]에는 첫 라운드 점수가 삽입된다. 그 다음 반복에서 j는 ['S', 'D', 'T'] 중 하나일테니 제곱 계산을 한다. 여기서 i가 0이니까 answer[0]은 첫 라운드의 점수를 의미하고 그 점수를 알맞게 수정하는 것이다. 만약 점수를 우선 삽입하는 것이 아니라 보너스와 옵션을 적용한 최종 점수를 삽입한다면 저렇게 i를 -1로 잡아둬야 할 필요는 없었을 것 같다.

0개의 댓글

Powered by GraphCDN, the GraphQL CDN