프로그래머스 입문 120904 숫자 찾기
문제
매개변수로 자연수 num과 한 자리 자연수 k가 주어진다.
num에 k가 포함되어 있으면 해당 위치를 반환하고, 포함되어 있지 않으면 -1을 반환한다.
| num | k | result |
|---|---|---|
| 29183 | 1 | 3 |
| 232443 | 4 | 4 |
| 123456 | 7 | -1 |
| 102 | 0 | 2 |
| 102 | 2 | 3 |
풀이
num에 k가 여러 개 있으면 가장 왼쪽에 등장한 k의 위치를 반환해야 한다.
위치를 나타내는 반환값 result는 0이 아닌 1부터 세어 반환한다는 점에 유의해야 한다.
문자열로 바꿔 찾기
sprintf로 변환하기
#include <stdio.h>
int solution(int num, int k)
{
char numbers[11] = { 0 };
sprintf(numbers, "%d", num);
for (int i = 0; numbers[i] != '\0'; i++)
{
if (numbers[i] - '0' == k)
{
return i + 1;
}
}
return -1;
}
int가 표현할 수 있는 최댓값은 2^31 - 1인 2,147,483,647이고 자릿수는 10자리다.
숫자와 널 문자까지 담아야 하므로 numbers 배열의 크기를 11로 선언한다.
sprintf 함수로 int 값을 문자열로 바꾼 뒤, 앞에서부터 한 자리씩 k와 비교한다.
배열의 인덱스는 0부터 시작하지만, 문제에서 요구하는 위치는 1부터 센 값이다.
따라서 일치하는 숫자를 찾으면 i + 1을 반환한다.
직접 문자열 변환하기
int solution(int num, int k)
{
char numbers[11] = { 0 };
int len = 0;
while (num > 0)
{
numbers[len++] = num % 10 + '0';
num /= 10;
}
for (int i = 0; i < len / 2; i++)
{
char temp = numbers[i];
numbers[i] = numbers[len - i - 1];
numbers[len - i - 1] = temp;
}
for (int i = 0; i < len; i++)
{
if (numbers[i] - '0' == k)
{
return i + 1;
}
}
return -1;
}
나머지 연산자로 일의 자리부터 숫자를 하나씩 가져와서 문자열로 만든다.
이렇게 만든 문자열은 역순이므로 길이의 절반만큼 반복하며 원래 순서로 뒤집는다.
앞자리부터 나눗셈으로 찾기
int solution(int num, int k)
{
int divisor = 1;
while (num / divisor >= 10)
{
divisor *= 10;
}
int position = 1;
while (divisor > 0)
{
if (num / divisor == k)
{
return position;
}
num %= divisor;
divisor /= 10;
position++;
}
return -1;
}
앞자리부터 숫자를 가져오려면 먼저 num의 자릿수와 같은 10의 제곱을 만들고, 그 수로 num을 나누면 된다.
예를 들어 123에서 1을 가져오려면 123을 100으로 나누면 된다.
그래서 divisor를 10씩 곱해 num과 자릿수가 같은 값으로 만든다.
이제 divisor와 num의 자릿수가 같아졌다.
num / divisor로 현재 앞자리 숫자를 구하고, k와 같으면 위치를 반환한다.
현재 앞자리 숫자를 확인했으니 num %= divisor로 num의 자릿수를 앞에서 하나 줄인다.
divisor도 10으로 나눠 자릿수를 하나 줄인다.
이 과정을 반복하다가 k를 찾으면 현재 위치를 반환하고, 끝까지 찾지 못하면 -1을 반환한다.
뒷자리부터 살펴보며 위치 계산
int solution(int num, int k)
{
int target_index_from_right = -1;
int digit_count = 0;
while (num > 0)
{
if (num % 10 == k)
{
target_index_from_right = digit_count;
}
digit_count++;
num /= 10;
}
if (target_index_from_right == -1)
{
return -1;
}
return digit_count - target_index_from_right;
}
오른쪽 끝 자리를 0번째 인덱스로 두고, 전체 숫자의 길이를 세어 나가면서 k의 오른쪽 기준 인덱스도 찾는다.
오른쪽부터 전체를 탐색하므로 k가 중복될 때, 최종적으로 가장 왼쪽에 있는 k의 인덱스가 남는다.
전체 자릿수에서 오른쪽 기준 인덱스를 빼면 왼쪽에서 1부터 센 위치를 구할 수 있다.