{"id":8139,"date":"2021-02-20T22:16:18","date_gmt":"2021-02-21T06:16:18","guid":{"rendered":"https:\/\/zxi.mytechroad.com\/blog\/?p=8139"},"modified":"2021-02-20T22:34:48","modified_gmt":"2021-02-21T06:34:48","slug":"leetcode-1766-tree-of-coprimes","status":"publish","type":"post","link":"https:\/\/zxi.mytechroad.com\/blog\/searching\/leetcode-1766-tree-of-coprimes\/","title":{"rendered":"\u82b1\u82b1\u9171 LeetCode 1766. Tree of Coprimes"},"content":{"rendered":"\n<p>There is a tree (i.e.,&nbsp;a connected, undirected graph that has no cycles) consisting of&nbsp;<code>n<\/code>&nbsp;nodes numbered from&nbsp;<code>0<\/code>&nbsp;to&nbsp;<code>n - 1<\/code>&nbsp;and exactly&nbsp;<code>n - 1<\/code>&nbsp;edges. Each node has a value associated with it, and the&nbsp;<strong>root<\/strong>&nbsp;of the tree is node&nbsp;<code>0<\/code>.<\/p>\n\n\n\n<p>To represent this tree, you are given an integer array&nbsp;<code>nums<\/code>&nbsp;and a 2D array&nbsp;<code>edges<\/code>. Each&nbsp;<code>nums[i]<\/code>&nbsp;represents the&nbsp;<code>i<sup>th<\/sup><\/code>&nbsp;node&#8217;s value, and each&nbsp;<code>edges[j] = [u<sub>j<\/sub>, v<sub>j<\/sub>]<\/code>&nbsp;represents an edge between nodes&nbsp;<code>u<sub>j<\/sub><\/code>&nbsp;and&nbsp;<code>v<sub>j<\/sub><\/code>&nbsp;in the tree.<\/p>\n\n\n\n<p>Two values&nbsp;<code>x<\/code>&nbsp;and&nbsp;<code>y<\/code>&nbsp;are&nbsp;<strong>coprime<\/strong>&nbsp;if&nbsp;<code>gcd(x, y) == 1<\/code>&nbsp;where&nbsp;<code>gcd(x, y)<\/code>&nbsp;is the&nbsp;<strong>greatest common divisor<\/strong>&nbsp;of&nbsp;<code>x<\/code>&nbsp;and&nbsp;<code>y<\/code>.<\/p>\n\n\n\n<p>An ancestor of a node&nbsp;<code>i<\/code>&nbsp;is any other node on the shortest path from node&nbsp;<code>i<\/code>&nbsp;to the&nbsp;<strong>root<\/strong>. A node is&nbsp;<strong>not&nbsp;<\/strong>considered an ancestor of itself.<\/p>\n\n\n\n<p>Return&nbsp;<em>an array&nbsp;<\/em><code>ans<\/code><em>&nbsp;of size&nbsp;<\/em><code>n<\/code>,&nbsp;<em>where&nbsp;<\/em><code>ans[i]<\/code><em>&nbsp;is the closest ancestor to node&nbsp;<\/em><code>i<\/code><em>&nbsp;such that&nbsp;<\/em><code>nums[i]<\/code>&nbsp;<em>and&nbsp;<\/em><code>nums[ans[i]]<\/code>&nbsp;are&nbsp;<strong>coprime<\/strong>, or&nbsp;<code>-1<\/code><em>&nbsp;if there is no such ancestor<\/em>.<\/p>\n\n\n\n<p><strong>Example 1:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/assets.leetcode.com\/uploads\/2021\/01\/06\/untitled-diagram.png\" alt=\"\"\/><\/figure>\n\n\n\n<pre class=\"wp-block-preformatted;crayon:false\"><strong>Input:<\/strong> nums = [2,3,3,2], edges = [[0,1],[1,2],[1,3]]\n<strong>Output:<\/strong> [-1,0,0,1]\n<strong>Explanation:<\/strong> In the above figure, each node's value is in parentheses.\n- Node 0 has no coprime ancestors.\n- Node 1 has only one ancestor, node 0. Their values are coprime (gcd(2,3) == 1).\n- Node 2 has two ancestors, nodes 1 and 0. Node 1's value is not coprime (gcd(3,3) == 3), but node 0's\n  value is (gcd(2,3) == 1), so node 0 is the closest valid ancestor.\n- Node 3 has two ancestors, nodes 1 and 0. It is coprime with node 1 (gcd(3,2) == 1), so node 1 is its\n  closest valid ancestor.\n<\/pre>\n\n\n\n<p><strong>Example 2:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/assets.leetcode.com\/uploads\/2021\/01\/06\/untitled-diagram1.png\" alt=\"\"\/><\/figure>\n\n\n\n<pre class=\"wp-block-preformatted;crayon:false\"><strong>Input:<\/strong> nums = [5,6,10,2,3,6,15], edges = [[0,1],[0,2],[1,3],[1,4],[2,5],[2,6]]\n<strong>Output:<\/strong> [-1,0,-1,0,0,0,-1]\n<\/pre>\n\n\n\n<p><strong>Constraints:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>nums.length == n<\/code><\/li><li><code>1 &lt;= nums[i] &lt;= 50<\/code><\/li><li><code>1 &lt;= n &lt;= 10<sup>5<\/sup><\/code><\/li><li><code>edges.length == n - 1<\/code><\/li><li><code>edges[j].length == 2<\/code><\/li><li><code>0 &lt;= u<sub>j<\/sub>, v<sub>j<\/sub>&nbsp;&lt; n<\/code><\/li><li><code>u<sub>j<\/sub>&nbsp;!= v<sub>j<\/sub><\/code><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Solution: DFS + Stack<\/strong><\/h2>\n\n\n\n<p>Pre-compute for coprimes for each number.<\/p>\n\n\n\n<p>For each node, enumerate all it&#8217;s coprime numbers, find the deepest occurrence. <\/p>\n\n\n\n<p>Time complexity: O(n * max(nums))<br>Space complexity: O(n)<\/p>\n\n\n\n<div class=\"responsive-tabs\">\n<h2 class=\"tabtitle\">C++<\/h2>\n<div class=\"tabcontent\">\n\n<pre lang=\"c++\">\n\/\/ Author: Huahua\nclass Solution {\npublic:\n  vector<int> getCoprimes(vector<int>& nums, vector<vector<int>>& edges) {\n    constexpr int kMax = 50;\n    const int n = nums.size();\n    vector<vector<int>> g(n);\n    for (const auto& e : edges) {\n      g[e[0]].push_back(e[1]);\n      g[e[1]].push_back(e[0]);\n    }    \n        \n    vector<vector<int>> coprime(kMax + 1);\n    for (int i = 1; i <= kMax; ++i)\n      for (int j = 1; j <= kMax; ++j)\n        if (gcd(i, j) == 1) coprime[i].push_back(j);\n    \n    vector<int> ans(n, INT_MAX);\n    vector<vector<pair<int, int>>> p(kMax + 1);\n    function<void(int, int)> dfs = [&](int cur, int d) {    \n      int max_d = -1;\n      int ancestor = -1;\n      for (int co : coprime[nums[cur]])\n        if (!p[co].empty() && p[co].back().first > max_d) {\n          max_d = p[co].back().first;\n          ancestor = p[co].back().second;          \n        }\n      ans[cur] = ancestor;\n      p[nums[cur]].emplace_back(d, cur);\n      for (int nxt : g[cur])\n        if (ans[nxt] == INT_MAX) dfs(nxt, d + 1);\n      p[nums[cur]].pop_back();\n    };\n    \n    dfs(0, 0);\n    return ans;\n  }\n};\n<\/pre>\n<\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>There is a tree (i.e.,&nbsp;a connected, undirected graph that has no cycles) consisting of&nbsp;n&nbsp;nodes numbered from&nbsp;0&nbsp;to&nbsp;n &#8211; 1&nbsp;and exactly&nbsp;n &#8211; 1&nbsp;edges. Each node has a&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[44],"tags":[638,33,217,28],"class_list":["post-8139","post","type-post","status-publish","format-standard","hentry","category-searching","tag-ancestor","tag-dfs","tag-hard","tag-tree","entry","simple"],"_links":{"self":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts\/8139","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/comments?post=8139"}],"version-history":[{"count":2,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts\/8139\/revisions"}],"predecessor-version":[{"id":8141,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts\/8139\/revisions\/8141"}],"wp:attachment":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/media?parent=8139"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/categories?post=8139"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/tags?post=8139"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}