728x90

통계학 

 
 
시간 제한메모리 제한제출정답맞힌 사람정답 비율
2 초 256 MB 160120 38733 31053 26.358%

문제

수를 처리하는 것은 통계학에서 상당히 중요한 일이다. 통계학에서 N개의 수를 대표하는 기본 통계값에는 다음과 같은 것들이 있다. 단, N은 홀수라고 가정하자.

  1. 산술평균 : N개의 수들의 합을 N으로 나눈 값
  2. 중앙값 : N개의 수들을 증가하는 순서로 나열했을 경우 그 중앙에 위치하는 값
  3. 최빈값 : N개의 수들 중 가장 많이 나타나는 값
  4. 범위 : N개의 수들 중 최댓값과 최솟값의 차이

N개의 수가 주어졌을 때, 네 가지 기본 통계값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.

출력

첫째 줄에는 산술평균을 출력한다. 소수점 이하 첫째 자리에서 반올림한 값을 출력한다.

둘째 줄에는 중앙값을 출력한다.

셋째 줄에는 최빈값을 출력한다. 여러 개 있을 때에는 최빈값 중 두 번째로 작은 값을 출력한다.

넷째 줄에는 범위를 출력한다.

예제 입력 1 복사

5
1
3
8
-2
2

예제 출력 1 복사

2
2
1
10

예제 입력 2 복사

1
4000

예제 출력 2 복사

4000
4000
4000
0

예제 입력 3 복사

5
-1
-2
-3
-1
-2

예제 출력 3 복사

-2
-2
-1
2

예제 입력 4 복사

3
0
0
-1

예제 출력 4 복사

0
0
0
1

(0 + 0 + (-1)) / 3 = -0.333333... 이고 이를 첫째 자리에서 반올림하면 0이다. -0으로 출력하면 안된다.

 

 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>


int compare(const void* a, const void* b) {
	int int_a = *(int*)a;
	int int_b = *(int*)b;

	if (int_a < int_b) return -1;
	else if (int_a > int_b) return 1;
	else return 0;
}

int mean(int* arr, int size) {
	double sum = 0; 
	for (int i = 0; i < size; i++) {
		sum += arr[i];
	}
	return (int)round(sum/size);
}

int median(int* arr, int size) {
	int indexA = 0, indexB = 0;
	int temp[2] = { 0 };
	//sort first

	if (size % 2 == 0) { //even case
		indexA = size / 2 - 1;
		indexB = size / 2;
		temp[0] = arr[indexA];
		temp[1] = arr[indexB];
		return mean(temp, 2);

	}
	else {//odd case
		indexA = size / 2;
		return arr[indexA];
	}
}



int most_num(int* arr, int size) {
	int maxCount = 0, mode = arr[0], count = 1, modeCount = 0; //maxCount : 현재 최고 빈도수, mode = 현재 최빈값, count = 현재 반복수, modeCount = 현재 최빈값 개수

	for (int i = 1; i < size; i++) {
		if (arr[i] ==  arr[i - 1]) { //같은 원소를 발견하면
			count++;  //count + 1
		}
		else { //다른 원소를 발견하면
			if (count > maxCount) { //만약, 빈도수가 더 큰값이면
				maxCount = count; //최고 빈도수를 업데이트
				mode = arr[i - 1]; //최고 빈도수를 가지는 값을 업데이트
				modeCount = 1; //최고 빈도수를 1개로 업데이트 
			}
			else if (count == maxCount) { //같은 빈도수를 가지는 값일 경우, 특히 빈도수가 현재 최고 빈도수값이랑 같을 경우
				if (modeCount == 1) { //최고 빈도수의 개수가 하나일 경우에만
					mode = arr[i - 1]; //최고 빈도수 값을 업데이트, 왜냐하면 두번째로 작은 수를 기록해야기 때문
					modeCount++; //최고 빈도수를 가지는 값의 개수를 업데이트, 2개 이상이므로 이제 기록 안됨
				}
			}
			count = 1; // else 문 마지막 문장으로, 다른 원소를 발견했으므로 count값 초기화
		}
	}
	// Check last element
	if (count > maxCount) { //마지막에 최빈값이 나온 경우
		mode = arr[size - 1];
	}
	else if (count == maxCount && modeCount == 1) { //배열의 끝에 최빈값이 나오는 경우. 끝에 나오는 경우가 아닌 이상 modeCount는 1이 아니다. 왜냐? 위 for문의 else-elseif문에서 해당 경우를 처리했기 때문
		mode = arr[size - 1]; //그 값 리턴
	}
	return mode;
}

