- 
                            
                            [LeetCode] 653. Two Sum IV - Input is a BST알고리즘 문제 풀이 2021. 8. 24. 11:21
문제 출처: https://leetcode.com/problems/two-sum-iv-input-is-a-bst/
Two Sum IV - Input is a BST - LeetCode
Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.
leetcode.com
문제
이진 탐색 트리의 root 와 목표 숫자 k 가 주어지면, BST 내에 두 노드의 값의 합이 k인 노드가 존재한다면 true 를 반환하라.
예제

Input: root = [5,3,6,2,4,null,7], k = 9 Output: true
Input: root = [5,3,6,2,4,null,7], k = 28 Output: false
풀이
이진 탐색 트리의 특성을 아는지, 그 특성을 이용해서 문제를 풀 수 있는지에 대한 문제
문제 풀이에 사용될 수 있는 이진 탐색 트리의 특성은 다음과 같다:
- (균형 잡힌) 트리라면, 값 탐색 시 매 단계마다 탐색 범위가 절반으로 줄어든다.
 - 이진 탐색 트리를 중위 순회하면 정렬된 배열 값을 얻을 수 있다.
 
이진 탐색 트리의 탐색을 이용한 문제 접근
트리에서 임의의 노드를 node[i] 라고 할 때, 트리에서 k - node[i].val 값이 존재하는지 찾는 문제로 접근할 수 있다. 이진트리에서 어떤 값이 존재하는지 탐색하는 것은 다음과 같다.
var findNode = function(root, target) { if (root == null) { return false; } if (root.val == target) { return true; } if (target > root.val) { return root.right ? findNode(root.right, target) : false; } else { return root.left ? findNode(root.left, target) : false; } }이제 트리의 모든 노드를 돌면서 k - node[i].val 의 값을 갖는 노드가 트리에 있는지 찾아보는 코드를 작성해보자. 여기서는 BFS 방식을 이용해서 전체 트리를 탐색하도록 하였다.
var findTraget = function(root, k) { const q = [root]; while (q.length) { const node = q.shift(); if (findNode(root, k - node.val)) { return true; } node.right ? q.push(node.right) : ''; node.left ? q.push(node.left) : ''; } return false; }이 코드들을 제출하기 전에, 한 가지 추가로 고려해야 하는 점이 있다. 아래 그림을 살펴보자.

그림은 k = 8, root = [3, 2, 4, null, null, null, 7] 로 주어졌을 때이다. 노드 4에서 findNode() 의 target은 4 가 된다. 트리 내부를 탐색하면서 노드 값이 4 인 노드를 찾게 되는데 이때 찾아지는 노드는 바로 자기 자신이 된다. 트리 내의 두 개의 노드 합계가 k 가 되어야 하는 것이므로 이 경우는 걸러져야 한다. 그래서 다음과 같이 원래 노드와 비교하는 코드를 추가하는 방식으로 이 문제를 해결하였다.
var findNode = function(root, target, origin) { if (root == null) { return false; } if (origin != root && root.val == target) { return true; } if (target > root.val) { return root.right ? findNode(root.right, target, origin) : false; } else { return root.left ? findNode(root.left, target, origin) : false; } } var findTraget = function(root, k) { const q = [root]; while (q.length) { const node = q.shift(); if (findNode(root, k - node.val, node)) { return true; } node.right ? q.push(node.right) : ''; node.left ? q.push(node.left) : ''; } return false; }중위 순회를 이용한 문제 접근(정렬 + 투포인터)
이진 탐색 트리를 중위 순회하게 되면, 그 특성상 노드 값이 오름차순으로 정렬된 배열을 얻을 수 있다.
var inorder = function(root, arr) { root.left ? inorder(root.left, arr) : ''; arr.push(root.val); root.right ? inorder(root.right, arr) : ''; }정렬된 배열에서 두 개의 값의 합이 k 인 두 노드를 찾기 위해서 투 포인터 기법을 사용할 수 있다. 이 방법은 이름에서 보이는 것처럼 두 개의 포인터를 이용한 방법으로 다음과 같은 과정으로 진행된다.
- 두 개의 포인터(left, right)를 선언하고 각각 배열의 시작과 끝을 가리키도록 한다.
 - 두 포인터가 가리키는 원소를 합하고, k 와 비교를 한다.
 - 비교 결과에 따라 다음 행위 중 하나를 선택한다.
- k 가 더 크다면? right = right - 1
 - k 가 더 작다면? left = left - 1
 - k 와 같다면? true 반환
 
 - left 가 right 보다 같거나 커질 때까지 2~3을 반복한다.
 
var findTarget = function(root, k) { const arr = []; inorder(root, arr); let l = 0, r = arr.length-1; while (l < r) { const sum = arr[l] + arr[r]; if (sum == k) { return true; } if (sum > k) { r -= 1; } else { l += 1; } } return false; };Github: 653.js
GitHub - opwe37/Algorithm-Study
Contribute to opwe37/Algorithm-Study development by creating an account on GitHub.
github.com
'알고리즘 문제 풀이' 카테고리의 다른 글
[LeetCode] 633. Sum of Square Numbers (0) 2021.08.26 [LeetCode] 537. Complex Number Multiplication (0) 2021.08.25 [LeetCode] 850. Rectangle Area II (0) 2021.08.23 [LeetCode] 1339. Maximum Product of Splitted Binary Tree (0) 2021.08.20 [LeetCode] 91. Decode Ways (0) 2021.08.19  
