• 문제

배열 arr가 주어집니다. 배열 arr의 각 원소는 숫자 0부터 9까지로 이루어져 있습니다. 이때, 배열 arr에서 연속적으로 나타나는 숫자는 하나만 남기고 전부 제거하려고 합니다. 단, 제거된 후 남은 수들을 반환할 때는 배열 arr의 원소들의 순서를 유지해야 합니다. 예를 들면,

  • arr = [1, 1, 3, 3, 0, 1, 1] 이면 [1, 3, 0, 1] 을 return 합니다.
  • arr = [4, 4, 4, 3, 3] 이면 [4, 3] 을 return 합니다.

배열 arr에서 연속적으로 나타나는 숫자는 제거하고 남은 수들을 return 하는 solution 함수를 완성해 주세요.


[제한사항]

  • 배열 arr의 크기 : 1,000,000 이하의 자연수
  • 배열 arr의 원소의 크기 : 0보다 크거나 같고 9보다 작거나 같은 정수

[입출력 예]

 

 

 


추측) 

String을 이용하면 int Array > String > int Array 로 형변환이 일어나고

ArrayList면 int Array > ArrayList > int Array로 형변환 일어나고..

형 변환 자체 횟수는 동일하나, String이나 ArrayList 중 어느쪽이 더 효율적인가..

 

for문을 돌려 배열의 값을 하나하나 출력하는데 이때 카운트를 집어넣어 같은 값일때는 카운트를 올리고 문자열에는 추가하지 않는다. 같은 값이 아니라면 카운트를 초기화한다. 

 

 

소스코드) 

* 1차) 실패 - 결과값은 전부성공했으나 효율성 테스트에서 떨어진 케이스

public int[] solution(int []arr) {
    int[] answer = {};
    String result = "";

    for(int i=0; i<arr.length; i++){		// Arrays.asList() 가 사람들처럼 안나와..
        if(i == 0){
            result += Integer.toString(arr[i]);
            continue;
        }

        if(arr[i-1] == arr[i]){
            continue;
        } else {
            result += Integer.toString(arr[i]);
        }
    }
    answer = new int[result.length()];
    for(int j=0; j<result.length(); j++){
        answer[j] = Integer.parseInt(result.substring(j,j+1));
    }

    return answer;
}

* 2차) 성공 - 충격 String에서 변환하는 게 더 효율성이 안좋은 것 같다. 흐름은 바꾸지 않고 ArrayList로만 바꿔서 했는데 통과했다.

public int[] solution(int []arr) {
    int[] answer = {};

    ArrayList<Integer> arr1 = new ArrayList<Integer>();

    for(int i=0; i<arr.length; i++){
        if(i==0){
            arr1.add(arr[0]);
        } else {
            if(arr[i-1] != arr[i]){
                arr1.add(arr[i]);
            }
        }
    }

    answer = new int[arr1.size()];
    for(int j=0; j<answer.length; j++){
        answer[j] = arr1.get(j);
    }

    return answer;
}

 

리뷰) 

형변환에 따른 효율성을 비교를 잘해야 할 거 같다. 효율성 비교할 수 있는 방법을 찾아보자.

 

  • 문제

로또 6/45(이하 '로또'로 표기)는 1부터 45까지의 숫자 중 6개를 찍어서 맞히는 대표적인 복권입니다. 아래는 로또의 순위를 정하는 방식입니다. (실제로 사용되는 로또 순위의 결정 방식과는 약간 다르지만, 이 문제에서는 지문에 명시된 대로 로또 순위를 결정하도록 합니다.)

순위당첨 내용
1 6개 번호가 모두 일치
2 5개 번호가 일치
3 4개 번호가 일치
4 3개 번호가 일치
5 2개 번호가 일치
6(낙첨) 그 외

로또를 구매한 민우는 당첨 번호 발표일을 학수고대하고 있었습니다. 하지만, 민우의 동생이 로또에 낙서를 하여, 일부 번호를 알아볼 수 없게 되었습니다. 당첨 번호 발표 후, 민우는 자신이 구매했던 로또로 당첨이 가능했던 최고 순위와 최저 순위를 알아보고 싶어 졌습니다.
알아볼 수 없는 번호를 0으로 표기하기로 하고, 민우가 구매한 로또 번호 6개가 ( 44, 1, 0, 0, 31 25 )라고 가정해보겠습니다. 당첨 번호 6개가 ( 31, 10, 45, 1, 6, 19 )라면, 당첨 가능한 최고 순위와 최저 순위의 한 예는 아래와 같습니다.

당첨 번호3110451619결과
최고 순위 번호 31 0→10 44 1 0→6 25 4개 번호 일치, 3등
최저 순위 번호 31 0→11 44 1 0→7 25 2개 번호 일치, 5등
  • 순서와 상관없이, 구매한 로또에 당첨 번호와 일치하는 번호가 있으면 맞힌 걸로 인정됩니다.
  • 알아볼 수 없는 두 개의 번호를 각각 10, 6이라고 가정하면 3등에 당첨될 수 있습니다.
    • 3등을 만드는 다른 방법들도 존재합니다. 하지만, 2등 이상으로 만드는 것은 불가능합니다.
  • 알아볼 수 없는 두 개의 번호를 각각 11, 7이라고 가정하면 5등에 당첨될 수 있습니다.
    • 5등을 만드는 다른 방법들도 존재합니다. 하지만, 6등(낙첨)으로 만드는 것은 불가능합니다.

