데굴데굴이
데굴이의 개발일지
데굴데굴이
전체 방문자
오늘
어제
  • 분류 전체보기
    • 프로그래밍
      • C,C++
      • C#
      • 백준(BOJ)
      • 알고리즘
      • HTML
      • WinAPI
      • ETC
    • 유니티
      • 쉐이더
    • 컴퓨터 구조
    • 일본어

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 25644
  • 평가 순서
  • 정적 라이브러리 만들기
  • 10811
  • 알고리즘
  • 전처리
  • Sequence Point
  • C언어
  • c++
  • 1032번#
  • 동적 라이브러리
  • 25644번
  • C
  • 정적 라이브러리
  • 동적 라이브러리 만들기
  • 바구니 뒤집기
  • 라이브러리 적용
  • 동적 라이브러리 적용
  • BOJ
  • 백준
  • 컴파일
  • msvc++
  • 1158번
  • 재귀함수가 뭔가요?
  • multable
  • 10811번
  • 라이브러리
  • 1343번
  • 시퀀스 포인트
  • 최대 상승

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
데굴데굴이

데굴이의 개발일지

프로그래밍/백준(BOJ)

[백준(BOJ) / C][Silver Ⅳ] 1158번 : 요세푸스 문제

2024. 1. 2. 21:30
반응형

문제

https://www.acmicpc.net/problem/1158

 

1158번: 요세푸스 문제

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

www.acmicpc.net


풀이

이 문제는 원형 링크드 리스트를 사용하여 문제를 해결하였습니다.

리스트에 1,2,3,4 ... N 의 숫자를 넣은 후 K 만큼 옆으로 이동하여 그 숫자를 출력하고 리스트에서 제외한다.

이 행동을 리스트에 숫자가 다 없어질때까지 반복한다.

 

배열을 사용하여 해당 값을 넣은 뒤 for문으로 풀게되면 원형 링크드 리스트를 사용하는 것보다 시간이 3배 넘게 오래 걸리기때문에 효율적이지 못하다.

 

그러기에 큐(Queue)를 이용하거나 원형 링크드 리스트를 사용하는 것이 효율이 좋다.


소스코드

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

typedef struct tag_Node
{
	int data;
	
	struct tag_Node* prevNode;
	struct tag_Node* nextNode;
}Node;

Node* CreateNode(int NewData);
void AppendNode(Node** Head, Node* NewNode);
void RemoveNode(Node** Head, Node* Remove);
Node* Shift(Node* Current, int Location);
void DestroyNode(Node* Node);
int GetNodeCount(Node* Head);

int main(void)
{
	int n,k,count;
	Node* List = NULL;
	Node* NewNode = NULL;
	Node* Current = NULL;
	
	scanf("%d %d", &n, &k);
	
	// 리스트에 N개의 숫자를 오름차순으로 입력
	for(int i = 0; i < n; i++)
	{
		NewNode = CreateNode(i+1);
		AppendNode(&List, NewNode);
	}
	
	// 만약 숫자가 1이라면 출력할 숫자도 1뿐이기에 1만 출력 후 종료 
	if(n == 1)
	{
		printf("<1>");
		return 0;
	}
	
	// 첫 번째 출력 후 노드 삭제
	Current = Shift(List, k-1);

	RemoveNode(&List,Current);
	printf("<%d, ", Current->data);
	
	// 첫번째, 마지막 노드를 따로 출력하니 두개를 빼고 나머지를 계산
	for(int j = 0; j < n-2; j++)
	{
		Current = Shift(Current, k);
		printf("%d, ", Current->data);
		RemoveNode(&List, Current);
	}
	
	// 마지막 출력 후 노드 삭제
	Current = Shift(List, k);
	RemoveNode(&List,Current);
	printf("%d>", Current->data);
	
	count = GetNodeCount(List);
	
	for(int i = 0; i < count; i++)
	{
		Current = Shift(List, 0);
		
		if(Current != NULL)
		{
			RemoveNode(&List, Current);
			DestroyNode(Current);
		}
	}
	
	return 0;
}

// 노드 생성
Node* CreateNode(int NewData)
{
	Node* NewNode = (Node*)malloc(sizeof(Node));
	
	NewNode->data = NewData;
	NewNode->nextNode = NULL;
	NewNode->prevNode = NULL;
	
	return NewNode;
}

// 현재 가르키고있는 노드를 K 만큼 이동.
Node* Shift(Node* Current, int Location)
{
	Node* CurrentNode = Current;
	while(CurrentNode != NULL && (--Location) >= 0)
	{
		CurrentNode = CurrentNode->nextNode;
	}
	
	return CurrentNode;
}

// 리스트에 노드를 추가
void AppendNode(Node** Head, Node* NewNode)
{
	if(*Head == NULL)
	{
		*Head = NewNode;
		(*Head)->nextNode = *Head;
		(*Head)->prevNode = *Head;
	}
	else
	{
		Node* TailNode = (*Head)->prevNode;
		
		TailNode->nextNode->prevNode = NewNode;
		TailNode->nextNode = NewNode;
		
		NewNode->nextNode = (*Head);
		NewNode->prevNode = TailNode;
	}
}
// 동적할당된 노드 메모리 해제
void DestroyNode(Node* Node)
{
	free(Node);
}

// 출력한 노드는 리스트에서 삭제
void RemoveNode(Node** Head, Node* Remove)
{
	
	if((*Head) == Remove)
	{
		(*Head)->prevNode->nextNode = (*Head)->nextNode;
		(*Head)->nextNode->prevNode = (*Head)->prevNode;
		
		(*Head) = Remove->nextNode;	
	}
	else
	{
		Remove->prevNode->nextNode = Remove->nextNode;
		Remove->nextNode->prevNode = Remove->prevNode;
	}
}

// 리스트의 총 노드 개수를 구함
int GetNodeCount(Node* Head)
{
	unsigned int Count = 0;
	Node* Current = Head;
	
	while(Current != NULL)
	{
		Current = Current->nextNode;
		Count++;
			
		if(Current == Head)
		{
			break;
		}
	}
	
	return Count;
}

 

 

 

 

 

반응형

'프로그래밍 > 백준(BOJ)' 카테고리의 다른 글

[백준(BOJ) / C][Silver Ⅳ] 9012번 : 괄호  (1) 2024.01.03
[백준(BOJ) / C][Silver Ⅴ] 25644번 : 최대 상승  (0) 2024.01.03
[백준(BOJ) / C][Bronze Ⅱ] 1152번 : 단어의 개수  (1) 2024.01.03
[백준(BOJ) / C][Silver Ⅴ] 7568번 : 덩치  (1) 2024.01.01
[백준(BOJ) / C][Bronze I] 1032번 : 명령 프롬포트  (1) 2023.12.31
    '프로그래밍/백준(BOJ)' 카테고리의 다른 글
    • [백준(BOJ) / C][Silver Ⅴ] 25644번 : 최대 상승
    • [백준(BOJ) / C][Bronze Ⅱ] 1152번 : 단어의 개수
    • [백준(BOJ) / C][Silver Ⅴ] 7568번 : 덩치
    • [백준(BOJ) / C][Bronze I] 1032번 : 명령 프롬포트
    데굴데굴이
    데굴데굴이

    티스토리툴바