Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions C++/House-Robber-3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/

// Question link: https://leetcode.com/problems/house-robber-iii/
class Solution
{
public:
/*
Why is this DP on tree? And not simply greedy?
Try to think of some cases, like 5 -> 4 -> 2 -> 3
here greedy takes only alternate levels sum -> max(5 + 2, 4 + 3)
and misses the final answer as 5 + 3 (choosing the main root and last leaf) giving 8

Case 1: you choose the current node
Case 2: you dont choose the current node

Caching using map(unordered because its quicker than std::map & since we dont need nodes sorted in this question), to avoid TLE

Time Complexity: O(N) (because traversing over all N nodes of tree)
Space Complexity: O(N) (because of map)
*/
unordered_map<TreeNode *, int> mp; // maximum value obtained for this node, stored as pairs in map
int helper(TreeNode *root)
{
if (root == NULL)
return 0;
if (mp.find(root) != mp.end())
return mp[root];
int case1 = root->val;
if (root->left)
{
case1 += helper(root->left->left);
case1 += helper(root->left->right);
}
if (root->right)
{
case1 += helper(root->right->right);
case1 += helper(root->right->left);
}
int case2 = helper(root->left) + helper(root->right);
return mp[root] = max(case1, case2);
}
int rob(TreeNode *root)
{
if (root == NULL)
return 0;
int ans = helper(root);
return ans;
}
};
66 changes: 66 additions & 0 deletions C++/Sum-of-distances-in-tree.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
class Solution
{
public:
/*
Uses classics Tree Re-rooting DP,
Need to do 2 traversals: DFSes but 1 as Post Order and second as Pre-order

When we move our root from parent to its child i,
count[i] points get 1 closer to root, n - count[i] nodes get 1 futhur to root.

Time Complexity: O(N) because both DFS visit all ndoes
Space Compexity: O(N) because of the resultant & helper subtree-node-count array

*/

/* Post Order to update distances while going from parent to root
To track a count of number of children in the subtree
*/
void dfs1(int node, int parent, vector<int> &res, vector<int> &count, vector<vector<int>> &graph)
{
for (auto child : graph[node])
{
if (child == parent)
continue;
dfs1(child, node, res, count, graph);
count[node] += count[child];
res[node] += res[child] + count[child];
}
}

/* Pre order traversal style DFS, to update the result vector in direction of child -> parent */
void dfs2(int node, int parent, vector<int> &res, vector<int> &count, vector<vector<int>> &graph, int n)
{
for (auto child : graph[node])
{
if (child == parent)
continue;
res[child] = res[node] - count[child] + n - count[child];
dfs2(child, node, res, count, graph, n);
}
}

vector<int> sumOfDistancesInTree(int n, vector<vector<int>> &edges)
{

vector<int> count(n, 1); //stores count of number of children, atleast 1 node, ie itself should be in count[node]
vector<int> res(n, 0); //Stores final distance sum for each node

vector<vector<int>> graph(n);

int u, v;

// Constructing the graph from the given array
for (int i = 0; i < edges.size(); ++i)
{
u = edges[i][0], v = edges[i][1];
graph[u].push_back(v);
graph[v].push_back(u);
}

dfs1(0, -1, res, count, graph);
dfs2(0, -1, res, count, graph, n);

return res;
}
};
Loading