민우가 구매한 로또 번호를 담은 배열 lottos, 당첨 번호를 담은 배열 win_nums가 매개변수로 주어집니다. 이때, 당첨 가능한 최고 순위와 최저 순위를 차례대로 배열에 담아서 return 하도록 solution 함수를 완성해주세요.


[제한사항]

  • lottos는 길이 6인 정수 배열입니다.
  • lottos의 모든 원소는 0 이상 45 이하인 정수입니다.
    • 0은 알아볼 수 없는 숫자를 의미합니다.
    • 0을 제외한 다른 숫자들은 lottos에 2개 이상 담겨있지 않습니다.
    • lottos의 원소들은 정렬되어 있지 않을 수도 있습니다.
  • win_nums은 길이 6인 정수 배열입니다.
  • win_nums의 모든 원소는 1 이상 45 이하인 정수입니다.
    • win_nums에는 같은 숫자가 2개 이상 담겨있지 않습니다.
    • win_nums의 원소들은 정렬되어 있지 않을 수도 있습니다.

[입출력 예]

 


추측) 

0은 당첨, 낙첨의 두 경우수를 가진다고 생각하면 될거 같고 숫자 값을 따질 필요는 없을 듯하다.

for을 돌려 두 배열의 수를 비교하고 값이 있다면 당첨 카운트를 올린다.

그리고 이 for문 안에서 0의 카운트도 별도의 변수로 추가한다.

최종적으로 나온 두개의 카운트를 가지고 최저 순위와 최고 순위를 따지는데

최고 순위 당첨수라고 하면 - 당첨 카운트 + 0의 카운트 수 (0의 숫자가 다 당첨되었다는 가정하의 결과값)

최저 순위 당첨수라고 하면 - 당첨 카운트 + 그냥 숫자 0 (0의 숫자가 다 낙첨되었다는 가정하의 결과값)

이 당첨수를 각각 switch로 해당하는 순위로 바꿔주어 2길이의 배열에 각각 대입해 주면 될 거 같다. 

 

소스코드) 

* 1차) 성공

public int[] solution(int[] lottos, int[] win_nums) {
    int[] answer = new int[2];
    int zeroCnt = 0;
    int winNumCnt = 0;
    for(int i=0; i<lottos.length; i++){
        for(int j=0; j<win_nums.length; j++){
            if(lottos[i] == 0){
                zeroCnt++;
                break;
            }
            if(lottos[i] == win_nums[j]){
                winNumCnt++;
            }
        }
    }

    answer[0] = winNumCnt + zeroCnt;
    answer[1] = winNumCnt + 0;

    for(int k=0; k<2; k++){
        switch (answer[k]) {
            case 6 :
                answer[k] = 1;
                break;
            case 5:
                answer[k] = 2;
                break;
            case 4:
                answer[k] = 3;
                break;
            case 3:
                answer[k] = 4;
                break;
            case 2:
                answer[k] = 5;
                break;
            case 1:
            case 0:
                answer[k] = 6;
        }
    }

    return answer;
}

 

리뷰) 

당첨여부를 따질때 0이 어떤 숫자인지 알 필요가 없다는 걸 생각하면 좀 쉬운 문제였다.

 

'Coding Test > Algorithm' 카테고리의 다른 글

Programmers] 최소직사각형  (0) 2022.11.21
Programmers] 같은 숫자는 싫어  (0) 2022.11.21
Programmers] 두 개 뽑아서 더하기  (0) 2022.11.21
Programmers] 3진법 뒤집기  (0) 2022.11.19
Programmers] 하샤드 수  (0) 2022.11.19

 

  • 정수 배열 numbers가 주어집니다. numbers에서 서로 다른 인덱스에 있는 두 개의 수를 뽑아 더해서 만들 수 있는 모든 수를 배열에 오름차순으로 담아 return 하도록 solution 함수를 완성해주세요.

[제한사항]

  • numbers의 길이는 2 이상 100 이하입니다.
    • numbers의 모든 수는 0 이상 100 이하입니다.

[입출력 예]

 


추측) 

지성님이 알려준 배열인덱스를 플래그로 써서 풀이하는게 맞는거 같다.

최대 나올수 있는 경우의 수는 100 + 100 이니까 길이 200의 배열을 생성하고

수는 0 + 0도 나올 수 있으니 0도 포함해야 하니까 길이를 201인가? 

경우의 수 값을 인덱스 삼아 해당 인덱스에 넣고 ..

근데 디폴트 값인 0이랑 0+0은 어떻게 판별하지? -> 카운트

 

 

소스코드) 

* 1차) 성공  [메모리: 81.1 MB, 시간: 0.20 ms]

