hot-100-1

文章详细介绍了多个编程题目,包括两数之和、两数相加(链表实现)、有效括号、合并两个有序链表、爬楼梯、二叉树的中序遍历、对称二叉树、二叉树的最大深度、买卖股票的最佳时机、环形链表、相交链表、多数元素、翻转链表、翻转二叉树、回文链表、比特位计数、找到所有数组中消失的数字和汉明距离等。每个题目都提供了至少两种解法,如哈希表、递归、迭代等策略。
摘要由CSDN通过智能技术生成

hot-100-1

第1题 两数和taget-num

方法一: 哈希表

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> hashtable;
        for (int i = 0; i < nums.size(); ++i) {
            auto it = hashtable.find(target - nums[i]);
            if (it != hashtable.end()) {
                return {it->second, i};
            }
            hashtable[nums[i]] = i;
        }
        return {};
    }
};

方法二:暴力枚举

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int n = nums.size();
        for (int i = 0; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                if (nums[i] + nums[j] == target) {
                    return {i, j};
                }
            }
        }
        return {};
    }
};

第二题,两数相加(链表实现)

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
在这里插入图片描述

方法一:c++ 用二级指针,不用创建dummyhead

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* node = nullptr;
        ListNode** n = &node;
        int ca = 0;
        while(l1 || l2 || ca){
            int sum = ca;
            sum += l1? l1->val: 0;
            sum += l2? l2->val: 0;
            ca = sum / 10;
            *n = new ListNode(sum % 10);
            n = &((*n)->next);
            if(l1) l1 = l1->next;
            if(l2) l2 = l2->next;
        }
        return node;
    }
};

方法二:

整体思路:
不对齐补零,若链表不为空则用 sum(代表每个位的和的结果)加上,考虑进位。

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* head=new ListNode(-1);//存放结果的链表
        ListNode* h=head;//移动指针
        int sum=0;//每个位的加和结果
        bool carry=false;//进位标志
        while(l1!=NULL||l2!=NULL)
        {
            sum=0;
            if(l1!=NULL)
            {
                sum+=l1->val;
                l1=l1->next;
            }
            if(l2!=NULL)
            {
                sum+=l2->val;
                l2=l2->next;
            }
            if(carry)
                sum++;
            h->next=new ListNode(sum%10);
            h=h->next;
            carry=sum>=10?true:false;
        }
        if(carry)
        {
            h->next=new ListNode(1);
        }
        return head->next;
    }
};

第三题 20.有效的括号 2023/4/13

(如下是官方给的代码:)

class Solution {
public:
    bool isValid(string s) {
        int n = s.size();
        if (n % 2 == 1) {
            return false;
        }

        unordered_map<char, char> pairs = {
            {')', '('},
            {']', '['},
            {'}', '{'}
        };
        stack<char> stk;
        for (char ch: s) {
            if (pairs.count(ch)) {
                if (stk.empty() || stk.top() != pairs[ch]) {
                    return false;
                }
                stk.pop();
            }
            else {
                stk.push(ch);
            }
        }
        return stk.empty();
    }
};

第四题:2023/4/13 合并两个有序链表

在这里插入图片描述

方法一:

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* preHead = new ListNode(-1);

        ListNode* prev = preHead;
        while (l1 != nullptr && l2 != nullptr) {
            if (l1->val < l2->val) {
                prev->next = l1;
                l1 = l1->next;
            } else {
                prev->next = l2;
                l2 = l2->next;
            }
            prev = prev->next;
        }

        // 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
        prev->next = l1 == nullptr ? l2 : l1;

        return preHead->next;
    }
};

方法二:(递归)

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if (l1 == nullptr) {
            return l2;
        } else if (l2 == nullptr) {
            return l1;
        } else if (l1->val < l2->val) {
            l1->next = mergeTwoLists(l1->next, l2);
            return l1;
        } else {
            l2->next = mergeTwoLists(l1, l2->next);
            return l2;
        }
    }
};

第五题 爬楼梯

第六题 94. 二叉树的中序遍历

自己的答案:方法一:递归(栈)

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int>v;
        inorder(root,v);
        return v;
    }
    void inorder(TreeNode* root,vector<int> &v)
    {
        if(!root)return ;
        inorder(root->left,v);
        v.push_back(root->val);
        inorder(root->right,v);
    }
};

方法二:迭代

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int>v;
        inorder(root,v);
        return v;
    }
    void inorder(TreeNode* root,vector<int> &v)
    {
        if(!root)return ;
        inorder(root->left,v);
        v.push_back(root->val);
        inorder(root->right,v);
    }
};

第七题: 对称二叉树

