JZ84 (m)二叉树中和为某一值的路径(三)
-
主要考察在给定数组中寻找和为
k
的连续子数组,在此之上套了个二叉树的皮- 找连续子数组可以用两次dfs或者两重循环,但是这样时间复杂度就 O ( n 2 ) O(n^2) O(n2)了
- 原始问题可以转化为:
- 在数组中寻找两个位置 i , j i, j i,j,使得 s u m i − s u m j = k sum_i-sum_j=k sumi−sumj=k,其中 s u m i sum_i sumi表示从数组开头一直到 i i i位置的累加和
- 上式可变为: s u m i − k = s u m j sum_i-k=sum_j sumi−k=sumj,建立map,存放{累加和, 出现次数}
- 只需遍历一次,每次先更新 s u m i sum_i sumi,然后检查map中是否存在 s u m i − k sum_i-k sumi−k,若存在,就说明在 i i i之前有一个 j j j,从 j j j到 i i i这一段的元素和为 k k k;然后将 s u m i sum_i sumi加入map中。
-
复杂度:时间 O ( n ) O(n) O(n)(一次dfs),空间 O ( n ) O(n) O(n)(递归调用栈+map)
class Solution { public: int FindPath(TreeNode* root, int sum) { map<int, int> m{{0,1}}; int cnt=0, total=0; dfs(root, sum, cnt, total, m); return cnt; } void dfs(TreeNode *root,const int &sum, int &cnt, int total, map<int, int> &m){ if(!root) return; total+=root->val; if(m.find(total-sum) != m.end()) cnt+=m.at(total-sum); if(m.find(total) != m.end()) m[total]++; else m[total] = 1; dfs(root->left, sum, cnt, total, m); dfs(root->right, sum, cnt, total, m); m[total]--; } };
今天学到的知识
- std::map
- std::map::find(const Key& key)
返回指向键等于 key 的元素的迭代器。若找不到,则返回end() 迭代器。 - 构造函数
可使用初始化列表const std::map<std::string, int> init { {"this", 100}, {"can", 100}, {"be", 100}, {"const", 100}, };
- std::map::find(const Key& key)