代码随想录训练营第三天|lc24两两交换链表中的节点 , lc19 删除链表的倒数第N个节点 , lc142 环形链表II, lc面试题02.07. 链表相交。拓展题:lc977 有序数组的平方

LC 24 两两交换链表中的节点

24. 两两交换链表中的节点 - 力扣(LeetCode)

1.递归法
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        //递归的终止条件,如果进行到链表为空或者链表只剩一个元素,则停止递归
        if (head == nullptr || head->next == nullptr) return head;


        ListNode *Next = head->next;

        //递归处理所有节点
        head->next = swapPairs(Next->next);

        //Next交换到了head前面
        Next->next = head;
        return Next;
    }
};
2.模拟法(虚拟头节点)
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode *virtualHead = new ListNode(0);//虚拟头节点
        virtualHead->next = head;//为了便于操作,虚拟头节点要设置在head之前
        ListNode *cur = virtualHead;
        while (cur->next != nullptr && cur->next->next != nullptr) {
            ListNode *temp1 = cur->next;
            ListNode *temp2 = cur->next->next->next;
            cur->next = cur->next->next;
            cur->next->next = temp1;
            cur->next->next->next = temp2;
            cur = cur->next->next;
        }
        ListNode *res = virtualHead->next;
        delete virtualHead;
        return res;
    }
};

个人觉得,递归法更好理解一些。虚拟头节点需要自己画图,才直观。

LC 19 删除链表的倒数第N个节点

1.虚拟头节点

这一题的虚拟头节点,快慢指针,比较好理解,也可以将倒数第n个转换为正数再去做。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        //双指针,先建立虚拟节点指向头节点,定义快慢指针指向虚拟节点
        //快指针先走n+1步
        //快慢指针同时走,直到快指针走到末尾,此时慢指针指向倒数第n个节点的上一个节点,删除其next
        ListNode *virtualHead = new ListNode(0);
        virtualHead->next = head;
        ListNode* r = virtualHead;
        ListNode* l = virtualHead;
        
        //快指针先走n + 1步
        while ( n != 0 && r->next != nullptr) {
            r = r->next;
            n -= 1;
        }
        r = r->next;
        while (r != nullptr) {
            r = r->next;
            l = l->next;
        }
        l->next = l->next->next;

        return virtualHead->next;
    }
};
2.将要删除的位置换算为整数第几个

同样,更直观的方法。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        //转换为正数第几个
        if (head == nullptr) return head;

        //求出链表有几个元素
        int listSize = 0;
        ListNode *pos = head;
        while (pos != nullptr) {
            pos = pos->next;
            listSize++;
        }
        if (n > listSize) return head;
        
        //将倒数第几个的位置,转化为正数第几个
        int deletePos = listSize - n;
        if (deletePos == 0) return head->next;
        ListNode *cur = head;
        int i = 0;
        //走到该位置的前一个元素
        while (i < deletePos - 1) {
            cur = cur->next;
            i++;
        }
        ListNode *temp = cur->next;
        cur->next = temp->next;
        delete temp;
        return head;

    }
};

LC 面试题02.07. 链表相交

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int sizeA = 0;
        int sizeB = 0;
        ListNode *curA = headA;
        ListNode *curB = headB;
        while (curA != nullptr) {
            sizeA++;
            curA = curA->next;
        }
        while (curB != nullptr) {
            sizeB++;
            curB = curB->next;
        }

        //重置curA和curB
        curA = headA;
        curB = headB; 

        //保证sizeA更大
        if (sizeB > sizeA) {
            swap(sizeA, sizeB);
            swap(curA, curB);
        }
        int gap = sizeA - sizeB;
        //对齐
        while (gap--) {
            curA = curA->next;
        }
        while(curA != nullptr) {
            if (curA == curB) return curA;
            curA = curA->next;
            curB = curB->next;
        }
        return nullptr;

    }
};

LC 142 环形链表II

使用哈希表,暴力解。会更容易想到。
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        unordered_set<ListNode*> st;
        while (head != nullptr) {
            if (st.count(head)) return head;
            st.insert(head);
            head = head->next;
        }
        return nullptr;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值