2021-11-18每日刷题打卡

2021-11-18每日刷题打卡

力扣——每日一题

563. 二叉树的坡度

给定一个二叉树,计算 整个树 的坡度 。

一个树的 节点的坡度 定义即为,该节点左子树的节点之和和右子树节点之和的 差的绝对值 。如果没有左子树的话,左子树的节点之和为 0 ;没有右子树的话也是一样。空结点的坡度是 0 。

整个树 的坡度就是其所有节点的坡度之和。

示例 1:

tilt2.jpg (1231×312) (leetcode.com)

输入:root = [1,2,3]
输出:1
解释:
节点 2 的坡度:|0-0| = 0(没有子节点)
节点 3 的坡度:|0-0| = 0(没有子节点)
节点 1 的坡度:|2-3| = 1(左子树就是左子节点,所以和是 2 ;右子树就是右子节点,所以和是 3 )
坡度总和:0 + 0 + 1 = 1

准备一个全局变量ans来计算坡度总和,递归遍历二叉树,先把根节点送去遍历,每次递归一开始先判断节点是否为空,如果为空,直接返回0,(递归函数的返回值是树整体的val值和,比如上面这图的2节点,它整个树的val和就是2+3+5),然后把当前节点的左子树和右子树送去递归,返回值分别用num_l和num_r接收,然后把他俩的差值的绝对值加到ans上,这就是这个节点的坡度了,然后把当前节点的val和num_l与nums_r的总和返回。当所有递归结束后,返回ans即可。

/**
 * 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) {}
 * };
 */
class Solution {
public:
    int ans=0;
    int findTilt(TreeNode* root) {
        dfs(root);
        return ans;
    }   
    int dfs(TreeNode*root)
    {
        if(!root)return 0;
        int val_num=root->val;
        int val_l=dfs(root->left);
        int val_r=dfs(root->right);
        ans+=abs(val_l-val_r);
        return val_r+val_l+val_num;
    }
};
802. 区间和 - AcWing题库

假定有一个无限长的数轴,数轴上每个坐标上的数都是 0。

现在,我们首先进行 n 次操作,每次操作将某一位置 x 上的数加 c。

接下来,进行 m 次询问,每个询问包含两个整数 l 和 r,你需要求出在区间 [l,r] 之间的所有数的和。

输入格式

第一行包含两个整数 n 和 m。

接下来 n 行,每行包含两个整数 x 和 c。

再接下来 m 行,每行包含两个整数 l 和 r。

输出格式

共 m 行,每行输出一个询问中所求的区间内数字和。

数据范围

−109≤x≤109
1≤n,m≤10^5
−109≤l≤r≤109
−10000≤c≤10000

输入样例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
输出样例:
8
0
5

离散化就这么说,题目虽然说了无限长的数轴,但实际用到的只有几个点而已,比如有一条数轴,上面有10w个点,但我只在1 20 5000 10000上加上1,其它点还是0,那么我们只要算这四个点就行,反正其它点是0,我们就把这四个点重新排,第1个点是1,第二个点是20,第三个点是5000,第四个点是10000,那么当题目问我们区间和时,我们只要看区间之间有没有我们这几个点就行,比如计算5~10000的和,那就是20和5000和10000上的值加起来就行。

#include<iostream>
using namespace std;
typedef pair<int,int> PII;
#include<vector>
#include<algorithm>
const int N=300010;
int a[N],s[N];
vector<int>alls;
vector<PII>adds,range;

int find(int x)
{
    int l=0,r=alls.size()-1;
    while(l<r)
    {
        int mid=l+r>>1;
        if(alls[mid]>=x)r=mid;
        else l=mid+1;
    }
    return r+1;
}

int main()
{
    int l,r,n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        int x,c;
        cin>>x>>c;
        adds.push_back({x,c});
        alls.push_back(x);
    }
    for(int i=0;i<m;i++)
    {
        cin>>l>>r;
        range.push_back({l,r});
        alls.push_back(l);
        alls.push_back(r);
    }
    sort(alls.begin(),alls.end());
    alls.erase(unique(alls.begin(),alls.end()),alls.end());
    for(auto i:adds)
    {
        int x=find(i.first);
        a[x]+=i.second;
    }
    for(int i=1;i<=alls.size();i++)s[i]=s[i-1]+a[i];
    for(auto i:range)
    {
        l=find(i.first),r=find(i.second);
        cout<<s[r]-s[l-1]<<endl;
    }
    return 0;
}
803. 区间合并 - AcWing题库

给定 n 个区间 [li,ri],要求合并所有有交集的区间。

注意如果在端点处相交,也算有交集。

输出合并完成后的区间个数。

例如:[1,3]和 [2,6] 可以合并为一个区间 [1,6]。

输入格式

第一行包含整数 n。

接下来 n 行,每行包含两个整数 l 和 r。

输出格式

共一行,包含一个整数,表示合并区间完成后的区间个数。

数据范围

1≤n≤100000
−109≤li≤ri≤109

输入样例:
5
1 2
2 4
5 6
7 8
7 9
输出样例:
3

区间合并就是把多个区间合并成一个区间,但必须是有交集的才能合并,比如【1,3】和【2,6】这种才能合并,或者【1,3】和【3,4】这类,即第一个区间的尾部在第二个区间的范围里,如果没交集则没法合并。

我们把每个区间设置成键值对的情况然后存入vector中,然后我们根据区间的左端点进行排序,从小到大,然后遍历vector,判断当前区间的右端点在不在下一个区间的范围里,如果在说明有交集,把这两个区间合并,如果不在范围里则不合并,最后输出vector容器的size(即有多少区间)。

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>

typedef pair<int,int> PII;
const int N=100010;
int n,l,r;
vector<PII>segs;

void merge(vector<PII>&segs)
{
    vector<PII>res;
    sort(segs.begin(),segs.end());
    int st=-2e9,ed=-2e9;
    for(auto i:segs)
    {
        if(ed<i.first)
        {
            if(st!=-2e9)res.push_back({st,ed});
            st=i.first,ed=i.second;
        }
        else ed=max(ed,i.second);
    }
    if(st!=-2e9)res.push_back({st,ed});
    segs=res;
}

int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>l>>r;
        segs.push_back({l,r});
    }
    merge(segs);
    cout<<segs.size()<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值