剑指offer-树1m-9


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 sumisumj=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 sumik=sumj,建立map,存放{累加和, 出现次数}
      • 只需遍历一次,每次先更新 s u m i sum_i sumi,然后检查map中是否存在 s u m i − k sum_i-k sumik,若存在,就说明在 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},
      };
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值