int range(int* arr, int size) {
		return arr[size - 1] - arr[0];
}


int main() {
	int size = 0;
	int* arr = NULL;
	
	scanf("%d", &size);
	arr = (int*)malloc(sizeof(int) * size);
	for (int i = 0; i < size; i++) {
		scanf("%d", &arr[i]);
	}

	qsort(arr, size, sizeof(int), compare);

	printf("%d\n",mean(arr, size));
	printf("%d\n",median(arr, size)); //n이 홀수이므로,  arr[size/2] 로 처리하여도 된다
	printf("%d\n",most_num(arr, size));
	printf("%d\n",range(arr, size));

}

 

최빈값을 구할 때, for문에서 i를 1부터 시작하여 size전까지 돈다.

그리고, 우측값과 좌측값을 비교하여 같은지 여부를 확인하고, (정렬되어 있다) 같은 경우엔 count++, 다를 경우 값을 업데이트 할지 여부를 결정한다. 하지만! 위 for문 로직으로는 배열의 끝에 최빈값이 등장한 경우를 처리하지 못한다.

(i를 기준으로 arr[i]와 arr[i-1]과 다를 경우 변수를 업데이트하는데, 위 경우에는 다른 경우가 없기 때문) 따라서, 해당 경우return하기 전에 조건문으로 한번 더 확인한다.

 

생각보다 많이 까다로웠던 문제다.

728x90
728x90

부녀회장이 될테야 

 

 

시간 제한메모리 제한제출정답맞힌 사람정답 비율
0.5 초 (추가 시간 없음) 128 MB 100353 56482 47987 57.340%

문제

평소 반상회에 참석하는 것을 좋아하는 주희는 이번 기회에 부녀회장이 되고 싶어 각 층의 사람들을 불러 모아 반상회를 주최하려고 한다.

이 아파트에 거주를 하려면 조건이 있는데, “a층의 b호에 살려면 자신의 아래(a-1)층의 1호부터 b호까지 사람들의 수의 합만큼 사람들을 데려와 살아야 한다” 는 계약 조항을 꼭 지키고 들어와야 한다.

아파트에 비어있는 집은 없고 모든 거주민들이 이 계약 조건을 지키고 왔다고 가정했을 때, 주어지는 양의 정수 k와 n에 대해 k층에 n호에는 몇 명이 살고 있는지 출력하라. 단, 아파트에는 0층부터 있고 각층에는 1호부터 있으며, 0층의 i호에는 i명이 산다.

입력

첫 번째 줄에 Test case의 수 T가 주어진다. 그리고 각각의 케이스마다 입력으로 첫 번째 줄에 정수 k, 두 번째 줄에 정수 n이 주어진다

출력

각각의 Test case에 대해서 해당 집에 거주민 수를 출력하라.

제한

  • 1 ≤ k, n ≤ 14

예제 입력 1 복사

2
1
3
2
3

예제 출력 1 복사

6
10

 

 

해당 문제는 다이나믹 프로그래밍 문제이다.

 

다이나믹 프로그래밍이란, 

복잡한 문제를 여러 개의 작은 하위 문제로 나누어 해결하는 방식을 말한다.

 

수열과 같이 특정한 규칙이 반복되는 경우, 해당 방법으로 해결할수 있다.

다이나믹 프로그래밍 문제를 푸는 방식은 1.바텀업, 2.탑다운 방식으로 총 2가지가 있는데, 

1. 바텀업 방식 -> 반복문을 활용하여, 필요한 정답을 모두 데이터에 저장한 후, 불러옴

2. 탑다운 방식-> 재귀함수를 이용하여, 필요한 값을 기준으로 하나하나 내려가면서(재귀함수를 통해) 더이상 내려갈 필요 없는 부분까지 내려간 후, 위 값을 이용해 다시 올라옴 (재귀함수 원리)

 

바텀업 방식은, 필요하지 않은 정답까지 모두 불러옴으로 시간과 자원을 낭비하는 단점이 있고