public int[] solution(int[] numbers) {
    int[] arr = new int[201];
    int[] answer = {};
    int zeroCnt = 0;
    for(int i=0; i<numbers.length; i++){
        if(i == numbers.length){
            break;
        }
        for(int j=i+1; j<numbers.length; j++){
            int idx = numbers[i] + numbers[j];
            if(idx == 0){
                zeroCnt++;
            } else if (arr[idx] != idx){
                arr[idx] = idx;
            }
        }
    }

    ArrayList<Integer> arr1 = new ArrayList<>();
    for(int j=0; j<arr.length; j++){
        if(j==0 && zeroCnt != 0){
            arr1.add(0);
            continue;
        }
        if(arr[j] != 0){
            arr1.add(arr[j]);
        }
    }

    answer = new int[arr1.size()];
    for(int k=0; k<answer.length; k++){
        answer[k] = arr1.get(k);
    }

    return answer;
}

 

리뷰) 

배열처리 할때 형변환 개선에 대해서 심히 고민해 볼 필요가 있다. new ArrayList<>(Arrays.asList())를 사용해보고 싶었는데 이게 그냥 배열을 List로 변경해주는게 아니라 List안에 배열을 집어넣는거라 사람들이 써놓은 글이랑 결과값이 달라서 사용할 수가 없었다. 왜 값이 다를까 ? 찾아봐야겠다. 

 

 

 

  • 자연수 n이 매개변수로 주어집니다. n을 3진법 상에서 앞뒤로 뒤집은 후, 이를 다시 10진법으로 표현한 수를 return 하도록 solution 함수를 완성해주세요.

[제한사항]

  • n은 1 이상 100,000,000 이하인 자연수입니다.

[입출력 예]

 

 

 


추측) 

3진법을 표현하려면 3으로 나눈 나머지를 각자리의 수로 목을 다시또 3으로 나눈 나머지를 수로 하므로 이를 통해 3진법을 구한다. 나온순서대로 저장하면 바로 앞뒤 반전된 체니까 자리를 바꾸진 않아도 되는데... 순서대로 저장하는 방법으로 배열말고 String한번 이용해보자 문자는 붙이는 게 편하니까 

합계를 더할 변수를 선언해 주고

자리수만큼 for문을 돌리기 위해 문자열 길이 값을 구하고 해당 값 만큼 돌리면서

문자열을 역순으로 가져와 그 수를 10진법으로 되돌린다.

 

소스코드) 

* 1차) 성공 [ 메모리: 74.7 MB, 시간: 1.72 ms ]

public int solution(int n) {
    int answer = 0;
    int num = 0;
    String numString = "";
    while(n > 0){
        num = n % 3;
        n /= 3;
        numString += String.valueOf(num);
    }

    String numOne = "";
    int numStringLen = numString.length();
    for(int i=0; i<numStringLen; i++){
        numOne = numString.substring(numStringLen-1-i, numStringLen-i);
        int squareNum = (int) Math.pow(3, i);
        int multiply = Integer.parseInt(numOne);
        answer += squareNum * multiply;
    }

    return answer;
}

 

리뷰) 

추측한 대로 구현한 편이지만 10진법 돌리는 걸 오랜만에 하니까 살짝 버벅였다; 기본적인 수학지식을 가지고 있는 게 평소 사고를 하는데 큰 도움이 될 거 같다. 

 

 

 

 

사용한 함수)

1차)

* String.valueOf(x) : int x를 문자열로 바꿔준다.

* Math.pow(x, y) : x의 y승의 숫자를 구한다.

* Integer.parseInt(x) : String을 int로 변환한다.

 
  • 양의 정수 x가 하샤드 수이려면 x의 자릿수의 합으로 x가 나누어져야 합니다. 예를 들어 18의 자릿수 합은 1+8=9이고, 18은 9로 나누어 떨어지므로 18은 하샤드 수입니다. 자연수 x를 입력받아 x가 하샤드 수인지 아닌지 검사하는 함수, solution을 완성해주세요.

[제한사항]

  • x는 1 이상, 10000 이하인 정수입니다.

[입출력 예] 

 

 


추측) 

int변수를 선언하고

while문으로 주어진수가 0 보다 크면 10씩 나눈 나머지로 자릿수를 반복해서 구하며 

10씩 나눈 몫을 주어진수에 다시 대입한다.

변수에 += 대입한다.

while문이 종료되면

합산한 변수로 원래의 수를 나누어 나머지가 0이면, 하샤드 수이므로 true, 나머지가 있으면 false를 반환한다.

 

소스코드) 

* 1차) 성공 [메모리: 73.9 MB, 시간: 0.03 ms]

public boolean solution(int x) {
    boolean answer = true;
    int sum = 0;
    int originNum = x;

    while(x > 0){
        sum += x%10;
        x /= 10;
    }

    if(originNum % sum != 0){
        answer = false;
    }

    return answer;
}

 

리뷰) 

얼마만의 1차 코드 합격인가 ㅠㅠㅠ

 

다른사람 풀이를 보다 보니 originNum % sum == 0 식을 가지고 true, false를 표현하는 방식도 있었고

숫자를 문자열로 바꾸어 아스키코드로 푸는 방식도 여기서 보인다. 수행시간이 어떨까???  

+ Recent posts