官方代码1:递归

class Solution {
public:
    bool check(TreeNode *p, TreeNode *q) {
        if (!p && !q) return true;
        if (!p || !q) return false;
        return p->val == q->val && check(p->left, q->right) && check(p->right, q->left);
    }

    bool isSymmetric(TreeNode* root) {
        return check(root, root);
    }
};

官方代码2:迭代

class Solution {
public:
    bool check(TreeNode *u, TreeNode *v) {
        queue <TreeNode*> q;
        q.push(u); q.push(v);
        while (!q.empty()) {
            u = q.front(); q.pop();
            v = q.front(); q.pop();
            if (!u && !v) continue;
            if ((!u || !v) || (u->val != v->val)) return false;

            q.push(u->left); 
            q.push(v->right);

            q.push(u->right); 
            q.push(v->left);
        }
        return true;
    }

    bool isSymmetric(TreeNode* root) {
        return check(root, root);
    }
};

第八题 二叉树的最大深度

方法一 深度优先 递归:

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if(!root)return 0;
        int a=maxDepth(root->left);
        int b=maxDepth(root->right);
        return (a>b)?a+1:b+1;
    }
};

方法二 广度优先遍历,队列

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if(!root)return 0;
        queue<TreeNode *>q;
        q.push(root);
        int temp,depth=0;
        TreeNode *node;
        while(!q.empty())
        {
            temp=q.size();
            while(temp>0)
            {
                node=q.front();
                q.pop();
                if(node->left) q.push(node->left);
                if(node->right)q.push(node->right);
                temp--;
            }
        depth++;
        }
        return depth;

    }
};

第九题 买卖股票的最佳时机ii

方法一:暴力法:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int output=0;
        for(int j=0;j<prices.size()-1;j++)
        {
            for(int i=j+1;i<prices.size();i++)
            {
                output=max(output,prices[i]-prices[j]);
            }
        }
        return output;
    }
};

方法二 一次遍历

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int minprice=1e9,maxprofit=0;
        for(int i:prices)
        {
            maxprofit=max(maxprofit,i-minprice);
            minprice=min(minprice,i);
        }
        return maxprofit;
    }
};

时间复杂度:O(n)。
空间复杂度:O(1)。在这里插入图片描述

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        if (n == 0) return 0; // 边界条件
        int minprice = prices[0];
        vector<int> dp (n, 0);

        for (int i = 1; i < n; i++){
            minprice = min(minprice, prices[i]);
            dp[i] = max(dp[i - 1], prices[i] - minprice);
        }
        return dp[n - 1];
    }
};

时间复杂度:O(n)。
空间复杂度:O(n)。

第10题 136.只出现一次数字

在这里插入图片描述
在这里插入图片描述

方法一:位运算

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ret = 0;
        for (auto e: nums) ret ^= e;
        return ret;
    }
};

O(n),O(1)
方法二: 排序然后找出该出现仅一次元素

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int len=nums.size();
        if(len==1)return nums[0];
        sort(nums.begin(),nums.end());
        if(nums[0]!=nums[1])return nums[0];
        if(nums[len-1]!=nums[len-2])return nums[len-1];
        for(int i=1;i<len-1;i++){
            if(nums[i]!=nums[i-1]&&nums[i]!=nums[i+1])return nums[i];
        }
        return 0;

    }
};

第11题 141. 环形链表

要求:给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。没有环pos=-1
如果链表中存在环 ,则返回 true 。 否则,返回 false 。
方法一:哈希表

class Solution {
public:
    bool hasCycle(ListNode *head) {
        unordered_set<ListNode*> seen;
        while (head != nullptr) {
            if (seen.count(head)) {
                return true;
            }
            seen.insert(head);
            head = head->next;
        }
        return false;
    }
};

方法二:指针

class Solution {
public:
    bool hasCycle(ListNode* head) {
        if (head == nullptr || head->next == nullptr) {
            return false;
        }
        ListNode* slow = head;
        ListNode* fast = head->next;
        while (slow != fast) {
            if (fast == nullptr || fast->next == nullptr) {
                return false;
            }
            slow = slow->next;
            fast = fast->next->next;
        }
        return true;
    }
};

第12题 相交链表 4/19

提示:
listA 中节点数目为 m
listB 中节点数目为 n

方法一:哈希集合

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        unordered_set<ListNode *> visited;
        ListNode *temp = headA;
        while (temp != nullptr) {
            visited.insert(temp);
            temp = temp->next;
        }
        temp = headB;
        while (temp != nullptr) {
            if (visited.count(temp)) {
                return temp;
            }
            temp = temp->next;
        }
        return nullptr;
    }
};

