개발자는 기록이 답이다

[프로그래머스][Java][Lv.0] 숨어있는 숫자의 덧셈(2) 본문

알고리즘/프로그래머스

[프로그래머스][Java][Lv.0] 숨어있는 숫자의 덧셈(2)

slow-walker 2023. 8. 30. 01:16

 

https://school.programmers.co.kr/learn/courses/30/lessons/120864

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

내가 푼 풀이

1. my_string배열을 순회하면서 숫자인 경우에만( Character.isDigit() ) 해당 숫자를 누적한다.

  1-1 .누적할때 숫자가 연속으로 있을 수 있으니 자릿수를 계산해준다.

2. 숫자가 아닌 경우에는 누적한 숫자를 anwer에 더해주고, 다시 초기화한다.

  2-1. 알파벳인 경우에는 더해주는것 없이 그냥 무시한다.

3. 마지막 인덱스 값이 숫자인 경우 else 구문을 타지 않으므로, for문 바깥에서 누적값을 더해준다.

public class Solution {
    public int solution(String my_string) {
        int answer = 0;
        int num = 0;

        for (int i = 0; i < my_string.length(); i++) {
            char tmp = my_string.charAt(i);
            if (Character.isDigit(tmp)) {
                num = num * 10 + (tmp - '0');  // 숫자 누적
            } else {
                answer += num;  // 숫자 누적값을 더해주고
                num = 0;  // 초기화

                // 알파벳인 경우는 무시
            }
        }
        answer += num;  // 마지막 숫자 처리
        return answer;
    }

    public static void main(String[] args) {
        Solution s = new Solution();
        String my_string = "aAb1B2cC34oOp";
        String my_string2 = "1a2b3c4d123Z";
        String my_string3 = "122a3bcd123";
        s.solution(my_string3);
    }
}
테스트 1 통과 (0.04ms, 74.1MB)
테스트 2 통과 (0.03ms, 66.3MB)
테스트 3 통과 (0.07ms, 75.5MB)
테스트 4 통과 (0.04ms, 77.5MB)
테스트 5 통과 (0.03ms, 78.4MB)
테스트 6 통과 (0.07ms, 73.7MB)
테스트 7 통과 (0.06ms, 72.1MB)
테스트 8 통과 (0.04ms, 74.4MB)
테스트 9 통과 (0.06ms, 76.2MB)
테스트 10 통과 (0.07ms, 71.7MB)

 

tmp - '0' VS Integer.parseInt(String.valueOf(tmp))

(tmp - '0') : 1
Integer.parseInt(String.valueOf(tmp)) : 1
(tmp - '0') : 2
Integer.parseInt(String.valueOf(tmp)) : 2
(tmp - '0') : 2
Integer.parseInt(String.valueOf(tmp)) : 2
1. tmp - '0': 이 표현식은 tmp 변수의 char 값에서 문자 '0'의 ASCII 값을 뺀 결과를 반환합니다. ASCII 값으로 '0'은 48이므로, 이 표현식은 실제 숫자를 나타내는 char 변수의 경우 해당 숫자의 정수 값을 얻을 수 있습니다. 예를 들어, '3'의 ASCII 값은 51이므로, '3' - '0'은 51 - 48로 3을 반환합니다. ==> 두 개의 char 값의 뺄셈 연산을 수행하면 되므로 매우 간단한 연산입니다.

2. Integer.parseInt(String.valueOf(tmp)): 이 표현식은 먼저 tmp 변수의 char 값을 String으로 변환한 다음, 그 String 값을 정수로 파싱합니다. 이 방법은 char 값을 먼저 String으로 변환하고 정수로 변환하는 과정을 거치기 때문에 1번 방법보다는 더 많은 연산이 필요할 수 있습니다. 하지만 결과적으로는 같은 숫자를 얻게 됩니다 ==> 다소 복잡한 과정을 거칩니다. 먼저 char 값을 String으로 변환하고, 그 다음에 해당 String 값을 다시 정수로 파싱합니다. 하지만 이러한 변환 작업 역시 매우 빠르게 이루어집니다.

대부분의 상황에서는 두 표현식 간 성능 차이가 미미하며, 코드의 가독성과 유지보수 가능성을 중시하는 것이 더 중요할 것입니다.

다른 사람 풀이 1

replaceAll()로 풀어서 내가 푼 코드보다 속도는 느리지만, 가독성은 좋다.

1. 입력 문자열을 정규식표현으로 알파벳일 경우 공백으로 대체한다.

2. for each문을 통해 숫자가 나올 경우에만 더해준다.

class Solution {
    public int solution(String my_string) {
        int answer = 0;

        String[] str = my_string.replaceAll("[a-zA-Z]", " ").split(" ");

        for(String s : str){
            if(!s.equals("")) answer += Integer.valueOf(s);
        }

        return answer;
    }
}
// s 출력값

