728x90
반응형
1. 오늘의 학습 키워드
해시맵/재귀/동적계획(다이나믹 프로그래밍)
2. 오늘의 학습 문제
문제
https://leetcode.com/problems/all-possible-full-binary-trees/
코드
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
import java.util.*;
class Solution {
static List<TreeNode> AnswerTree;
static Map<Integer, List<TreeNode>> memo; // 메모이제이션을 위한 맵
public List<TreeNode> allPossibleFBT(int n) {
memo= new HashMap<>(); //해시맵 선언
return generateFBT(n);
}
public List<TreeNode> generateFBT(int n){ //재귀적으로
if (memo.containsKey(n)) { //저장되어있는 값을 리턴.
return memo.get(n);
}
List<TreeNode> result = new ArrayList<>();
if (n == 1) { //1인 경우
result.add(new TreeNode(0));
}
else {
//왼쪽 노드의 개수-오른쪽 노드의 개수는 [1,1] [3,1] [1,3]...홀수
for (int leftNodes = 1; leftNodes < n; leftNodes += 2) {
int rightNodes = n - 1 - leftNodes;
List<TreeNode> left_subTrees = generateFBT(leftNodes);
List<TreeNode> right_subTrees = generateFBT(rightNodes);
for (TreeNode left : left_subTrees) { //만약 left_subTrees=[0] , right_subTrees=[0,0,0]이면 [ 0 ,0, 0, null,null,0,0] 생성. for문이지만 실제로는 각각 한 번씩만 실행.
for (TreeNode right : right_subTrees) {
TreeNode root = new TreeNode(0);
root.left = left;
root.right = right;
result.add(root);
}
}
}
}
memo.put(n, result); //해시맵에 넣기 메모이제이션.
return result; //result반환
}
}
작게 나누어서 푸는 방법을 떠올리고, 결과를 재귀적으로 구현할 수 있다는 사실까지는 생각했지만, ArrayList를 사용하는 알고리즘을 구상하는 과정에서, 데이터에 접근할때 원본이 건드려져서, 깊은 복사를 하여 원본을 유지하려했으나, 메모리가 꼬여서인지 실패했다. 그래서 풀이를 보고 작성한 코드다.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
import java.util.*;
class Solution {
static List<TreeNode> AnswerTree;
public List<TreeNode> allPossibleFBT(int n) {
AnswerTree = new ArrayList <> ();
TreeNode first= new TreeNode(0);
List<TreeNode> TempTree = new ArrayList <> ();
TempTree.add(first); //임시 트리
for(int i=3;i<=n; i+=2){
AnswerTree= recurFBT(i, TempTree); //f(i)일때 answer를 리턴
TempTree=AnswerTree;//TempTree업데이트
}
return AnswerTree;
}
static List<TreeNode> now =new ArrayList <> (); // 복사
static TreeNode motherNode; //원본트리노드.
public List<TreeNode> recurFBT( int i, List<TreeNode> TempTree){
now =new ArrayList <> (); //
for(TreeNode tree : TempTree){ //f(n)리턴...
motherNode= deepCopy(tree); //깊은 복사하여 사용
TreeNode gg=deepCopy(tree);
makeFBT(gg, gg);
//System.out.println(gg+ " " + gg + " " + tree);
}
return now; //AnswerTree를 갱신한다.
}
public void makeFBT (TreeNode node, TreeNode root){ //motherNode는 원본보호
//node는 현재 변화시킬거고, gg는 node의 루트
//System.out.println(node+ " " + gg + " " + motherNode );
if(node.left==null && node.right ==null){ //자식이 없으면
node.left=new TreeNode(0);
node.right=new TreeNode(0);
now.add(deepCopy(root));//깊은 복사하여 추가..
root=motherNode; //gg에 원본 넣어줌.
}
else{ //자식있으면
makeFBT(node.left, root);
root=motherNode;
makeFBT(node.right, root);
}
}
public static TreeNode deepCopy(TreeNode original) { //깊은 복사
if (original == null) {
return null;
}
TreeNode newNode = new TreeNode(original.val);
newNode.left = deepCopy(original.left);
newNode.right = deepCopy(original.right);
return newNode;
}
}
삽질한 코드..
3. 오늘의 회고
- 성공하면 좋았을텐데 아쉽다
- 해시맵을 떠올리자, 메모이제이션
https://www.youtube.com/watch?v=yu9pQYbCMB0
도움을 준 영상
728x90
반응형