문제링크 : http://codeup.kr/problem.php?id=3704


해결 방법 :

n 이 5라면은 다음과 같이 총 13가지 경우의 수를 알 수 있다.

5=1+1+1+1+1

5=1+1+1+2

5=1+1+2+1

5=1+2+1+1

5=2+1+1+1

5=1+1+3

5=1+3+1

5=3+1+1

5=1+2+2

5=2+1+2

5=2+2+1

5=2+3

5=3+2

이걸 보고 생각해보면 5를 도달하기 직전 시점에서 보면 한 칸 전에오는 경우의수 가 있을 것이고, 두 칸 전에 오는 경우의 수도 있을거고 그리고 세 칸전에 오는 경우의 수가 있을것이다.


그렇다면 n에 도달하는데 모든 경우의 수는 n-1까지 오는데 경우의수 + n-2 까지 오는데 경우의 수 + n-3 까지 오는데 경우의수로 모든 경우를 다 합해주면은 원하는 답을 구할 수 있다.


이렇게하면 정답은 구할수 있지만, 이렇게 모든 경우를 세주면은 하나의 경우에있어서 계속 3가지의 경우의수가 발생이 되므로 3의 n승이라는 어마어마한 시간이 걸려서 틀리게 된다.


따라서, 중복되는 경우를 세주지 않게하기위해서 memo라는 배열에 n에 도달하는 경우의수를 미리 기록해둔다.

그렇게되면 일단 n이 1씩계속 감소하며 모든경우를 구하게 되고 n-2, n-3으로 부르는 재귀함수는 n-1의 재귀함수에 모두 포함되므로 경우의수가 확 줄어들게 된다. 


이제 코드를 작성해 보면 다음과 같다.




반응형

'PS > 코드업' 카테고리의 다른 글

1925 (재귀함수) nCr  (0) 2019.05.15
3015번 성적표 출력  (1) 2019.04.14
1920번 2진수 변환 (재귀함수)  (0) 2019.03.16
3733번 우박수 길이 - large  (0) 2019.01.27
2606. 소수점 이하 출력  (0) 2018.12.17

요즘 코딩을 잘 안하는 것 같아 자료구조 중 링크드 리스트를 코딩해 보면서 공부 하기로 했다.

그래서 오늘은 간단하게 링크드 리스트 구조를 설계하고 원소를 왼쪽, 오른쪽으로 각각 삽입하는 기능을 구현해보도록 하겠다.

 

구현하기에 앞서 어떤 순서로 시작할지 대략 생각해 보면

 

1. 노드를 일단 만든다.

   노드는 데이터와 next라는 것을 지닌다. 여기서 next 는 다음 노드를 가리키는 포인터변수다.

 

Node

 

2. 링크드 리스트 클래스를 만든다.

    멤버변수 : 링크드 리스트의 시작위치를 알려주는 start, 끝의 위치를 알려주는 end

    함수 :  왼쪽 삽입, 오른쪽 삽입, 리스트 출력

링크드 리스트 구조

 

3. 리스트 왼쪽 부분에 원소 추가 방법

- 추가할 원소 Next 를 다음 원소로 가리키게 하고 현재 링크드리스트의 start새로추가한 원소로 변경해준다.  그럼 왼쪽으로 추가가 된다.

 

4. 리스트 오른쪽 부분에 원소 추가 방법

현재 링크드리스트의 end부분 노드의 next 를 새로 만든 노드로 가리키게 해주면 된다. 그럼 오른쪽으로 원소가 추가가 된다.

 

5.  마지막으로 링크드리스트 원소를 전부 출력 해주는 방법은 C라는 변수를 두고 링크드 리스트의 start 부터 end 까지 순회시키면서 각 요소가 가진 데이터 전부를 출력하도록 한다.

 

 

이 절차대로 구현해주면 소스는 다음과 같다.

 

...더보기

 

#include <iostream>
#include <string>
#include <stdlib.h>
#include <vector>
using namespace std;
struct Node {
	// 각원소  
	const char * data;
	Node * next;
};
class myLinkedList {
public:
	myLinkedList();
	~myLinkedList();
	void addLeft(const char*);
	void addRight(const char*);
	void getList();
private:
	Node * start;
	Node * end;
};
myLinkedList::myLinkedList() :start(NULL), end(NULL) {};
myLinkedList::~myLinkedList() {
}
void myLinkedList::addLeft(const char* data) {
	Node * pTemp = (Node *)malloc(sizeof(Node));
	pTemp->data = data;
	pTemp->next = NULL;
	if (this->start == NULL) {
		this->start = pTemp;
		this->end = pTemp;
	}
	else {
		pTemp->next = this->start;
		this->start = pTemp;
	}
}
void myLinkedList::addRight(const char* data) {
	Node * pTemp = (Node *)malloc(sizeof(Node));

	pTemp->data = data;
	pTemp->next = NULL;
	if (this->start == NULL) {
		this->start = pTemp;
		this->end = pTemp;
	}
	else {
		this->end->next = pTemp;
		this->end = pTemp;
	}
}
void myLinkedList::getList() {
	Node * c;
	Node result[100];
	int index = 1;
	c = this->start;

	while (c != NULL) {
		cout << index << "번째 data : " << c->data << endl;
		index++;
		c = c->next;
	}
}
int main(){
	Node * result = NULL;
	myLinkedList myLinkPipe;
	
	myLinkPipe.addLeft("red");
	myLinkPipe.addLeft("blue");
	myLinkPipe.addLeft("green");
	myLinkPipe.addRight("black");
	myLinkPipe.addRight("purple");
	myLinkPipe.getList();
	
	
	return 0;
}

 

 

반응형

<해결 방법>

이 문제는 정수 n 을 입력받아서 2진수로 출력하는 문제이다.


예를들어 12라는 숫자가 입력되면 


1100 이 출력되면된다.


이 문제를 재귀함수로만 풀어야 하는 조건이 있기때문에 재귀적인 패턴을 먼저 찾아야한다.


우리가 일반적으로 2진수를 변환할때를 생각해보면, 12를 일단 2로 쭊쭉쭉 계속 나눠본후 나머지를 거꾸로 이어서 붙여주면 2진수가 완성된다.


이때, 12를 2로나눠서 생긴 나머지에 2로나눈 몫인 6을 다시 2로 쭉쭉쭉 나눠서 생긴 나머지와 붙여준다면 2진수가 완성된다.

이걸 그림으로 표현해 보면 다음과 같다. (그림 잘 못그림 ㅜ)

이걸보면 재귀적 패턴을 알수있다.  

string getBinaryNum(int n) : n을 입력받아 2진수를 반환하는 함수  라고 정의를 한다면, 


getBinaryNum(n/2) + (n % 2)  <- 이 식의 의미는 현재 n의 2를 나눈 나머지를 n/2로 나눈 숫자의 2진수를 반환하는 것에 갖다 붙인다. 즉, 원래 n에 대한 2진수를 반환할 수 있게된다. 


요약하자면 재귀함수가 n/2에 대한 2진수를 반환해줄거니까 우리는 이거에 현재 n을 2로나눈 나머지만 갖다가 붙이면 되는것이다.



반응형

'PS > 코드업' 카테고리의 다른 글

3015번 성적표 출력  (1) 2019.04.14
3704번 계단 오르기 2  (0) 2019.03.31
3733번 우박수 길이 - large  (0) 2019.01.27
2606. 소수점 이하 출력  (0) 2018.12.17
재귀함수 1부터 n까지 합 구하기  (0) 2018.11.18

+ Recent posts