LeetCode/链表操作综合

1. 两数相加

两数相加(尾插法)
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *head = nullptr, *tail = nullptr;
        int carry = 0;
        while (l1 || l2) {
            int n1 = l1 ? l1->val: 0;//有值取值、没值赋0
            int n2 = l2 ? l2->val: 0;
            int sum = n1 + n2 + carry;//当前位和
            if (!head) {
                head = tail = new ListNode(sum % 10);//头指针初始化
            } else {
                tail->next = new ListNode(sum % 10);
                tail = tail->next;
            }
            carry = sum / 10;
            if (l1) {
                l1 = l1->next;
            }
            if (l2) {
                l2 = l2->next;
            }
        }
        if(carry) tail->next = new ListNode(carry);

        return head;
    }
};

2. 删除链表的倒数第N位

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        //删除倒数第n个节点,前一节点要指向倒数n+1
        ListNode* p1 =head;
        ListNode* p2 =head;
        for(int i=0;i<n;i++) p2=p2->next;
        if(!p2) return head->next;//对于第一个点被删除的处理,也可以设一个头结点统一所有操作
        while(p2->next){
            p1=p1->next;
            p2=p2->next;
        }
        p1->next=p1->next->next;
        return head;
    }
};

2. 合并两个有序链表

//合并k个可以采用二分合并、顺序合并
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* preHead = new ListNode(-1);
        //一定要使用头指针并复制一个副本,不然后面循环操作不统一,未合并完的也不好加上去
        ListNode* prev = preHead;
        while (l1&&l2) {
            if (l1->val < l2->val) {
                prev->next = l1;//链入pre
                l1 = l1->next;//指针后移
            } else {
                prev->next = l2;
                l2 = l2->next;
            }
            prev = prev->next;//pre指针后移
        }
        // 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
        prev->next = l1 == nullptr ? l2 : l1;

        return preHead->next;
    }
//也可以使用递归
};

3. 反转链表

//递归(从后往前进行尾插)
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (!head || !head->next) 
            return head;//返回初始为空的节点以及单个节点
        ListNode* newHead = reverseList(head->next);
        head->next->next = head;//head->next变成了尾结点,将head放在尾结点后
        head->next = nullptr;
        return newHead;
    }
};
//头插法
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode*pre= new ListNode();
        ListNode*node= head;
        while(head!=NULL){
            head=head->next;
            node->next=pre->next;
            pre->next=node;
            node = head;
        }
        return pre->next;
    }
};

4. 反转链表搬砖操作

5. 判断回文链表(递归)

//另一种做法快慢指针,再反转链表
public:
    bool recursivelyCheck(ListNode* currentNode) {
        if (currentNode != nullptr) {
            if (!recursivelyCheck(currentNode->next)) //递归到最右,同时承接返回判断
                return false;
            if (currentNode->val != frontPointer->val) //从右往左出递归,如果不等返回假
                return false;
            frontPointer = frontPointer->next;//全局指针右移
        }
        return true;
    }

    bool isPalindrome(ListNode* head) {
        frontPointer = head;
        return recursivelyCheck(head);
    }
};

6. 相交链表

//跑到终点后互换位置,要么最后相交、要么都为NULL
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;
    }
};

7. 排序链表

posted @ 2022-05-14 19:59  失控D大白兔  阅读(44)  评论(0编辑  收藏  举报