[Leetcode] 116, 129, 23

本文解决三道经典算法题目:填充每个节点的下一个右侧节点指针、求根到叶路径数字之和及合并K个有序链表。通过递归与迭代方法展示不同思路,提供多种实现方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

116. Populating Next Right Pointers in Each Node

Given a binary tree

    struct TreeLinkNode {
      TreeLinkNode *left;
      TreeLinkNode *right;
      TreeLinkNode *next;
    }

Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.

Initially, all next pointers are set to NULL.

Note:

  • You may only use constant extra space.
  • You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children).

For example,
Given the following perfect binary tree,

         1
       /  \
      2    3
     / \  / \
    4  5  6  7

After calling your function, the tree should look like:

         1 -> NULL
       /  \
      2 -> 3 -> NULL
     / \  / \
    4->5->6->7 -> NULL

Solution: 递归,注意题目中已经限定了是perfect binary tree ,因此不需要讨论很多种情况

Code:

/**
 * Definition for binary tree with next pointer.
 * struct TreeLinkNode {
 *  int val;
 *  TreeLinkNode *left, *right, *next;
 *  TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {}
 * };
 */
class Solution {
public:
    void connect(TreeLinkNode *root) {
        connect(root, NULL);
    }
private:
    void connect(TreeLinkNode *root, TreeLinkNode *next){
        if(root==NULL) return;
        
        root->next = next;
        
        connect(root->left, root->right);
        connect(root->right, next!=NULL?next->left:NULL);
    }
};



129. Sum Root to Leaf Numbers

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.

An example is the root-to-leaf path 1->2->3 which represents the number 123.

Find the total sum of all root-to-leaf numbers.

For example,

    1
   / \
  2   3

The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.

Return the sum = 12 + 13 = 25.

Solution: 树的递归。

Code:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int sumNumbers(TreeNode* root) {
        sumNumbers(root, 0);
        return sum;
    }
private:
    int sum = 0;
    void sumNumbers(TreeNode* root, int cur){
        if(root==NULL) return;
        cur = cur*10 + root->val;
        if(root->left==NULL && root->right==NULL){
            sum += cur;
        }else{
            sumNumbers(root->left, cur);
            sumNumbers(root->right, cur);
        }
        cur = cur/10;
    }
};


23. Merge k Sorted Lists

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

Solution(1): 直接做,时间复杂度为O(kn),k是数组list的长度,n是待排序的数的总数,当k比较大的时候,无法等同于O(n),Leetcode上会超时。 

Code:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode dummy(INT_MAX);
        ListNode* cur = &dummy;
        int mini = -1;
        int k = 20;
        while(1){
            mini = -1;
            for(int i=0; i<lists.size(); i++){
                if(lists[i]!=NULL){
                    if(mini < 0){
                        mini = i;
                    }else if(lists[i]->val<lists[mini]->val){
                        mini = i;
                    }
                }
                
            }
            if(mini<0) break;
            cur->next = lists[mini];
            cur = cur->next;
            lists[mini] = lists[mini]->next;//注意要修改lists数组中的值,不能直接提取指针然后修改
        }
        return dummy.next;
    }
};

Solution(2): 两个两个的merge,直到将所有的链表都merge到一起,时间复杂度大约是O((nk)/2),Leetcode运行时间222ms,因为leetcode给的时间限制不严格,这样做也可以过。复用Merge Two Sorted Lists的函数。

Code:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode* start = NULL;
        for(int i=0; i<lists.size(); i++){
            start = mergeTwoLists(start, lists[i]);
        }
        return start;
    }
private:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if(l1==NULL) return l2;
        else if(l2==NULL) return l1;
        
        ListNode* start = NULL;
        if(l1->val < l2->val){
            start = l1;
            l1 = l1->next;
        }else{
            start = l2;
            l2 = l2->next;
        }
        
        ListNode* cur = start;
        while(l1!=NULL && l2!=NULL){
            if(l1->val < l2->val){
                cur->next = l1;
                l1 = l1->next;
            }else{
                cur->next = l2;
                l2 = l2->next;
            }
            cur = cur->next;
        }
        if(l1!=NULL) cur->next = l1;
        else if(l2!=NULL) cur->next = l2;
        
        return start;
    }
};

Solution(3): 将上面的做法加以改进,使用分治法,可以得到O(nlogn)的解法,Leetcode运行时间26ms。

Code:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        return mergeKLists(lists.begin(), lists.end());
    }
private:
    ListNode* mergeKLists(vector<ListNode*>::iterator itbegin, vector<ListNode*>::iterator itend){
        if(itbegin>=itend) return NULL;
        if((itend-itbegin)==1) return *itbegin;
        if((itend-itbegin)==2) return mergeTwoLists(*itbegin, *(itbegin+1));
        
        auto mid = itbegin + (itend-itbegin)/2;
        return mergeTwoLists(mergeKLists(itbegin, mid),mergeKLists(mid, itend));
    }
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {}//同上,我就不写了
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值