문제
깊이우선탐색(DFS)/ 너비우선탐색(BFS)
DFS
- 루트 노드(혹은 다른 임의의 노드)에서 시작해서 다음 분기(branch)로 넘어가기 전에 해당 분기를 완벽하게 탐색하는 방법
- 어떤 노드를 방문했었는지 반드시 검사해야함
- 그래프(정점의 수 : N, 간선의 수: E)의 모든 간선을 조회함
* 인접 리스트로 표현된 그래프 : O(N+E)
* 인접 행렬로 표현된 그래프 : O(N^2)
BFS
- 루트 노드(혹은 다른 임의의 노드)에서 시작해서 인접한 노드를 먼저 탐색하는 방법
- 어떤 노드를 방문했었는지 반드시 검사해야함
- 방문한 노드들을 차례로 저장한 후 꺼낼 수 있는 자료 구조인 큐(Queue)를 사용함, 선입선출
- DFS와 동일한 시간복잡도이나 평균적으로 DFS보다 조금 빠르다고 함
출처: yunyoung1819.tistory.com/86
풀이
꽤 오래 고민해도 잘 생각이 안 나 예전에 C++로 풀어뒀던 풀이를 봤다. 어째 갈수록 더 못 하는 것 같다.
#include <string>
#include <vector>
#include <iostream>
using namespace std;
int number;
int targetNumber;
vector<int> staticNumbers;
int count = 0;
void dfs(int index, int sum) {
if(index == staticNumbers.size()){
if(sum == targetNumber){
count++;
}
return;
}
dfs(index + 1, sum - staticNumbers[index]);
dfs(index + 1, sum + staticNumbers[index]);
}
int solution(vector<int> numbers, int target) {
targetNumber = target;
staticNumbers = numbers;
dfs(0, 0);
return count;
}
그래프처럼 풀려고 했어서 잘 생각이 안 났던 듯 하다. index와 sum을 인자로 넘겨 다음 숫자를 각각 더하고 빼서 재귀함수 형태로 풀었다.
다른 사람의 코드
#include <string>
#include <vector>
using namespace std;
int solution(vector<int> numbers, int target) {
int answer = 0;
int size = 1 << numbers.size();
for(int i = 1 ; i < size ; i++){
int temp = 0;
for(int j = 0 ; j < numbers.size() ; j++)
{
if(i &(1 << j)){
temp -= numbers[j];
}
else temp += numbers[j];
}
if(temp == target) answer++;
}
return answer;
}
비트 연산으로 푼 다른 분의 코드를 보았다.
<< 는 shift 연산으로 왼쪽에 오는 숫자를 오른쪽에 오는 수만큼 비트를 옮긴다.
즉 1 << numbers.size()은 비트로 보면 왼쪽의 숫자인 0000 0001을 0010 0000으로 5칸 옮긴 것으로 size에는 32가 저장되었다.
다음 두 번째 포문 안의 조건문 i &(1 << j)를 보자.
&는 비트 AND연산자이다. i가 1, j가 0일 때
0000 0001 & 0000 0001 은 0000 0001이므로 1이 되어 if문에 들어가게 된다.
같은 방법으로 연산하면 두번의 포문을 돌면서 모든 경우의 수를 확인하게 된다.
이해하기 쉽게 출력해보았다.
#include <string>
#include <vector>
#include <iostream>
using namespace std;
int solution(vector<int> numbers, int target) {
int answer = 0;
int size = 1 << numbers.size();
cout << size << endl;
for(int i = 1 ; i < size ; i++){
int temp = 0;
cout << "--------------" <<endl;
for(int j = 0 ; j < numbers.size() ; j++)
{
cout << int(i &(1 << j)) << endl;
if(i &(1 << j)){
temp -= numbers[j];
}
else temp += numbers[j];
}
if(temp == target) answer++;
}
return answer;
}
int main(){
vector<int> numbers;
numbers.push_back(1);
numbers.push_back(1);
numbers.push_back(1);
numbers.push_back(1);
numbers.push_back(1);
solution(numbers, 3);
return 0;
}
엄청 오래 걸려서 이해했는데 내거보다 느려서 좀 허탈했다. 그치만 신박한 풀이였다...
def solution(numbers, target):
global new_numbers
new_numbers = numbers
global total
total = 0
global new_target
new_target = target
dfs(0, 0)
return total
def dfs(index, sum):
global total
if index == len(new_numbers):
if sum == new_target:
total += 1
return
dfs(index + 1, sum + new_numbers[index])
dfs(index + 1, sum - new_numbers[index])
return
파이썬으로도 다시 풀었다.
'알고리즘 스터디' 카테고리의 다른 글
[프로그래머스] 탐욕법 2. 조이스틱 (0) | 2021.02.24 |
---|---|
[프로그래머스] 이분탐색 1. 입국심사 (0) | 2021.02.21 |
[프로그래머스] 힙 1. 더 맵게 (0) | 2021.02.10 |
[프로그래머스] 스택/큐 2. 주식가격 (0) | 2021.02.06 |
[프로그래머스] 해시 2. 전화번호 목록 (0) | 2021.02.03 |