LeetCode 实践练习21-25

LeetCode—21(合并两个有序链表)

在这里插入图片描述方法一:新建一个链表,然后比较两个链表中的元素值,把较小的那个链到新链表中,由于两个输入链表的长度可能不同,所有最终会有一个链表先完成插入所有的元素,则直接另一个未完成的链表直接链入新链表的末尾。

C++解法:

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode *dummy = new ListNode(-1),*cur = dummy;
        while(l1 && l2){
            if (l1->val < l2->val){
                cur->next = l1;
                l1 = l1->next;
            }else{
                cur->next = l2;
                l2 = l2->next;
            }
            cur = cur->next;
        }
        cur->next = l1 ? l1 : l2;
        return dummy->next;
    }
};

方法二:递归的思想。核心还是比较当前两个节点值大小,如果l1的小,那么对于l1的下一个节点和l2调用递归函数,将返回值赋值给l1.next,然后返回l1;否则就对于l2的下一个节点和l1调用递归函数,将返回值赋值给l2.next,然后返回l2。
代码:

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if (!l1 || (l2 && l1->val > l2->val)) swap(l1, l2);
        if (l1) l1->next = mergeTwoLists(l1->next, l2);
        return l1;
    }
};

LeetCode—22(括号生成)

LeetCode 实践练习21-25_第1张图片
方法一:递归思想Recursion解,定义两个变量left与right分别表示剩下的左右括号的个数。如果在某次递归时,左括号的个数大于右括号的个数,说明此时生成的字符串中右括号的个数大于左括号的个数,这样会出现 ‘)(’ 此时直接返回,不继续处理。若left与right都为0,且都合法,存入结果。如果以上两种都不满足,此时left大于0,调用递归函数,right同理。注意更新参数。
C++代码:

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<string> res;
        generateParenthesisDFS(n, n, "", res);
        return res;
    }
    void generateParenthesisDFS(int left, int right, string out, vector<string> &res) {
        if (left > right) return;
        if (left == 0 && right == 0) res.push_back(out);
        else {
            if (left > 0) generateParenthesisDFS(left - 1, right, out + '(', res);
            if (right > 0) generateParenthesisDFS(left, right - 1, out + ')', res);
        }
    }
};

方法二:
LeetCode 实践练习21-25_第2张图片

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        set<string> t;
        if (n == 0) t.insert("");
        else {
            vector<string> pre = generateParenthesis(n - 1);
            for (auto a : pre) {
                for (int i = 0; i < a.size(); ++i) {
                    if (a[i] == '(') {
                        a.insert(a.begin() + i + 1, '(');
                        a.insert(a.begin() + i + 2, ')');
                        t.insert(a);
                        a.erase(a.begin() + i + 1, a.begin() + i + 3);
                    }
                }
                t.insert("()" + a);
            }
        }
        return vector<string>(t.begin(), t.end());
    }
};

LeetCode—23(合并K个排序链表)

LeetCode 实践练习21-25_第3张图片
方法一:利用到了混合排序的思想,也属于分治法的一种,做法是将原链表分成两段,然后对每段调用递归函数,suppose返回的left和right已经合并好了,然后再对left和right进行合并,合并的方法就使用之前那道 Merge Two Sorted Lists 中的任意一个解法即可,这里我们使用了递归的写法。

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        return helper(lists,0,(int)lists.size() - 1);
    }
    ListNode* helper(vector<ListNode*>& lists,int start,int end){
        if(start > end) return NULL;
        if(start == end) return lists[start];
        int mid = start + (end - start)/2;
        ListNode *left = helper(lists,start,mid);
        ListNode *right = helper(lists,mid + 1,end);
        return mergeTwoLists(left,right);
    }
    ListNode* mergeTwoLists(ListNode* l1 ,ListNode* l2){
        if (!l1 || (l2 && l1->val > l2->val)) swap(l1, l2);
        if (l1) l1->next = mergeTwoLists(l1->next, l2);
        return l1;
    }
};

另外解法(读懂):

ListNode *mergeKLists(vector<ListNode *> &lists) {
    if(lists.empty()){
        return nullptr;
    }
    while(lists.size() > 1){
        lists.push_back(mergeTwoLists(lists[0], lists[1]));
        lists.erase(lists.begin());
        lists.erase(lists.begin());
    }
    return lists.front();
}
ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
    if(l1 == nullptr){
        return l2;
    }
    if(l2 == nullptr){
        return l1;
    }
    if(l1->val <= l2->val){
        l1->next = mergeTwoLists(l1->next, l2);
        return l1;
    }
    else{
        l2->next = mergeTwoLists(l1, l2->next);
        return l2;
    }
}

LeetCode—24(两两交换链表中的节点)

LeetCode 实践练习21-25_第4张图片
方法一:迭代的方法
代码:

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode *dummy = new ListNode(-1), *pre = dummy;
        dummy->next = head;
        while (pre->next && pre->next->next) {
            ListNode *t = pre->next->next;
            pre->next->next = t->next;
            t->next = pre->next;
            pre->next = t;
            pre = t->next;
        }
        return dummy->next;
    }
};

方法二:递归的方法
代码:

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

LeetCode—25(k个一组翻转链表)

方法一:需要两个函数,一个用来分段,一个用来翻转的。一般在处理链表问题时,我们大多时候会在开头再加一个dummy node,因为翻转链表时头结点可能会变化,为了记录当前头结点的位置而引入dummy node。
LeetCode 实践练习21-25_第5张图片
注意翻转之后新的cur和pre的位置都不同了,那么翻转之后,cur应该更新为pre->next,而如果不需要翻转的话,cur更新为cur->next。
C++代码:

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        if (!head || k == 1) return head;
        ListNode *dummy = new ListNode(-1), *pre = dummy, *cur = head;
        dummy->next = head;
        for (int i = 1; cur; ++i) {
            if (i % k == 0) {
                pre = reverseOneGroup(pre, cur->next);
                cur = pre->next;
            } else {
                cur = cur->next;
            }
        }
        return dummy->next;
    }
    ListNode* reverseOneGroup(ListNode* pre, ListNode* next) {
        ListNode *last = pre->next, *cur = last->next;
        while(cur != next) {
            last->next = cur->next;
            cur->next = pre->next;
            pre->next = cur;
            cur = last->next;
        }
        return last;
    }
};

方法二:使用递归来做,我们用head记录每段的开始位置,cur记录结束位置的下一个节点,然后我们调用reverse函数来将这段翻转,然后得到一个new_head,原来的head就变成了末尾,这时候后面接上递归调用下一段得到的新节点,返回new_head即可。
代码:

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode *cur = head;
        for (int i = 0; i < k; ++i) {
            if (!cur) return head;
            cur = cur->next;
        }
        ListNode *new_head = reverse(head, cur);
        head->next = reverseKGroup(cur, k);
        return new_head;
    }
    ListNode* reverse(ListNode* head, ListNode* tail) {
        ListNode *pre = tail;
        while (head != tail) {
            ListNode *t = head->next;
            head->next = pre;
            pre = head;
            head = t;
        }
        return pre;
    }
};

你可能感兴趣的:(刷题大法)