Post

[Programmers] #181921 - 배열 만들기 2 [Java][C++][Python]

l부터 r까지 정수를 순회하며 0과 5로만 이루어진 수를 걸러내는 문제.

[Programmers] #181921 - 배열 만들기 2 [Java][C++][Python]

문제 링크


1. 아이디어

l부터 r까지의 정수를 하나씩 확인하며 각 자리수가 전부 0 또는 5로만 이루어졌는지 판별한다. 판별 함수는 숫자를 10으로 나눈 나머지를 확인하는 과정을 자리수가 다 없어질 때까지 반복하다가, 0도 5도 아닌 자리가 하나라도 나오면 그 즉시 false를 반환하고 그렇지 않으면 true를 반환한다. 조건을 만족하는 수를 오름차순으로 모으고, 하나도 없으면 -1을 담은 배열을 대신 반환한다.


2. 복잡도

접근시간공간
풀이$O(N \log R)$$O(N)$

($N$ = l부터 r까지의 정수 개수, $\log R$ = r의 자리수)


3. 코드

풀이 [Java][C++][Python]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.*;

class Solution {
    public int[] solution(int l, int r) {
        List<Integer> list = new ArrayList<>();
        for (int i = l; i <= r; i++) {
            if (func(i)) list.add(i);
        }

        if (list.isEmpty()) return new int[]{-1};
        return list.stream().mapToInt(Integer::intValue).toArray();
    }

    static boolean func(int x) {
        while (x > 0) {
            int r = x % 10;
            if (r != 0 && r != 5) return false;
            x /= 10;
        }

        return true;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <bits/stdc++.h>
using namespace std;

bool func(int x) {
    while (x > 0) {
        int r = x % 10;
        if (r != 0 && r != 5) return false;
        x /= 10;
    }

    return true;
}

vector<int> solution(int l, int r) {
    vector<int> v;
    for (int i = l; i <= r; i++) {
        if (func(i)) v.push_back(i);
    }

    if (v.empty()) return {-1};
    return v;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
def func(x):
    while x > 0:
        r = x % 10
        if r != 0 and r != 5:
            return False
        x //= 10

    return True


def solution(l, r):
    ans = [x for x in range(l, r + 1) if func(x)]
    return ans if ans else [-1]

참고

$[l, r]$ 전체를 순회하며 0과 5로만 이루어진 수를 걸러내는 대신, 그런 수를 직접 구성하는 방법도 있다. $r \le 1{,}000{,}000$이라 최대 7자리인데, 첫 자리는 반드시 5(선행 0 불가)이고 나머지 자리는 0 또는 5 중 하나이므로 자릿수 $k$일 때 만들 수 있는 수는 $2^{k-1}$개, 1~7자리를 다 더해도 127개뿐이다. 이 127개를 BFS/재귀로 생성한 뒤 $[l, r]$ 범위만 걸러내면 순회량이 최대 100만에서 127로 줄어든다.


This post is licensed under CC BY 4.0 by the author.