탑다운 방식은 스택 오버플로우 위험성과 재귀 호출의 오버헤드로 인한 단점이 있다. (흔히 재귀함수의 단점) 

 

 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int cal(int k, int n) {
	if (k == 0) {
		return n;
	}
	int temp = 0;
	for (int i = 1; i <= n; i++)
		temp += cal(k - 1, i);
	return temp;
}

int main() {
	int size;
	int n, k;
	scanf("%d", &size);
	for (int i = 0; i < size; i++) {
		scanf("%d %d", &n, &k);
		printf("%d\n", cal(n, k));
	}
	
	return 0;
}

 

재귀함수는 직관적이라 이해/작성 하기 쉬움으로, 탑다운 방식으로 작성하였다.

728x90

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 1003 피보나치 함수  (0) 2024.03.04
[백준] 2108 통계학  (2) 2024.02.27
[백준] 2292 벌집  (0) 2024.02.26
[백준] 10814 나이순 정렬  (0) 2024.02.25
[백준] 9012 괄호  (0) 2024.02.25
728x90

벌집 

 
시간 제한메모리 제한제출정답맞힌 사람정답 비율
2 초 128 MB 173331 78473 66792 44.798%

문제

위의 그림과 같이 육각형으로 이루어진 벌집이 있다. 그림에서 보는 바와 같이 중앙의 방 1부터 시작해서 이웃하는 방에 돌아가면서 1씩 증가하는 번호를 주소로 매길 수 있다. 숫자 N이 주어졌을 때, 벌집의 중앙 1에서 N번 방까지 최소 개수의 방을 지나서 갈 때 몇 개의 방을 지나가는지(시작과 끝을 포함하여)를 계산하는 프로그램을 작성하시오. 예를 들면, 13까지는 3개, 58까지는 5개를 지난다.

입력

첫째 줄에 N(1 ≤ N ≤ 1,000,000,000)이 주어진다.

출력

입력으로 주어진 방까지 최소 개수의 방을 지나서 갈 때 몇 개의 방을 지나는지 출력한다.

예제 입력 1 복사

13

예제 출력 1 복사

3

 

 

경계값을 기준으로 보면, 

1, 1+6, 1+6+12, ... {1+6+12 .. + 6*(n)}와 같은 형식으로 이루어진다.

 

수가 주어지면, 위 형식의 경계값 중 주어진 수보다 작으면서 가장 가까운 경계값을 찾은 후 이를 이용해 방의 수를 구할 수 있다.

 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
	int num;
	scanf("%d", &num);
    
	if (num == 1) {
		printf("1");
		return 0;
	}
	
	int index = 0;
	int boundary = 1;
	
	while (boundary < num) {
		boundary = boundary + 6 * index++;
	}
	printf("%d", index);

	return 0;
}

 

1일때는 예외처리가 필요하다.

728x90

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 2108 통계학  (2) 2024.02.27
[백준] 2775 부녀회장이 될테야 (다이나믹 프로그래밍)  (0) 2024.02.26
[백준] 10814 나이순 정렬  (0) 2024.02.25
[백준] 9012 괄호  (0) 2024.02.25
[백준] 2798 블랙잭  (1) 2024.02.25
728x90

요세푸스 문제 0 

 
시간 제한메모리 제한제출정답맞힌 사람정답 비율

 

2 초 512 MB 74836 42388 35521 56.483%

문제

요세푸스 문제는 다음과 같다.

1번부터 N번까지 N명의 사람이 원을 이루면서 앉아있고, 양의 정수 K(≤ N)가 주어진다. 이제 순서대로 K번째 사람을 제거한다. 한 사람이 제거되면 남은 사람들로 이루어진 원을 따라 이 과정을 계속해 나간다. 이 과정은 N명의 사람이 모두 제거될 때까지 계속된다. 원에서 사람들이 제거되는 순서를 (N, K)-요세푸스 순열이라고 한다. 예를 들어 (7, 3)-요세푸스 순열은 <3, 6, 2, 7, 5, 1, 4>이다.

N과 K가 주어지면 (N, K)-요세푸스 순열을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N과 K가 빈 칸을 사이에 두고 순서대로 주어진다. (1 ≤ K ≤ N ≤ 1,000)

출력

예제와 같이 요세푸스 순열을 출력한다.

예제 입력 1 복사

7 3

예제 출력 1 복사

<3, 6, 2, 7, 5, 1, 4>

 

