Skip to content

leetcode_OJ WC92 解題心得

  • Contest time: Jul 8,2018
  • 紀念一下難得打進前10% Screenshot

PA. 868. Transpose Matrix 求轉置矩陣

  • 思路: 直接解即可 注意先以原矩陣比較大的row or col(看誰大) 開一個暫時存放用的,以免segfault,最後丟到res,其中大小剛好跟原本的矩陣是對稱的
  • 分析: Time complexity = O(ROW * COL), Space complexity = O(ROW * COL)
#define FORI(n) for(int i = 0; i < n; ++ i)
class Solution
{
public:
    vector<vector<int>> transpose(vector<vector<int>>& arr)
    {
        vector<vector<int>>trans, res;
        int big = max(arr[0].size(), arr.size());
        trans.resize(big);
        FORI(trans.size())
        {
            trans[i].resize(big);
        }
        cout << 1 <<endl;
        for(int i = 0; i < arr.size(); i++)
        {
            for(int j = 0; j < arr[0].size(); j++)
            {
                trans[j][i] = arr[i][j];
            }
        }
        cout << 1 <<endl;
        res.resize(arr[0].size());
        FORI(res.size())
        {
            res[i].resize(arr.size());
        }
        cout << 1 <<endl;
        for(int i = 0; i < arr[0].size(); i++)
        {
            for(int j = 0; j < arr.size(); j++)
            {
                res[i][j] = trans[i][j];
            }
        }
        return res;
    }
};

