leetcode 第一天


记录自己刷leetcode的所有题目,以增加印象

验证二叉树

二叉树上有 n 个节点,按从 0 到 n - 1 编号,其中节点 i 的两个子节点分别是 leftChild[i] 和 rightChild[i]。
只有 所有 节点能够形成且 只 形成 一颗 有效的二叉树时,返回 true;否则返回 false。
如果节点 i 没有左子节点,那么 leftChild[i] 就等于 -1。右子节点也符合该规则。
注意:节点没有值,本问题中仅仅使用节点编号。

示例 1:

在这里插入图片描述

输入:n = 4, leftChild = [1,-1,3,-1], rightChild = [2,-1,-1,-1]
输出:true
示例 2:
在这里插入图片描述
输入:n = 4, leftChild = [1,-1,3,-1], rightChild = [2,3,-1,-1]
输出:false
示例 3:

在这里插入图片描述

输入:n = 2, leftChild = [1,0], rightChild = [-1,-1]
输出:false
示例 4:

在这里插入图片描述

输入:n = 6, leftChild = [1,-1,-1,4,-1,-1], rightChild = [2,-1,-1,5,-1,-1]
输出:false

提示:

1 <= n <= 10^4
leftChild.length == rightChild.length == n
-1 <= leftChild[i], rightChild[i] <= n - 1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/validate-binary-tree-nodes

解题思路:并查集
并查集:并查集是这样一个数组
①F[x]=y x的父节点是y
②F[x]=x x是根节点
一棵二叉树可以确定一个并查集,例如 第一个二叉树的并查集如下
F[0]=0 //根节点
F[1]=0 //1号节点的父亲是0
F[2]=0 //2号节点的父亲是0
F[3]=2 //3号节点的父亲是2

class Solution {
private:
    int find(int x,int f[],int n){
        //判断是否有环,有环返回-1
        if(n<0) return -1;
        if(x == f[x]){
            return x;
        }
        //路径压缩,加快查询父节点的速度
        return f[x]=find(f[x],f,n-1);
    }
public:
    bool validateBinaryTreeNodes(int n, vector<int>& leftChild, vector<int>& rightChild) {
        int father[10005];
        //初始所有节点的父节点是自己
        for(int i=0;i<n;i++){
            father[i]=i;
        }
        //设置每个节点的真实父节点
        for(int i=0;i<n;i++){
            int index = leftChild[i];
            if(index!=-1){
                if(father[index]==index){
                    father[index] = i;
                }else{
                    return false;
                }
            }
        }
        for(int i=0;i<n;i++){
            int index = rightChild[i];
            if(index!=-1){
                if(father[index]==index){
                    father[index] = i;
                }else{
                    return false;
                }
            }
        }
        int fa = -1;
        //判断是否只有一个并查集,如果只有一个并查集,则只会有一个父节点
        for(int i=0;i<n;i++){
            int tf = find(i,father,n);
            if(tf==-1){
                return false;
            }else if(fa == -1){
                fa = tf;
            }else if(fa != tf){
                return false;
            }
        }
        return true;
    }
};

形成3的最大倍数

给你一个整数数组 digits,你可以通过按任意顺序连接其中某些数字来形成 3 的倍数,请你返回所能得到的最大的 3 的倍数。

由于答案可能不在整数数据类型范围内,请以字符串形式返回答案。

如果无法得到答案,请返回一个空字符串。

示例 1:

输入:digits = [8,1,9]
输出:“981”
示例 2:

输入:digits = [8,6,7,1,0]
输出:“8760”
示例 3:

输入:digits = [1]
输出:""
示例 4:

输入:digits = [0,0,0,0,0,0]
输出:“0”

提示:

1 <= digits.length <= 10^4
0 <= digits[i] <= 9
返回的结果不应包含不必要的前导零。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/largest-multiple-of-three
解题思路:此处参考官方答案
①一个整数能被三整除,必有各数位上之和是三的倍数,设所有数相加和为S
②如果S是3的倍数,则返回最大数,否则③
③将digits数组分为三部分,第一部分为所有数字均能被3整除,第二部分为除以3余数为2,第三部分为除以3余数为1
④如果S除以3余2,则在第二部分中除去最小的一个数即可,如果第二部分没有数字,则在第三部分除去两个最小的数字即可
⑤如果S除以3余1,则在第三部分中除去最小的一个数即可,如果第三部分没有数字,则在第二部分找两个最小的数即可

class Solution {
public:
    string largestMultipleOfThree(vector<int>& digits) {
        int sum=0;
        int num[10]={0};
        //统计各种数字的数量,求和sum
        for(int i=0;i<digits.size();i++){
            sum+=digits[i];
            num[digits[i]]++;
        } 
        //若sum除以3余2
        if(sum%3==2){
        	//只要2,5,8有一个存在即可
            if(num[2]||num[5]||num[8]){
                for(int i=2;i<9;i+=3){
                    if(num[i]){
                        num[i]--;
                        break;
                    }
                }
                //否则要求有两个余数为1的数字
            }else if(num[1]+num[4]+num[7]>1){
                int counts=2;
                for(int i=1;i<9&&counts>0;){
                    if(num[i]>0){
                        counts--;
                        num[i]--;
                    }else{
                        i+=3;
                    }
                }
            }
            //如果余数是1
        }else if(sum%3==1){
        	//1,4,7有一个即可
            if(num[1]+num[4]+num[7]>0){
                for(int i=1;i<9;i+=3){
                    if(num[i]>0){
                        num[i]--;
                        break;
                    }
                }
                //否则要求有两个余数为2的数字
            }else if(num[2]+num[5]+num[8]>1){
                int counts=2;
                for(int i=2;i<9&&counts>0;){
                    if(num[i]>0){
                        counts--;
                        num[i]--;
                    }else{
                        i+=3;
                    }
                }
            }
        }
        string result;
        for(int i=9;i>=0;){
            if(num[i]!=0){
                result=result+(char)(i+'0');
                num[i]--;
            }else{
                i--;
            }
        }
        if(result[0]=='0'){
            return "0";
        }
        return result;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值