문제
N개의 정수 A[1], A[2], …, A[N]이 주어져 있을 때, 이 안에 X라는 정수가 존재하는지 알아내는 프로그램을 작성하시오.
입력
첫째 줄에 자연수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 N개의 정수 A[1], A[2], …, A[N]이 주어진다. 다음 줄에는 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 줄에는 M개의 수들이 주어지는데, 이 수들이 A안에 존재하는지 알아내면 된다. 모든 정수의 범위는 -2^31 보다 크거나 같고 2^31보다 작다.
출력
M개의 줄에 답을 출력한다. 존재하면 1을, 존재하지 않으면 0을 출력한다.
예제
입력:
5
4 1 5 2 3
5
1 3 7 9 5
출력:
1
1
0
0
1
코드1 - while문
using System;
using System.Text;
class Program
{
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder();
int totalC = int.Parse(Console.ReadLine());
string[] str = Console.ReadLine().Trim().Split();
int[] criteria = new int[str.Length];
int totalS = int.Parse(Console.ReadLine());
string[] search = Console.ReadLine().Trim().Split();
for(int i=0; i<str.Length; i++)
{
criteria[i] = int.Parse(str[i]);
}
Array.Sort(criteria);
for(int i=0; i<totalS; i++)
{
int low = 0;
int high = criteria.Length-1;
bool found = false;
while(low<=high && !found)
{
int mid = (low+high)/2;
if(criteria[mid] == int.Parse(search[i])) found = true;
else if(criteria[mid] > int.Parse(search[i])) high = mid-1;
else low = mid+1;
}
sb.Append(found?"1\n":"0\n");
}
Console.WriteLine(sb.ToString());
}
}
코드2 - 재귀함수
using System;
using System.Text;
class Program
{
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder();
int totalC = int.Parse(Console.ReadLine());
string[] str = Console.ReadLine().Trim().Split();
int[] criteria = new int[str.Length];
int totalS = int.Parse(Console.ReadLine());
string[] search = Console.ReadLine().Trim().Split();
for(int i=0; i<str.Length; i++)
{
criteria[i] = int.Parse(str[i]);
}
Array.Sort(criteria);
for(int i=0; i<totalS; i++)
{
sb.Append(BinarySearch(criteria, int.Parse(search[i]), 0, criteria.Length-1)? "1\n":"0\n");
}
Console.WriteLine(sb.ToString());
}
static bool BinarySearch(int[] criteria, int element, int low, int high)
{
if(low>high) return false;
int mid = (low+high)/2;
if(criteria[mid] == element) return true;
else if(criteria[mid] > element) return BinarySearch(criteria, element, low, mid-1);
else return BinarySearch(criteria, element, mid+1, high);
}
}
참고
이 문제를 풀 때 처음에는 단순히 IndexOf를 사용했지만 '시간 초과'로 인해 다른 방법을 사용해야 했다.
그래서 이진탐색을 이용해서 코드를 작성했더니 '시간 초과'는 아니었지만 '틀렸습니다'가 나왔다.
VSCode에서 돌려볼 땐 결과에 문제가 없었는데 왜 틀렸는지 알 수가 없었다.
그래서 반례를 찾아보다가 백준 질문글에서 발견한 다른 사람의 반례를 넣어봤더니 출력 결과가 이상했다.
반례)
7
1234567890 12345 987654321 1357924680 -1234543210 -999999999 2147483647
7
1111111111 1234567890 987654321 0 12345 -999999999 -2122222222
정답)
0
1
1
0
1
1
0
출력)
0
1
0
0
1
1
0
왜 그런가 원인을 찾아봤더니 처음에 코드 짤 때 criteria를 int가 아닌 string 배열로 해서 Sort했더니
string[] criteria = Console.ReadLine().Trim().Split();
Array.Sort(criteria);
[-1234543210] [-999999999] [12345] [1234567890] [1357924680] [2147483647] [987654321]
위 결과처럼 정렬됐다...
숫자의 첫 번째만 보고 정렬되어서 이상한 결과가 나왔던 것이다.
그래서 입력받은 string을 str에 먼저 저장하고 다시 criteria에 int로 변환해서 저장했더니 해결됐다.
string[] str = Console.ReadLine().Trim().Split();
int[] criteria = new int[str.Length];
for(int i=0; i<str.Length; i++)
{
criteria[i] = int.Parse(str[i]);
}
Array.Sort(criteria);
(추가)
코드3 - List<T>.BinarySearch 메소드
using System;
using System.Text;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder();
int totalC = int.Parse(Console.ReadLine());
string[] str = Console.ReadLine().Trim().Split();
List<int> criteria = new List<int>();
int totalS = int.Parse(Console.ReadLine());
string[] search = Console.ReadLine().Trim().Split();
for(int i=0; i<str.Length; i++)
{
criteria.Add(int.Parse(str[i]));
}
criteria.Sort();
for(int i=0; i<totalS; i++)
{
int index = criteria.BinarySearch(int.Parse(search[i]));
sb.Append(index < 0? "0\n":"1\n");
}
Console.WriteLine(sb.ToString());
}
}
'Coding > BaekJoon' 카테고리의 다른 글
[BaekJoon/C#] 4344. 평균은 넘겠지 (0) | 2021.10.02 |
---|---|
[BaekJoon/C#] 2504. 괄호의 값 (0) | 2021.09.25 |
[BaekJoon/C#] 9012. 괄호 (0) | 2021.09.25 |
[BaekJoon/C#] 10773. 제로 (0) | 2021.09.24 |
[BaekJoon/C#] 10828. 스택 (시간초과 해결) (0) | 2021.09.24 |