PB. 866. Smallest Subtree with all the Deepest Nodes 擁有最深節點的最小子樹(經典題目,可搭配LCA並用)

  • 思路:
    • 用一個struct表示每一個node的父節點以及他的深度(annotated node),接的用一個map儲存該節點與其對應資訊的關係(因為在二元樹,節點數值都是單一的,不必擔心重複蓋過的問題)
    • 使用 dfs_information這個函數來走訪樹,同時儲存節點的父親、深度資訊。
    • 將該map貼到第二個map,查找最深的node,找完後移除他(要貼到第二個map的原因在於,如果用原本的map,移除後找第二深的,最後要LCA會喪失最深節點的資訊,會錯)
    • 如果有一個一樣深的節點(一樣最深)則samllest subtree會是他們的LCA(應該很好想像,因為一樣深的關係,勢必得找他們的LCA),如果最深的節點沒有人跟他一樣深,那就是他自己作為最小subtree
    • 兩個最深的節點就LCA,一個就返回最深的
  • 分析: Time complexity = O(N), Space complexity = O(N) (auxiliary map structure to store the information, where N is # of nodes of the binary tree)
    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution
    {
    public:
        struct node_info
        {
            TreeNode* parent;
            int depth;
        };
        map<TreeNode*, node_info> node_info_map;
        map<TreeNode*, node_info> node_info_map_2;
        TreeNode* deepest_node;
        TreeNode* deepest_2nd_node;
        TreeNode* res;
        TreeNode* subtreeWithAllDeepest(TreeNode* root)
        {
            if(root->left == NULL && root->right == NULL) //if tree size is 1 just return the root
            {
                return root;
            }
            dfs_information(root, 0);
            //find the 1st deepest leaf
            int deepest = 0;
            deepest_node = deepest_2nd_node = NULL;
            node_info_map_2 = node_info_map;
            for(map<TreeNode* , node_info>::iterator it = node_info_map_2.begin(); it != node_info_map_2.end(); it++)
            {
                if(it->first->left == NULL && it->first->right == NULL)
                {
                    //
                    if(it->second.depth > deepest)
                    {
                        deepest = it->second.depth;
                        deepest_node = it->first;
                    }
                }
            }
    
            node_info_map_2.erase(deepest_node);
    
            //find the 2nd deepest leaf if same depth, then update the sceond one for the LCA
            for(map<TreeNode* , node_info>::iterator it = node_info_map_2.begin(); it != node_info_map_2.end(); it++)
            {
                if(it->first->left == NULL && it->first->right == NULL)
                {
                    //
                    if(it->second.depth == deepest)
                    {
                        deepest = it->second.depth;
                        deepest_2nd_node = it->first;
                    }
                }
            }
             //if no other deepest with same depth, do not do LCA, since the deepest_node "ITSELF" is the smallest subtree containing the deepest_node
            if(deepest_2nd_node == NULL)
            {
                return deepest_node;
            }
    
            climbup_LCA(deepest_node, deepest_2nd_node);
            return res;
        }
        void dfs_information(TreeNode* root, int depth)
        {
            if(root == NULL)
            {
                return;
            }
            node_info_map[root].depth = depth;
            if(root->left)
            {
                node_info_map[root->left].parent = root;
                dfs_information(root->left, depth + 1);
            }
            if(root->right)
            {
                node_info_map[root->right].parent = root;
                dfs_information(root->right, depth + 1);
            }
        }
        void climbup_LCA(TreeNode* node_p, TreeNode* node_q)
        {
            if(node_info_map[node_p].parent == node_info_map[node_q].parent)
            {
                res = node_info_map[node_p].parent;
                return;
            }
            else if(node_info_map[node_p].parent == node_q)
            {
                res = node_q;
                return;
            }
            else if(node_info_map[node_q].parent == node_p)
            {
                res = node_p;
                return;
            }
    
            else if(node_info_map[node_p].depth > node_info_map[node_q].depth) //the one who is lower has to climb up one depth
            {
                climbup_LCA(node_info_map[node_p].parent, node_q);
            }
            else
            {
                climbup_LCA(node_p, node_info_map[node_q].parent);
            }
        }
    };
    

  • 在此也額外分享LCA的解法 經典tree題目,一定要會!!!!! 236. Lowest Common Ancestor of a Binary Tree
  • 思路: 儲存每個節點的parent節點資訊,之後看哪個節點比較深,就往parent節點回溯,最後看兩個節點的parent是否一樣,就是答案,蠻直觀的,畫個圖就能想像。
  • 分析: Time complexity = O(N), Space complexity = O(N) (auxiliary map structure to store the information, where N is # of nodes of the binary tree)
  • 心得: 用map來儲存節點的資訊真的好用(因為unique value的關係,形成很好的node_value, node_information pair),以後可以多練tree了
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution
{
public:
    struct node_info
    {
        TreeNode* parent;
        int depth;
    };
    map<TreeNode* , node_info> node_info_map;
    TreeNode* res;
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* node_p, TreeNode* node_q)
    {
        dfs_information(root, 0);
        node_info_map[root].parent = root; //for the root itself without runtime error
        res = root; //initialize
        climbup_LCA(node_p, node_q);
        return res;
    }
    //traverse the tree first to find the child-parent pair
    void dfs_information(TreeNode* root, int depth)
    {
        if(root == NULL)
        {
            return;
        }
        node_info_map[root].depth = depth;
        if(root->left)
        {
            node_info_map[root->left].parent = root;
            dfs_information(root->left, depth + 1);
        }
        if(root->right)
        {
            node_info_map[root->right].parent = root;
            dfs_information(root->right, depth + 1);
        }
    }
    //climb up to find the LCA, using depth comparison algorithm
    void climbup_LCA(TreeNode* node_p, TreeNode* node_q)
    {
        //
        if(node_info_map[node_p].parent == node_info_map[node_q].parent)
        {
            res = node_info_map[node_p].parent;
            return;
        }
        else if(node_info_map[node_p].parent == node_q)
        {
            res = node_q;
            return;
        }
        else if(node_info_map[node_q].parent == node_p)
        {
            res = node_p;
            return;
        }

        else if(node_info_map[node_p].depth > node_info_map[node_q].depth) //the one who is lower has to climb up one depth
        {
            climbup_LCA(node_info_map[node_p].parent, node_q);
        }
        else
        {
            climbup_LCA(node_p, node_info_map[node_q].parent);
        }
    }
};

PC.867. Prime Palindrome回文質數

  • 思路: 簡單來說就只是找有『回文』性質的植樹,由於偶數的回文ABBCCBBA、ABBA除了11以外都是11的倍數,因此可以忽略掉加快時間。 對於大於九百萬的,因為測資上界是一千萬,可以用OEIS檢測
  • 補充: 對於900萬以上的測資怎麼樣就是TLE,後來自己生了一次測資,發現900萬以上直到1000萬,測資上界的只剩下100030001這個,因此超過那個TLE的數字,我選擇直接回傳100030001,結果莫名其妙就AC了@@,因此也有直接列出OEIS版本的解法(算是有點偷吃步),詳見LeetCode討論串我寫的這篇文章
  • 分析: Time complexity O(N * sqrt (N)), Space complexity O(1), where N is the magnitude of input.
    class Solution
    {
    public:
        int primePalindrome(int num)
        {
            if(num == 1)
            {
                return 2;
            }
            else if(num >= 9989900)
            {
                return 100030001;
            }
            int flag = 0, cnt = 2;
            while(1)
            {
                if(cnt >= num)
                {
                    if(is_prime(cnt))
                    {
                        if(is_palindrome(cnt) )
                        {
                            break;
                        }
                    }
                }
                cnt++;
            }
            return cnt;
        }
        bool is_prime(int num)
        {
            for(int i = 2;i <= sqrt(num) ; i++)
            {
                if(num % i == 0)
                {
                    return 0;
                }
            }
            return 1;
        }
        bool is_palindrome(int num)
        {
    
            string str = to_string(num);
            string rev = str;
            if(num > 11 && str.size() % 2 == 0)
            {
                return 0;
            }
            reverse(rev.begin(), rev.end());
            return str == rev;
        }
    };
    

PD.865. Shortest Path to Get All Keys

  • 還沒做,好像是dijkstra的變化題,程度尚不夠,之後再來試試看囉:D