菜鸟刷题Day7

⭐作者:别动我的饭
⭐专栏:菜鸟刷题
⭐标语:悟已往之不谏,知来者之可追
在这里插入图片描述

一.整理字符串:1544. 整理字符串 - 力扣(LeetCode)

描述

给你一个由大小写英文字母组成的字符串 s 。

一个整理好的字符串中,两个相邻字符 s[i] 和 s[i+1],其中 0<= i <= s.length-2 ,要满足如下条件:

若 s[i] 是小写字符,则 s[i+1] 不可以是相同的大写字符。
若 s[i] 是大写字符,则 s[i+1] 不可以是相同的小写字符。

请你将字符串整理好,每次你都可以从字符串中选出满足上述条件的 两个相邻 字符并删除,直到字符串整理好为止。

请返回整理好的 字符串 。题目保证在给出的约束条件下,测试样例对应的答案是唯一的。

注意:空字符串也属于整理好的字符串,尽管其中没有任何字符。

示例 1:

输入:s = "leEeetcode"
输出:"leetcode"
解释:无论你第一次选的是 i = 1 还是 i = 2,都会使 "leEeetcode" 缩减为 "leetcode" 。

解题思路

这个题目描述很长给人一种压迫感,但是这个题目并不难。对于删除字符,我们至少有两种办法一种是直接挪动数据(复杂度太高,不考虑),还有就是新开一个数组,将有效数据放入新的数组中(用空间换时间)。

这里采用栈的思想,新建一个数组通过下标控制来达到模拟实现栈的目标。用栈的话就会很简单,直接将元素读取到栈中,如果栈顶的两个相邻元素是互为大小写,那么直接将栈顶的两个元素删除就行。在数组的表现形式上就是不断尾插尾删

char * makeGood(char * s)
{
    int len=strlen(s);
    
    char*tmp=(char*)malloc(sizeof(char)*(len+1));
    int top=0;//栈顶位置
    
    for(int i=0;i<len;i++)
    {
        //将所有元素入栈,如果栈顶的两个元素互为大小写,就将两个元素都删除
        tmp[top++]=s[i];
        
        if(top>=2&&(tmp[top-1]==tmp[top-2]-32||tmp[top-1]==tmp[top-2]+32))
        {
            //因为top是后置++,新入栈的两个元素一定是top-1和top-2
            
            top-=2;//改变top位置就实现删除,这个在数组中常用的(逻辑覆盖删除)
		}
    }
    
    //字符串的结束标志是'\0',前面的循环到'\0'前就结束了,所以还需要我们自行补充
    tmp[top]='\0';
    return tmp;
}

二.开幕式火焰:LCP 44. 开幕式焰火 - 力扣(LeetCode)

描述

「力扣挑战赛」开幕式开始了,空中绽放了一颗二叉树形的巨型焰火。
给定一棵二叉树 root 代表焰火,节点值表示巨型焰火这一位置的颜色种类。请帮小扣计算巨型焰火有多少种不同的颜色。

示例 1:

输入:root = [1,3,2,1,null,2]

输出:3

解释:焰火中有 3 个不同的颜色,值分别为 1、2、3

提示:

  • 1 <= 节点个数 <= 1000
  • 1 <= Node.val <= 1000

解题思路

根据示例可以看到,如果树中出现值相同的节点也只算一次,也就是说要统计节点val不相同的个数(null不算),有没有想起一个很熟悉的解法,这个解法在刚开始的时候就已经提到过了,就是基数排序。

其实就是建立一个数组,然后将节点的值作为下标,然后给这个下标位置的元素+1(要知道如果不对变量初始化,则变量中的值是随机值,所以一定要初始化)用memset对数组初始化后,调用前序遍历,最后再对数组遍历统计数组中不为零的个数。

int hash[1001];//因为前序遍历中也要用到这个数组,所以写成全局变量

void Perfind(struct TreeNode*root)
{
    if(root)
    {
        hash[root->val]+=1;//是不是很眼熟哈哈
        
        Perfind(root->left);
        Perfind(root->right);
    } 
    
}

int numColor(struct TreeNode* root)
{
    memset(hash,0,sizeof(hash));
    Perfind(root);
    
    int count=0;
    //暴力遍历
    for(int i=0;i<1001;i++)
    {
        if(hash[i]!=0)
            count++;
    }
    
    return count;
}  

你猜我为什么不直接在声明的时候定义写成:int hash[1001]={0},当然是因为跑不过所以才用memset。


三.从根到叶的二进制数之和:1022. 从根到叶的二进制数之和 - 力扣(LeetCode)

描述

给出一棵二叉树,其上每个结点的值都是 0 或 1 。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。

例如,如果路径为 0 -> 1 -> 1 -> 0 -> 1,那么它表示二进制数 01101,也就是 13 。
对树上的每一片叶子,我们都要找出从根到该叶子的路径所表示的数字。

返回这些数字之和。题目数据保证答案是一个 32 位 整数。

示例1:

在这里插入图片描述

输入:root = [1,0,1,0,1,0,1]
输出:22
解释:(100) + (101) + (110) + (111) = 4 + 5 + 6 + 7 = 22


解题思路

关于二进制求和的题目在前面也有做过,当时给了两种方法,但是第一种在这里不太好用,这里建议使用左移操作符,求和不是问题。

根据题目给的示例可以发现,是先走完左子树再走的右子树,也就是说遍历顺序是左子树——右子树——根(后序遍历),所以只要递归使用后续遍历即可,遍历到叶子节点时就开始计算累加和。当然如果这是一个空树,那我们直接返回空就行。

void AddVal(struct TreeNode* root,int val,int *sum)
{
    if(root==NULL)
        return NULL;
    //树不为空树,直接开始计算本次遍历获取到的二进制数
    val=(val<<1)+root->val;
    
    //到达叶子节点就累加计算整棵树的结果
    if(root->left==NULL&&root->right==NULL)
        *sum+=val;
    
    //递归遍历
    AddVal(root->left,val,sum);
    
    AddVal(root->right,val,sum);

}

int sumRootToLeaf(struct TreeNode* root)
{
    int sum=0;
    AddVal(root,0,&sum);
    
    return sum;//最后sum就是结果
}

四.二叉树的坡度:563. 二叉树的坡度 - 力扣(LeetCode)

描述

给你一个二叉树的根节点 root ,计算并返回 整个树 的坡度 。

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

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

示例1:

在这里插入图片描述

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

解题思路

这一题其实是一个变种的二叉树遍历,二叉树的坡度等于左树的坡度加右数的坡度加根的坡度,最后根节点的坡度是根所有子树和之间的坡度。可以采取和上题类似的办法,从叶子节点开始计算坡度和子树的和,并且累加每个子树坡度。最后根节点的坡度用两个子树和相减.

int dfs(struct TreeNode*root,int *sum)
{
    if(root==NULL)
        return 0;
    int left=dfs(root->left,sum);
    int right=dfs(root->right,sum);
    *sum+=abs(left-right);//拿到两个节点之间差的绝对值
    
    return left+right+root->val;//题目中说是该节点的左子树之和和右子树之和的差,要知道该节点的左子树又有左子树和右子树,所以必须要将左右子树节点记下来
}

int findTilt(struct TreeNode* root)
{
    int sum=0;
    dfs(root,&sum);
    return sum;
}

该说不说,递归有时候可读性是真不高,也很难整(菜鸡流泪again)。

人们总是高估短期努力带来的提升,而忽略长期坚持带来的改变。今天是第七天了,你还有坚持吗?

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

别动我的饭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值