方法二:双指针

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if (headA == nullptr || headB == nullptr) {
            return nullptr;
        }
        ListNode *pA = headA, *pB = headB;
        while (pA != pB) {
            pA = pA == nullptr ? headB : pA->next;
            pB = pB == nullptr ? headA : pB->next;
        }
        return pA;
    }
};

第13题 多数元素 4/19

在这里插入图片描述

方法一:哈希表 自己做出来的

 int majorityElement(vector<int>& nums) {
        unordered_map<int,int>hashtable;
        int maxe,half=nums.size()/2;
        for(auto e:nums)
        {
            ++hashtable[e];
            if(hashtable[e]>half)
            {
                maxe=e;
                break;
            }
        }
        return maxe;
    }

方法二:排序

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        return nums[nums.size() / 2];
    }
};

方法三 动态增减。 经典啊!

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int cur = INT_MIN, count = 0;
        for (const int& num : nums) {
            if (count == 0) {
                cur = num;
                ++count;
            } else {
                count += (cur == num ? 1 : -1);
            }
        }
        return cur;
    }
};

方法四:随机

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        while (true) {
            int candidate = nums[rand() % nums.size()];
            int count = 0;
            for (int num : nums)
                if (num == candidate)
                    ++count;
            if (count > nums.size() / 2)
                return candidate;
        }
        return -1;
    }
};

方法五:Boyer-Moore 投票

在这里插入图片描述

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int candidate = -1;
        int count = 0;
        for (int num : nums) {
            if (num == candidate)
                ++count;
            else if (--count < 0) {
                candidate = num;
                count = 1;
            }
        }
        return candidate;
    }
};

206. 反转链表 第14题 23/4/19

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
方法一:

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* curr = head;
        while (curr) {
            ListNode* next = curr->next;
            curr->next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
};

方法二:递归

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (!head || !head->next) {
            return head;
        }
        ListNode* newHead = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return newHead;
    }
};

226. 翻转二叉树 第15题 23/4/20

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
方法一:队列层序遍历

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(!root)return nullptr;
        queue<TreeNode *>q;
        q.push(root);
        TreeNode *node,*temp;
        while(!q.empty())
        {
            node=q.front();
            q.pop();
            temp=node->left;
            node->left=node->right;
            node->right=temp;
            if(node->left)q.push(node->left);
            if(node->right)q.push(node->right);
        }
        return root;
    }
};

方法二:迭代 时间:O(n),空间:O(n)

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(!root)return nullptr;
        TreeNode *left=invertTree(root->left);
        TreeNode *right=invertTree(root->right);
        root->left=right;
        root->right=left;
        return root;
    }
};

234. 回文链表 第16题 23/4/20

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

方法一:官方代码 迭代,太优雅了

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        vector<int> vals;
        while (head != nullptr) {
            vals.emplace_back(head->val);
            head = head->next;
        }
        for (int i = 0, j = (int)vals.size() - 1; i < j; ++i, --j) {
            if (vals[i] != vals[j]) {
                return false;
            }
        }
        return true;
    }
};

方法二:将值复制到数组中后用双指针法

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        vector<int> vals;
        while (head != nullptr) {
            vals.emplace_back(head->val);
            head = head->next;
        }
        for (int i = 0, j = (int)vals.size() - 1; i < j; ++i, --j) {
            if (vals[i] != vals[j]) {
                return false;
            }
        }
        return true;
    }
};

方法三:快慢指针和反转后半链表 进行比较

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if (head == nullptr) {
            return true;
        }

        // 找到前半部分链表的尾节点并反转后半部分链表
        ListNode* firstHalfEnd = endOfFirstHalf(head);
        ListNode* secondHalfStart = reverseList(firstHalfEnd->next);

        // 判断是否回文
        ListNode* p1 = head;
        ListNode* p2 = secondHalfStart;
        while (p2 != nullptr) {	//注意:需要p2是否为空作为条件。p1还是整个链表的长度
            if (p1->val != p2->val) {
                return false;
            }
            p1 = p1->next;
            p2 = p2->next;
        }        

        // 还原链表并返回结果
        firstHalfEnd->next = reverseList(secondHalfStart);
        return true;
    }

    ListNode* reverseList(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* curr = head;
        while (curr != nullptr) {
            ListNode* nextTemp = curr->next;
            curr->next = prev;
            prev = curr;
            curr = nextTemp;
        }
        return prev;
    }

    ListNode* endOfFirstHalf(ListNode* head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while (fast->next != nullptr && fast->next->next != nullptr) {
            fast = fast->next->next;
            slow = slow->next;
        }
        return slow;
    }
};

