leetcode--linked list

reference

linked list 题解

intro

很多链表问题可以用递归来处理。marked by (*)
这是刷题的初期可能还要复习下

1. 找交点

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *l1 = headA, *l2 = headB;
    //while two ptrs doesn't meet    
    while (l1 != l2) {
    	
        l1 = (l1) ? l1->next: headB;
        l2 = (l2) ? l2->next: headA;
    }
    return l1;
    }
};

要求时间复杂度为 O(N),空间复杂度为 O(1)。如果不存在交点则返回 null。

设 A 的长度为 a + c,B 的长度为 b + c,其中 c 为尾部公共部分长度,可知 a + c + b = b + c + a。

当访问 A 链表的指针访问到链表尾部时,令它从链表 B 的头部开始访问链表 B;同样地,当访问 B 链表的指针访问到链表尾部时,令它从链表 A 的头部开始访问链表 A。这样就能控制访问 A 和 B 两个链表的指针能同时访问到交点

如果不存在交点,那么 a + b = b + a,以下实现代码中 l1 和 l2 会同时为 null,从而退出循环。

2. Reverse Linked List(*)

用递归的思路

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head == NULL || head->next == NULL){
            return head;
        }
        
        ListNode* oldheadnext = head -> next;
        ListNode* newhead = reverseList(oldheadnext);
        //this is important, link the oldheadnext to original head
        oldheadnext -> next = head;
        //now head is the last entry
        head -> next = NULL;
        
        return newhead;
        
    }
};

3. Merge Two Sorted Lists(*)

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if(!l1){return l2;}
        if(!l2){return l1;}
        
        if(l1->val < l2-> val){
            l1->next = mergeTwoLists(l1->next, l2);
            //this is key, as this recursion works in list one
            //it must have been finished before leveing this if
            return l1;
        }
        else{
            l2->next = mergeTwoLists(l2->next, l1);
            return l2;
        }
    }
};

4. delete duplicates(*)

用了C的语法和递归的思路

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if(head == NULL || head->next==NULL){
            return head;
        }
        
        head->next = deleteDuplicates(head->next);
        return head->val == head->next->val ? head->next : head;
        
    }
};

5. Remove Nth Node From End of List

使用快慢指针,一次遍历即可实现(!效率依然不高,有更优解)

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyhead = new ListNode(0);
        dummyhead->next = head;
        
        ListNode* fast = dummyhead;
        ListNode* slow = dummyhead;
        while(n-- >= 0){
            fast = fast->next;
            //slow stay at head, now fast and slow are n apart
        }
        
        while(fast){
            fast = fast -> next;
            slow = slow -> next;
            //push fast to the end, now slow's next is to be deleted
        }
        
        ListNode* tmp = slow->next;
        slow->next = tmp->next;
        delete tmp;
        
        head = dummyhead -> next;
        delete dummyhead;
        
        return head;
    }
};

更优解

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        
    ListNode* fast = head;
    while (n-- > 0) {
            fast = fast->next;
        }
        //this is key, this means the list is shorter than n 
        //so the head should be removed
        if (fast == NULL) return head->next;
        ListNode* slow = head;
        while (fast->next) {
            fast = fast->next;
            slow = slow->next;
        }
        ListNode* tmp = slow->next;
        slow->next = slow->next->next;
        delete tmp;
        
        return head;
    }
};

6. Swap Nodes in Pairs(*)

用递归的思路,两两一组
时间复杂度:O(N),其中 N 指的是链表的节点数量
*空间复杂度:O(N), 递归过程使用的堆栈空间

递归法:

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode * first, * second;
        if(head == NULL || head->next == NULL){
            return head;
        }
        first = head;
        second = head->next;
        first->next = swapPairs(second->next);
        second->next=first;
        
        return second;
    }
};

迭代法:
时间复杂度:O(N),其中 N 指的是链表的节点数量
空间复杂度:O(1)

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
    ListNode* dummy = new ListNode(0);
    dummy->next = head;

    ListNode* prevNode = dummy;

    while (head && head->next) {
        // Nodes to be swapped
        ListNode* firstNode = head;
        ListNode* secondNode = head->next;
        // Swapping
        prevNode->next = secondNode;  // 放到交换前后都可以
        firstNode->next = secondNode->next;
        secondNode->next = firstNode;
        // Reinitializing the head and prevNode for next swap
        prevNode = firstNode;
        head = firstNode->next;
    }
    return dummy->next;
    }
};

7. add two linked list

! better solution exists

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *node1 = reverseListNode(l1);
        ListNode *node2 = reverseListNode(l2);
        return reverseListNode(add(node1,node2));
        
    }
    
private: 
    ListNode* reverseListNode(ListNode* head){
    if(head == NULL) return NULL;
    ListNode* prev = NULL;
    while (head != NULL) {
        ListNode* next = head->next;
        head->next = prev;
        prev = head;
        head = next;
    }
    return prev;
}
    
    //两条链表中的各个节点数字相加
    ListNode* add(ListNode* l1, ListNode* l2){
    if (l1 == NULL && l2 == NULL) return NULL;
    ListNode* dummy = new ListNode(0);
    ListNode* temp = dummy;
    int addOne = 0;
    while (l1 || l2 || addOne != 0) {
        int val1 = !l1 ? 0 : l1->val;
        int val2 = !l2 ? 0 : l2->val;
        int sum = val1 + val2 + addOne;
        temp->next = new ListNode(sum%10);
        temp = temp->next;
        addOne = sum / 10;
        if (l1) l1 = l1->next;
        if (l2) l2 = l2->next;
    }
    temp = dummy->next;
    delete dummy;
    return temp;
}
};

8. 检测回文

注意这里reverse的使用和实现

class Solution {
public:
    bool isPalindrome(ListNode* head) {
    if (head == NULL || head->next == NULL) return true;
    ListNode* slow = head, *fast = head->next;
    while (fast && fast->next ) {
        slow = slow->next;
        fast = fast->next->next;
    }
    if (fast){
        ListNode* tmp = slow;
        slow = slow->next;
        tmp->next = NULL;
    }  // 偶数节点,让 slow 指向下一个节点
    return isEqual(head, reverse(slow));   
    }
private: 
    ListNode* reverse(ListNode* head) {
    ListNode* newHead = NULL;
    while (head) {
        ListNode* nextNode = head->next;
        head->next = newHead;
        newHead = head;
        head = nextNode;
    }
    return newHead;
}

     bool isEqual(ListNode* l1, ListNode* l2) {
        while (l1 && l2) {
        if (l1->val != l2->val) return false;
        l1 = l1->next;
        l2 = l2->next;
    }
    return true;
}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值