해당 문제는 queue를 이용해서, 일정한 간격대로 pop하는 문제이다.

본인은 이 문제를 출제 의도에 맞지 않게 풀었는데, 방법으론 원형 링크드 리스트를 사용해 모든 수를 출력할때까지, 일정한 간격으로 출력하는 방법이였다. 의도에 맞지 않게 풀었기에, 코드가 보기 좋지 않다.

 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

typedef struct CircleQueue {
	int id;
	char is_out;
	struct CircleQueue* next;
}UserQueue;

int main() {
	int n, k;
	int printed_num = 0, count = 1;
	scanf("%d %d", &n, &k);
	UserQueue* p = (UserQueue*)malloc(sizeof(UserQueue) * n);

	for (int i = 0; i < n - 1; i++) {
		p[i].id = i + 1;
		p[i].is_out = 0;
		p[i].next = &p[i + 1];
	}

	p[n-1].id = n; //원형 링크드 리스트를 위해 직접 초기화
	p[n-1].is_out = 0;
	p[n-1].next = &p[0];//마지막 구조체는 첫 구조체를 가리킴

	UserQueue* temp = &p[0]; //체크를 위한 임시 구조체 할당, 첫번째 사람으로 설정

	while (printed_num != n) { //다 출력할때까지 반복


		while (count != k) { //나갈 차례가 될 때까지 반복
			if (temp->is_out == 0)//나가지 않은 사람들은 
				count++; //count. 나간 사람의 자리도 count하지 않기 위함
			temp = temp->next; //다음 자리로
		}

		//나갈 차례가 된 경우
		if (count == k && temp->is_out != 1) { //차례가 되었고 해당 자리가 나간 사람의 자리가 아닌 경우
			if (printed_num == 0) {//첫 출력일 경우, 
				printf("<%d", temp->id); //'<'를 붙여줌
			}
			else {//기본 출력 양식
				printf(", %d", temp->id);
			}
			printed_num++; //출력된 횟수 업데이트
			
			count = 1; //count 초기화
			temp->is_out = 1; //나간 자리로 표시
		}
		//차례가 되었지만 해당 자리가 나간 사람의 자리인 경우, pass

		temp = temp->next; //다음 자리로 
	}
	printf(">"); //출력이 끝난 경우, '>'을 붙여줌

	free(p);

	return 0;
}

 

 

이 문제를 푸는 정석 코드는 다음과 같다.

 

//#11866 요세푸스 문제 0
#include <stdio.h>
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;
int n,k;

int main()
{
	scanf("%d %d", &n, &k);
	queue<int> q;
	for(int i=1; i<=n; i++)
		q.push(i);
		
	int t = 1;
	cout << "<";
	while(q.size()>1) 
	{
		if(t%k==0)
		{
			cout << q.front() << ", ";
			q.pop();
		}
		else
		{
			q.push(q.front());
			q.pop();
		}
		t++;
	}
	cout << q.front()<<">";
}

//출처: 백준, id : myjun0321
728x90

'자료구조론 > 백준' 카테고리의 다른 글

[백준] 4949 균형잡힌 세상, (스택과 재귀함수에 대하여)  (1) 2024.02.27
[백준] 10866 덱  (0) 2024.02.25
[백준] 2164 카드2  (1) 2024.02.24
[백준] 1966 프린터 큐  (1) 2024.02.24
[백준] 1874 스택 수열  (2) 2024.02.18
728x90

좌표 정렬하기 

 
시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초 256 MB 136597 65405 50827 48.023%

문제