338. 比特位计数 第18题 23/4/20 (自己做对了,但是效率很低)

给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。

class Solution {
public:
    vector<int> countBits(int n) {
        vector<int>v;
        for(int i=0;i<=n;i++)
        {
            v.push_back(binary(i));
        }
        return v;
    }
    int binary(int num)
    {
        int mod1,sum=0;
        while(num!=0)
        {
            mod1=num%2;
            num=num/2;
            sum+=mod1;
        }
    return sum;
    }
};

官方代码方法二:Brian Kernighan 算法Onlogn,O1

class Solution {
public:
    int countOnes(int x) {
        int ones = 0;
        while (x > 0) {
            x &= (x - 1);
            ones++;
        }
        return ones;
    }

    vector<int> countBits(int n) {
        vector<int> bits(n + 1);
        for (int i = 0; i <= n; i++) {
            bits[i] = countOnes(i);
        }
        return bits;
    }
};

方法二:动态规划——最高有效位On,O1

class Solution {
public:
    vector<int> countBits(int n) {
        vector<int> bits(n + 1);
        int highBit = 0;
        for (int i = 1; i <= n; i++) {
            if ((i & (i - 1)) == 0) {
                highBit = i;
            }
            bits[i] = bits[i - highBit] + 1;
        }
        return bits;
    }
};

方法三:动态规划——最低有效位On,O1

class Solution {
public:
    vector<int> countBits(int n) {
        vector<int> bits(n + 1);
        for (int i = 1; i <= n; i++) {
            bits[i] = bits[i >> 1] + (i & 1);
        }
        return bits;
    }
};

方法四:动态规划——最低设置位On,O1

class Solution {
public:
    vector<int> countBits(int n) {
        vector<int> bits(n + 1);
        for (int i = 1; i <= n; i++) {
            bits[i] = bits[i & (i - 1)] + 1;
        }
        return bits;
    }
};

448. 找到所有数组中消失的数字 (可以看看 **)23/4/21

方法一:每次取余,把得到的 +n (其实不影响后续的取余)
方法三:unordered_set insert()插入重复数字只保留一份。
给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

自己写出来的。很死板,老调
class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        vector<int>v1;
        sort(nums.begin(),nums.end());
        int j=1;
        for(int i=0;i<nums.size();)
        {
            if(nums[i]==j)
            {
                j++;
                i++;
            }
            else if(nums[i]>j)
            {
                v1.push_back(j);
                j++;
            }
            else
                i++;
            //1 2 2 3 3 4 7 8
            //1 1 1 1 1 
        }
        for(;j<=nums.size();j++)//最后考虑比如上面的全是1的情况。i一直在走。j原地不动
        {
            v1.push_back(j);
        }
        return v1;
    }
};

官方代码方法一:

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        int n = nums.size();
        for (auto& num : nums) {
            int x = (num - 1) % n;
            nums[x] += n;
        }
        vector<int> ret;
        for (int i = 0; i < n; i++) {
            if (nums[i] <= n) {
                ret.push_back(i + 1);
            }
        }
        return ret;
    }
};

方法二:先排序

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<int> ans;
        int n = nums.size();
        int loc = 0;
        for (int to = 1; to <= n; to++) {
            while (loc < n && nums[loc] < to)
                loc++;
            if (loc == n || nums[loc] != to)
                ans.push_back(to);
        }
        return ans;
    }
};

方法三:哈希

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        unordered_set<int> se;
        for (int& t : nums)
            se.insert(t);//插入重复的数字,只会保留一个
        vector<int> ans;
        int n = nums.size();
        for (int i = 1; i <= n; i++) {
            if (!se.count(i))
                ans.push_back(i);
        }
        return ans;
    }
};

461. 汉明距离 (值得看 ***) 23/4/21

两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。
给你两个整数 x 和 y,计算并返回它们之间的汉明距离。
核心思想: n & n-1 的值是 去掉二进制n最右边1的值;或者 n&0x1 或者n&1

不多废话,直接上核心: n & n-1 的值是 去掉二进制n最右边1的值; 比如 1010 & 1001 = 1000;用这个可以非常优雅的计算一个数里面的1的个数!
方法一: 优雅,实在是太优雅了,位运算yyds! Brian Kernighan 算法

class Solution {
public:
    int hammingDistance(int x, int y) {
        int ret = x^y;      //异或剩下1的个数就是二进制位不同的位置的数目
        int ans = 0;        //answer 记录1的个数
        while(ret){         //每一次运算消去一个1,直到为0终止循环
            ret&=(ret-1);   // ret= ret & (ret-1); 
            ans++;
        }
        return ans;
    }
};

