hyelie
hyelie
Hyeil Jeong
       
글쓰기    관리    수식입력
  • 전체보기 (495)
    • PS (283)
      • Algorithm (28)
      • PS Log (244)
      • Contest (6)
      • Tips (5)
    • Development (52)
      • Java (14)
      • Spring (23)
      • SQL (2)
      • Node.js (2)
      • Socket.io (3)
      • Study (4)
      • Utils (4)
    • DevOps (36)
      • Git (5)
      • Docker (4)
      • Kubernetes (2)
      • GCP (3)
      • Environment Set Up (8)
      • Tutorial (12)
      • Figma (2)
    • CS (74)
      • OOP (7)
      • OS (24)
      • DB (2)
      • Network (24)
      • Architecture (0)
      • Security (2)
      • Software Design (0)
      • Parallel Computing (15)
    • Project (15)
      • Project N2T (5)
      • Project ASG (0)
      • Project Meerkat (1)
      • Model Checking (7)
      • Ideas (2)
    • 내가 하고싶은 것! (34)
      • Plan (16)
      • Software Maestro (10)
      • 취준 (8)
hELLO · Designed By 정상우.
hyelie

hyelie

PS/PS Log

23.02.19. 풀었던 문제들

리트코드 daily challenge - 103. Binary Tree Zigzag Level Order Traversal

 Binary Tree를 BFS를 써서 순회하는 문제. 처음 풀었을 때는 7ms(27.9%), 12.2MB(17.21%)가 나왔다. 왜 이렇게 많이 나왔을까.. 생각해 보고, 답안지를 보고 개선점을 생각했다. 개선점은 아래 코드에 주석으로 달아놓았다.

typedef pair<TreeNode*, int> pni; // 개선

class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        int maxDepth = -1;
        vector<vector<int>> answer;

        // BFS init
        queue<pni> q;
        q.push({root, 0});

        while(!q.empty()){
            // pop
            TreeNode* curNode = q.front().first;
            int curDepth = q.front().second;
            q.pop();
            if(curNode == NULL) continue;

            // if depth is deeper, than add
            if(curDepth > maxDepth){
                answer.push_back({});
                maxDepth = curDepth;
            }
            answer[curDepth].push_back(curNode->val);

            q.push({curNode->left, curDepth + 1});  // 개선
            q.push({curNode->right, curDepth + 1}); // 개선
        }

        for(int i = 1; i<answer.size(); i += 2){
            reverse(answer[i].begin(), answer[i].end());
        }
        return answer;
    }
};

 

 생각해 보면, child가 null인데 굳이 queue에 넣을 필요가 없다. 모든 경우에 대해 한 단계 더 탐색하는 것이기 때문에 이것만 줄여도 시간은 50% 감소할 것이라 생각하고, 개선했다. 개선한 코드는 아래와 같다.

 실행시간은 0ms(100%), 12.1MB(78.56%)이다. 필요없는 탐색으로 실행시간을 많이 줄였다. 여기서 메모리는 어떻게 더 개선할 수 있을까? 나는 pni라는 pair를 통해 현재 탐색하고 있는 vertex가 몇 번째 layer의 vertex인지 기록을 했다. 그러나 이렇게 할 필요가 없다! while문 안에 q.size()와, 반복문을 이용하면 이번에 탐색할 layer의 크기를 알아낼 수 있기 때문이다. 

typedef pair<TreeNode*, int> pni;

class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        if(root == NULL) return {}; // 개선한 부분

        int maxDepth = -1; // 개선
        vector<vector<int>> answer; 

        // BFS init
        queue<pni> q;
        q.push({root, 0});

        while(!q.empty()){
            // pop
            TreeNode* curNode = q.front().first;
            int curDepth = q.front().second;
            q.pop();
            if(curNode == NULL) continue;

            // if depth is deeper, than add
            if(curDepth > maxDepth){ // 개선
                answer.push_back({});
                maxDepth = curDepth;
            }
            answer[curDepth].push_back(curNode->val);

            if(curNode->left != NULL) q.push({curNode->left, curDepth + 1});   // 개선한 부분
            if(curNode->right != NULL) q.push({curNode->right, curDepth + 1}); // 개선한 부분
        }

        for(int i = 1; i<answer.size(); i += 2){
            reverse(answer[i].begin(), answer[i].end());
        }
        return answer;
    }
};

 

 메모리 사용량도 개선한 코드는 아래와 같다. 0ms(100%), 11.9MB(93.95%)이다.

 위에서 설명한 것과 같이, while문 내에 q.size()가 [이번에 탐색할 layer의 vertex 개수]임을 알 수 있고, for문을 사용해서 "지금 탐색 중인 vertex가 어떤 layer인지" 알 수 있다. 이걸 안다면? 현재 layer가 짝수인지, 홀수인지 알 수 있기 때문에 zig-zag도 판단해 넣을 수 있다.

class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        if(root == NULL) return {};

        vector<vector<int>> answer;
        bool isLeftToRight = true;

        // BFS init
        queue<TreeNode*> q;
        q.push(root);

        while(!q.empty()){
            int curDepthSize = q.size(); // 개선한 부분
            vector<int> curDepthLayer(curDepthSize);

            for(int i = 0; i<curDepthSize; i++){ // 개선한 부분 - 이 for문으로 현재 layer vertex 개수를 알 수 있다.
                // pop
                TreeNode* curNode = q.front();
                q.pop();
                if(curNode == NULL) continue;

                int idx = isLeftToRight ? i : curDepthSize - i - 1;
                curDepthLayer[idx] = curNode->val;

                if(curNode->left != NULL) q.push(curNode->left);
                if(curNode->right != NULL) q.push(curNode->right);
            }

            isLeftToRight = !isLeftToRight;
            answer.push_back(curDepthLayer);
        }

        return answer;
    }
};

 

 i번째 layer의 개수를 3줄의 코드로 알아낸 것 같은 느낌이다. 상당히 좋은 기법인 듯 싶다.

 

프로그래머스 lv.1 과일 장수

 내림차순 정렬 하고, i번째 것만 구해주면 되는 쉬운 규칙 찾기 문제

 

프로그래머스 lv1 명예의 전당 (1)

 multiset을 이용해 정렬을 유지하고, iterator를 사용해 몇 칸 옮기는 문제. iterator는 advance를 이용한다.

 

프로그래머스 lv1 숫자 짝꿍

 vector로 각 숫자의 개수를 counting하고, string이 "00000"일 때만 예외처리 해 주면 되는 문제.

 

프로그래머스 lv1 문자열 나누기

 항상 귀찮은, C++ string parsing 문제.

#include <string>
#include <vector>

using namespace std;

int solution(string s) {
    vector<string> answer;
    
    for(int i = 0; i<s.length(); i++){
        int si = i, count = 0; // si : 시작 index, count : 동일문자 개수
        char standard = s[si]; // 시작 index에 있는 문자
        while(i < s.length()){ // 범위 내에 있을 때
            if(s[i] == standard) count++;
            else count--;
            if(count == 0) break;
            i++;
        }
        answer.push_back(s.substr(si, i-si+1));
    }
    
    return answer.size();
}
저작자표시 (새창열림)

'PS > PS Log' 카테고리의 다른 글

23.02.21. 풀었던 문제들  (0) 2023.02.21
23.02.20. 풀었던 문제들  (0) 2023.02.20
23.02.18. 풀었던 문제들  (0) 2023.02.18
23.02.17. 풀었던 문제들  (0) 2023.02.17
22.09.08. 풀었던 문제들  (0) 2022.09.08
    hyelie
    hyelie

    티스토리툴바