2차원 평면 위의 점 N개가 주어진다. 좌표를 x좌표가 증가하는 순으로, x좌표가 같으면 y좌표가 증가하는 순서로 정렬한 다음 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 점의 개수 N (1 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 N개의 줄에는 i번점의 위치 xi와 yi가 주어진다. (-100,000 ≤ xi, yi ≤ 100,000) 좌표는 항상 정수이고, 위치가 같은 두 점은 없다.

출력

첫째 줄부터 N개의 줄에 점을 정렬한 결과를 출력한다.

예제 입력 1 복사

5
3 4
1 1
1 -1
2 2
3 3

예제 출력 1 복사

1 -1
1 1
2 2
3 3
3 4

 

#include <iostream>
#include <stdlib.h>
#include <algorithm>
using namespace std;

typedef struct Coordinate {
	int x;
	int y;
}UserCoordinate;

bool compare_coordinate(const Coordinate& a, const Coordinate& b) {
	if (a.x != b.x)
		return a.x < b.x;
	return a.y < b.y;
}

int main() {
	int size = 0;
	cin >> size;

	UserCoordinate* p = (UserCoordinate*)malloc(sizeof(UserCoordinate) * size);

	for (int i = 0; i < size; i++) {
		cin >> p[i].x;
		cin >> p[i].y;
	}

	sort(p, p + size, compare_coordinate);

	for (int i = 0; i < size; i++) {
		cout << p[i].x << " ";
		cout << p[i].y << "\n";
	}

	free(p);

	return 0;
}

 

c언어와 달리 c++의 sort(algorithm 헤더에 정의)함수는 포인터 접근이 아닌 값에 의한 접근을 하므로 

compare함수의 인자는 포인터(*)가 아닌 값(&)으로 정의해야 한다.

 

부등호의 방향은 오름차순 기준으로 정렬이 필요없는 경우 1을 반환하도록 작성해야 한다.

(c의 qsort의 경우 정렬이 필요없는 경우 음수를 반환하도록)

728x90

'C, C++ > 백준' 카테고리의 다른 글

[백준] 15829 Hashing  (3) 2024.02.28
[백준] 11651 좌표 정렬하기 2  (1) 2024.02.28
[백준] 10816 숫자 카드 2  (1) 2024.02.25
[백준] 2231 분해합  (0) 2024.02.22
[백준] 1546 평균  (1) 2024.02.15
728x90

 

 
시간 제한메모리 제한제출정답맞힌 사람정답 비율
0.5 초 (추가 시간 없음) 256 MB 82123 45389 38327 56.025%

문제

정수를 저장하는 덱(Deque)를 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.

명령은 총 여덟 가지이다.

  • push_front X: 정수 X를 덱의 앞에 넣는다.
  • push_back X: 정수 X를 덱의 뒤에 넣는다.
  • pop_front: 덱의 가장 앞에 있는 수를 빼고, 그 수를 출력한다. 만약, 덱에 들어있는 정수가 없는 경우에는 -1을 출력한다.
  • pop_back: 덱의 가장 뒤에 있는 수를 빼고, 그 수를 출력한다. 만약, 덱에 들어있는 정수가 없는 경우에는 -1을 출력한다.
  • size: 덱에 들어있는 정수의 개수를 출력한다.
  • empty: 덱이 비어있으면 1을, 아니면 0을 출력한다.
  • front: 덱의 가장 앞에 있는 정수를 출력한다. 만약 덱에 들어있는 정수가 없는 경우에는 -1을 출력한다.
  • back: 덱의 가장 뒤에 있는 정수를 출력한다. 만약 덱에 들어있는 정수가 없는 경우에는 -1을 출력한다.

입력

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지 않은 명령이 주어지는 경우는 없다.

출력

출력해야하는 명령이 주어질 때마다, 한 줄에 하나씩 출력한다.

예제 입력 1 복사

15
push_back 1
push_front 2
front
back
size
empty
pop_front
pop_back
pop_front
size
empty
pop_back
push_front 3
empty
front

예제 출력 1 복사

2
1
2
0
2
1
-1
0
1
-1
0
3

예제 입력 2 복사

22
front
back
pop_front
pop_back
push_front 1
front
pop_back
push_back 2
back
pop_front
push_front 10
push_front 333
front
back
pop_back
pop_back
push_back 20
push_back 1234
front
back
pop_back
pop_back

예제 출력 2 복사

-1
-1
-1
-1
1
1
2
2
333
10
10
333
20
1234
1234
20

 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int deque[200001];
int front_index = 100000;
int back_index = 100001;

int size() {
	return (back_index - front_index) - 1;
}
char empty() {
	if (size() == 0)
		return 1;
	else
		return 0;
}

void push_front(int num){
	deque[front_index--] = num;
}

void push_back(int num){
	deque[back_index++] = num;
}

int pop_front() {
	if (!empty()) {
		front_index++;
		return deque[front_index];
	}
	return -1;
}
int pop_back() {
	if (!empty()) {
		back_index--;
		return deque[back_index];
	}
	return -1;
}

int front() {
	if(!empty())
		return deque[front_index + 1];
	return -1;
}
int back() {
	if(!empty())
		return deque[back_index - 1];
	return -1;
}

int main() {
	int num = 0;
	char line[100] = { 0, };
	char cmd[11] = { 0, };
	int arg = 0;

	scanf("%d", &num);
	fgets(line, sizeof(line), stdin);

	for (int i = 0; i < num; i++) {
		memset(line, 0, sizeof(line));
		memset(cmd, 0, sizeof(cmd));
		arg = 0;

		fgets(line, sizeof(line), stdin);
		sscanf(line, "%s %d", cmd, &arg);

		if (!strncmp("push_front", cmd, 10)) {
			push_front(arg);
		}
		else if (!strncmp("push_back", cmd, 9)) {
			push_back(arg);
		}
		else if (!strncmp("pop_front", cmd, 9)) {
			printf("%d\n", pop_front());
		}
		else if (!strncmp("pop_back", cmd, 8)) {
			printf("%d\n", pop_back());
		}
		else if (!strncmp("size", cmd, 4)) {
			printf("%d\n", size());
		}
		else if (!strncmp("empty", cmd, 5)) {
			printf("%d\n", empty());
		}
		else if (!strncmp("front", cmd, 5)) {
			printf("%d\n", front());
		}
		else if (!strncmp("back", cmd, 4)) {
			printf("%d\n", back());
		}
	}
}

 

전역변수로 아주 거대한 배열을 덱으로 활용하려 할당하였다.

덱은, 스택과 큐를 섞어놓은 자료구조로 front, back 모두 입출력이 가능하다.

특징으로 pop 연산은, 인덱스만 조정후 덱을 초기화하진 않는다.

따라서, 큰 배열 전체를 검색하여 사이즈를 구하는것에 비해 인덱스를 이용하여 사이즈를 계산하므로 더 빠른 동작을 할 수 있다.

 

하지만, 해당 코드에 인덱스값에 이상이 생기는 순간 보안취약점이 생기므로 인덱스 확인 로직 추가, 좀 더 효율적인 공간 할당방법을 택하면 좋은 코드가 되지 않을까?

 

또한 새로 배운점으로, 

stdin에 엔터를 기준으로 스트링을 받아놓은 후, 띄어쓰기를 기준으로 sscanf를 이용해 다시 스트링의 위치를 할당할 수 있다. (c언어의 입출력은 항상 까다로운것 같다)

728x90
728x90

숫자 카드 2 

 
시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초 256 MB 138996 53768 38424 37.414%

문제

숫자 카드는 정수 하나가 적혀져 있는 카드이다. 상근이는 숫자 카드 N개를 가지고 있다. 정수 M개가 주어졌을 때, 이 수가 적혀있는 숫자 카드를 상근이가 몇 개 가지고 있는지 구하는 프로그램을 작성하시오.

입력

첫째 줄에 상근이가 가지고 있는 숫자 카드의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에는 숫자 카드에 적혀있는 정수가 주어진다. 숫자 카드에 적혀있는 수는 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다.

셋째 줄에는 M(1 ≤ M ≤ 500,000)이 주어진다. 넷째 줄에는 상근이가 몇 개 가지고 있는 숫자 카드인지 구해야 할 M개의 정수가 주어지며, 이 수는 공백으로 구분되어져 있다. 이 수도 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다.

출력

첫째 줄에 입력으로 주어진 M개의 수에 대해서, 각 수가 적힌 숫자 카드를 상근이가 몇 개 가지고 있는지를 공백으로 구분해 출력한다.

예제 입력 1 복사

10
6 3 2 10 10 10 -10 -10 7 3
8
10 9 -5 2 3 4 5 -10

예제 출력 1 복사

3 0 0 1 2 0 0 2

 

 

c++ algorithm 라이브러리에는 binary_search 함수가 존재하지만, 이 함수는 bool타입을 반환하며, 존재 유무만 알려준다.

따라서, upper_bound, lower_bound 함수를 이용하여

찾는 값보다 최초로 큰 값을 가지는 멤버의 포인터(upper_bound) - 최초로 찾는 값을 가지는 멤버의 포인터(lower_bound)를 하면 c++에서 멤버의 크기를 고려해 나눠줘 우리가 찾는 값의 개수를 개산할 수 있다.

 

물론, 위 로직을 수행하기 위해선 오름차순 혹은 내림차순 정렬이 되어있어야 한다.

 

#include <iostream>
#include <stdlib.h>
#include <algorithm>
using namespace std;


int main() {
	int size_of_data_table = 0;
	cin >> size_of_data_table;
	int* data_table = (int*)malloc(sizeof(int) * size_of_data_table);
	for (int i = 0; i < size_of_data_table; i++) {
		cin >> data_table[i];
	}
	sort(data_table, data_table + size_of_data_table);

	int size_of_search_table = 0;
	cin >> size_of_search_table;
	int* search_table = (int*)malloc(sizeof(int) * size_of_search_table);
	for (int i = 0; i < size_of_search_table; i++) {
		cin >> search_table[i];
	}
	
	for (int i = 0; i < size_of_search_table; i++) {
		cout << upper_bound(data_table, data_table + size_of_data_table, search_table[i]) - lower_bound(data_table, data_table + size_of_data_table, search_table[i]) << " ";
	}


	free(data_table);
	free(search_table);
	
	return 0;
}
728x90

'C, C++ > 백준' 카테고리의 다른 글

[백준] 11651 좌표 정렬하기 2  (1) 2024.02.28
[백준] 11650 좌표 정렬하기  (2) 2024.02.25
[백준] 2231 분해합  (0) 2024.02.22
[백준] 1546 평균  (1) 2024.02.15
[백준] 1436 영화감독 숌  (1) 2024.02.10
728x90

나이순 정렬 

시간 제한메모리 제한제출정답맞힌 사람정답 비율
3 초 256 MB 138713 62404 47788 43.578%

문제

온라인 저지에 가입한 사람들의 나이와 이름이 가입한 순서대로 주어진다. 이때, 회원들을 나이가 증가하는 순으로, 나이가 같으면 먼저 가입한 사람이 앞에 오는 순서로 정렬하는 프로그램을 작성하시오.

입력

첫째 줄에 온라인 저지 회원의 수 N이 주어진다. (1 ≤ N ≤ 100,000)

둘째 줄부터 N개의 줄에는 각 회원의 나이와 이름이 공백으로 구분되어 주어진다. 나이는 1보다 크거나 같으며, 200보다 작거나 같은 정수이고, 이름은 알파벳 대소문자로 이루어져 있고, 길이가 100보다 작거나 같은 문자열이다. 입력은 가입한 순서로 주어진다.

출력

첫째 줄부터 총 N개의 줄에 걸쳐 온라인 저지 회원을 나이 순, 나이가 같으면 가입한 순으로 한 줄에 한 명씩 나이와 이름을 공백으로 구분해 출력한다.

예제 입력 1 복사

3
21 Junkyu
21 Dohyun
20 Sunyoung

예제 출력 1 복사

20 Sunyoung
21 Junkyu
21 Dohyun

 

 

구조체를 이용하여 데이터를 저장해야하는데, 멤버로는 가입 순서, 나이, 이름 이 필요하다.

STL을 이용하여 정렬을 수행하면 된다.

 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

typedef struct Info{
	int order_of_registration;
	int age;
	char name[101];
} UserInfo;

int compare_UserInfo_age_and_order(const void* a, const void* b) {
	UserInfo* userA = (UserInfo*)a;
	UserInfo* userB = (UserInfo*)b;
	if(userA->age != userB->age)
		return userA->age - userB->age;
	return userA->order_of_registration - userB->order_of_registration;
}


int main() {
	int size = 0;
	scanf("%d", &size);
	
	UserInfo* info_array = (UserInfo*)malloc(sizeof(UserInfo) * size);
	
	for (int i = 0; i < size; i++) {
		info_array[i].order_of_registration = i;
		scanf("%d %s", &(info_array[i].age), info_array[i].name);
	}

	qsort(info_array, size, sizeof(UserInfo), compare_UserInfo_age_and_order);

	for (int i = 0; i < size; i++) {
		printf("%d %s\n", info_array[i].age, info_array[i].name);
	}

	free(info_array);

	return 0;
}
728x90

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 2775 부녀회장이 될테야 (다이나믹 프로그래밍)  (0) 2024.02.26
[백준] 2292 벌집  (0) 2024.02.26
[백준] 9012 괄호  (0) 2024.02.25
[백준] 2798 블랙잭  (1) 2024.02.25
[백준] 1929 소수 구하기  (0) 2024.02.22

+ Recent posts