方法二:异或,每次并0x1 +右移运算符

class Solution {
public:
    int hammingDistance(int x, int y) {
        int s = x ^ y, ret = 0;
        while (s) {
            ret += s & 1;
            s >>= 1;
        }
        return ret;
    }
};

543. 二叉树的直径 第21题 23/4/22(可以看 **)

给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。
官方方法一:深度递归

class Solution {
    int ans;
    int depth(TreeNode* rt){
        if (rt == NULL) {
            return 0; // 访问到空节点了,返回0
        }
        int L = depth(rt->left); // 左儿子为根的子树的深度
        int R = depth(rt->right); // 右儿子为根的子树的深度
        ans = max(ans, L + R + 1); // 计算d_node即L+R+1 并更新ans
        return max(L, R) + 1; // 返回该节点为根的子树的深度
    }
public:
    int diameterOfBinaryTree(TreeNode* root) {
        ans = 1;
        depth(root);
        return ans - 1;
    }
};

官方代码方法一:详细介绍
ans = max(ans, L + R + 1);是求出当前的路径长度,return max(L, R) + 1;求出左路径与右路径的最大值,是为了方便上面节点求出当前的路径长度。 这种递归类型的题目我总结的思路是自底层往上层去写

int depth(TreeNode* root){
        if (root == NULL) return 0;
        //先考虑最下层的空节点

        int L = depth(root->left);
        int R = depth(root->right);
        //考虑中间层的左边的深度以及右节点的深度

        ans = max(ans, L + R + 1);
        //上层的深度更新

        return max(L, R) + 1;
        //返回给更上一层的深度
        //底层->中间层->上层->更上层
    }

网友:+1 -1麻烦:原树上进行加

class Solution {
    int maxd=0;
    public int diameterOfBinaryTree(TreeNode root) {
        depth(root);
        return maxd;
    }
    public int depth(TreeNode node){
        if(node==null){
            return 0;
        }
        int Left = depth(node.left);
        int Right = depth(node.right);
        maxd=Math.max(Left+Right,maxd);//将每个节点最大直径(左子树深度+右子树深度)当前最大值比较并取大者
        return Math.max(Left,Right)+1;//返回节点深度
    }
}

617. 合并二叉树 23/4/22(值得看 ***)

给你两棵二叉树: root1 和 root2 。

想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。

返回合并后的二叉树。
在这里插入图片描述

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        if (t1 == nullptr) {
            return t2;
        }
        if (t2 == nullptr) {
            return t1;
        }
        auto merged = new TreeNode(t1->val + t2->val);
        merged->left = mergeTrees(t1->left, t2->left);
        merged->right = mergeTrees(t1->right, t2->right);
        return merged;
    }
};

方法一:网友的方法,原树上进行操作

class Solution:
    def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode:
        if not root1: return root2
        if not root2: return root1
        root1.val += root2.val
        root1.left = self.mergeTrees(root1.left,root2.left)
        root1.right = self.mergeTrees(root1.right,root2.right)
        return root1

方法二:广度优先,迭代

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        if (t1 == nullptr) {
            return t2;
        }
        if (t2 == nullptr) {
            return t1;
        }
        auto merged = new TreeNode(t1->val + t2->val);
        auto q = queue<TreeNode*>();
        auto queue1 = queue<TreeNode*>();
        auto queue2 = queue<TreeNode*>();
        q.push(merged);
        queue1.push(t1);
        queue2.push(t2);
        while (!queue1.empty() && !queue2.empty()) {
            auto node = q.front(), node1 = queue1.front(), node2 = queue2.front();
            q.pop();
            queue1.pop();
            queue2.pop();
            auto left1 = node1->left, left2 = node2->left, right1 = node1->right, right2 = node2->right;
            if (left1 != nullptr || left2 != nullptr) {
                if (left1 != nullptr && left2 != nullptr) {
                    auto left = new TreeNode(left1->val + left2->val);
                    node->left = left;
                    q.push(left);
                    queue1.push(left1);
                    queue2.push(left2);
                } else if (left1 != nullptr) {
                    node->left = left1;
                } else if (left2 != nullptr) {
                    node->left = left2;
                }
            }
            if (right1 != nullptr || right2 != nullptr) {
                if (right1 != nullptr && right2 != nullptr) {
                    auto right = new TreeNode(right1->val + right2->val);
                    node->right = right;
                    q.push(right);
                    queue1.push(right1);
                    queue2.push(right2);
                } else if (right1 != nullptr) {
                    node->right = right1;
                } else {
                    node->right = right2;
                }
            }
        }
        return merged;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值