LeetCode 单链表专题 (一)

LeetCode 单链表专题 <c++>

\([2]\) Add Two Numbers

模拟,注意最后判断进位是否为1。
时间复杂度 \(O(n)\)

class Solution {
public:
    ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
        ListNode ans(-1);
        int carry = 0;
        auto p1 = l1, p2 = l2;
        auto p = &ans;
        while (p1 != nullptr || p2 != nullptr) {
            int val1, val2;
            if (p1 == nullptr) { val1 = 0; }
            else {
                val1 = p1->val;
                p1 = p1->next;
            }
            if (p2 == nullptr) { val2 = 0; }
            else {
                val2 = p2->val;
                p2 = p2->next;
            }
            int sum = (val1 + val2 + carry) % 10;
            carry = (val1 + val2 + carry) / 10;
            p = p->next = new ListNode(sum);
        }
        if(carry) p->next = new ListNode(carry);
        return ans.next;
    }
};

\([92]\) Reverse Linked List II

给定链表,翻转第m个结点到第n个结点。
从第m+1个结点开始,在第m-1个结点之后的位置用头插法插入新结点,可以避免使用栈。
时间复杂度 \(O(n)\)

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        ListNode res(-1);
        auto p = head, p_res = &res;
        for(int i = 1; i <= m-1; i++){
            p_res = p_res->next = new ListNode(p->val); // new list next node
            p = p->next; // origin list next node
        }
        auto prev = p_res;
        p_res = p_res->next = new ListNode(p->val);
        auto last = p_res; 
        p = p->next;
        for(int i = m+1; i <= n; i++){
            prev->next = new ListNode(p->val);
            prev->next->next = p_res;
            p_res = prev->next;
            p = p->next;
        }
        last->next = p;
        return res.next;
    }
};

\([86]\) Partition List

链表拼接。
时间复杂度 \(O(n)\)
(c++)搞清楚了实体用.,指针用->调用属性和方法。
(c++)new 构造方法(参数)返回的是同类型指针。

class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        ListNode dummy_l(-1);
        ListNode dummy_r(-1);
        auto dummy_l_p = &dummy_l, dummy_r_p = &dummy_r;
        for(auto p = head; p; p = p->next){
            if(p->val<x){
                dummy_l_p = dummy_l_p->next = p;
            } 
            else {
                dummy_r_p = dummy_r_p->next = p;
            }
        }
        dummy_l_p->next = dummy_r.next;
        dummy_r_p->next = nullptr;
        return dummy_l.next;
    }  
};

\([82]\) Remove Duplicates from Sorted List II

如果有元素重复出现,删掉该元素及其复制。
时间复杂度 \(O(n)\)

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        ListNode dummy(-1);
        auto prev = &dummy;
        bool flag = false;
        for(auto p = head; p; p = p->next){
            while(p->next!=nullptr && p->next->val == p->val){
                p->next = p->next->next;
                flag = true;
            }
            if(flag){
                flag = false;
                prev->next = p->next;
            }
            else prev = prev->next = p;
        }
        return dummy.next;
    }
};

\([61]\) Rotate List

先遍历求出长度length。k可能大于等于length,所以对length取模。从length-k处断开原链表,断开处为新链表头结点,原头结点接到原尾结点后面。
时间复杂度 \(O(n)\)

class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(head == nullptr) return head;
        int length = 1;
        auto cur = head;
        for(; cur->next; cur = cur->next) length++;
        k = k % length;
        if(k == 0) return head;
        ListNode dummy(-1);
        dummy.next = head;
        auto cut = &dummy;
        for(int i = 0; i<length - k; i++) cut = cut->next;
        dummy.next = cut->next;
        cur->next = head;
        cut->next = nullptr; // 记得断开,避免形成环,会TLE。
        return dummy.next;
    }
};

\([19]\) Remove Nth Node From End of List

删掉链表倒数第n个结点,要求只遍历一遍。
两个指针p,q。一个先走n步,然后两个一起走。
时间复杂度 \(O(n)\)

/**
 * Status: Accepted
 * Runtime: 12 ms
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode dummy(-1);
        dummy.next = head;
        auto p = &dummy, q = &dummy;
        int cnt = 0;
        while(p!=nullptr) {
            if(cnt>n) q = q->next;
            p = p->next;
            cnt++;
        }
        q->next = q->next->next;
        return dummy.next;
    }
};

这份代码跑了12ms。因为循环中有判断语句。
下面是优化后的代码

/**
 * Status: Accepted
 * Runtime: 8 ms
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode dummy(-1);
        dummy.next = head;
        auto p = &dummy, q = &dummy;
        for(int i = 0; i<=n; i++) p = p->next;
        while(p!=nullptr) {
            q = q->next;
            p = p->next;
        }
        auto tmp = q->next;
        q->next = q->next->next;
        delete tmp;
        return dummy.next;
    }
};
posted @ 2019-02-23 00:42  NeilThang  阅读(161)  评论(0编辑  收藏  举报