s = 122
s = 3
s = 
s = 
s = 123
테스트 1 통과 (0.43ms, 74.3MB)
테스트 2 통과 (0.19ms, 67.6MB)
테스트 3 통과 (0.22ms, 74.1MB)
테스트 4 통과 (0.39ms, 72.5MB)
테스트 5 통과 (0.19ms, 73.9MB)
테스트 6 통과 (0.09ms, 76.3MB)
테스트 7 통과 (0.09ms, 73.8MB)
테스트 8 통과 (0.16ms, 72.7MB)
테스트 9 통과 (0.27ms, 71.7MB)
테스트 10 통과 (0.18ms, 77.3MB)

 

다른 사람 풀이 2

split()함수를 사용해서 replaceAll()보다는 속도면에서 빠르다.

1. 입력 문자열을 정규표현식 기준으로 String배열로 쪼개준다.

2. 해당 배열을 순회하면서 0보다 클때만 더해준다.

class Solution {
    public int solution(String my_string) {
        int answer = 0;
        String[] str = my_string.split("[a-zA-Z]");
        for(int i = 0 ; i < str.length;i++){
            if(str[i].length() > 0)
                answer+=Integer.parseInt(str[i]);
        }
        return answer;
    }
}
// split("[a-zA-Z]")의 출력

[122, 3, , , 123]
테스트 1 통과 (0.29ms, 71MB)
테스트 2 통과 (0.22ms, 77.9MB)
테스트 3 통과 (0.21ms, 77.6MB)
테스트 4 통과 (0.21ms, 77.3MB)
테스트 5 통과 (0.26ms, 74MB)
테스트 6 통과 (0.14ms, 79.3MB)
테스트 7 통과 (0.09ms, 76.2MB)
테스트 8 통과 (0.14ms, 67.7MB)
테스트 9 통과 (0.16ms, 75.4MB)
테스트 10 통과 (0.17ms, 80.1MB)

 

 

내가 예전에 푼 풀이

창피하지만 내가 작년에 풀었던 코드이다. 

어떻게 이렇게 풀었는지 기억도 잘 안나지만 당시에는 배열,리스트,조건문,반복문만 알아서 설계를 할 줄 몰랐고 이렇게 똥코드가 되어버렸다. 이래서 역시 강의를 듣고 기초 지식을 채우고, 계속 풀어보면서 문제해결력을 키워야 되는 것 같다.

import java.util.ArrayList;
class Solution {
    public int solution(String my_string) {
      int answer = 0;
        String[] temp = my_string.split("");
        //대문자 arraylist 생성
        ArrayList<String> capitalLetters = new ArrayList<>();
        for (int i = 0; i < 26; i++) {
            capitalLetters.add(String.valueOf((char) (97 + i)));
        }
        //소문자 arraylist 생성
        ArrayList<String> smallLetters = new ArrayList<>();
        for (int i = 0; i < 26; i++) {
            smallLetters.add(String.valueOf((char) (65 + i)));
        }

        int tempTens = 0;
        // split으로 쪼갠 my_stringq의 문자열배열 비교
        for (int i = 0; i < temp.length; i++) {
            if (!smallLetters.contains(temp[i]) && !capitalLetters.contains(temp[i])) {
                //배열의 0 번째일때 인덱스음수 비교 시 에러발생
                if (i >= 1) {
                    if (i >= 2) {
                        if (!smallLetters.contains(temp[i - 1]) && !capitalLetters.contains(temp[i - 1]) && !smallLetters.contains(temp[i - 2]) && !capitalLetters.contains(temp[i - 2])) {
                            int tempHundreds = Integer.parseInt(temp[i - 2] + temp[i - 1] + temp[i]);
                            answer -= tempTens;
                            answer += tempHundreds;
                            continue;
                        }
                    }
                    if (!smallLetters.contains(temp[i - 1]) && !capitalLetters.contains(temp[i - 1])) {
                        tempTens = Integer.parseInt(temp[i - 1] + temp[i]);
                        answer -= Integer.parseInt(temp[i - 1]);
                        answer += tempTens;
                        continue;
                    }

                }
                answer += Integer.parseInt(temp[i]);
            }
        }
        return answer;
    }
}
테스트 1 통과 (12.46ms, 76.2MB)
테스트 2 통과 (0.23ms, 76.2MB)
테스트 3 통과 (14.48ms, 79.8MB)
테스트 4 통과 (12.15ms, 79MB)
테스트 5 통과 (14.79ms, 80.8MB)
테스트 6 통과 (12.22ms, 74.7MB)
테스트 7 통과 (18.78ms, 91.8MB)
테스트 8 통과 (0.22ms, 73.1MB)
테스트 9 통과 (1.35ms, 72.5MB)
테스트 10 통과 (12.40ms, 82.4MB)