代码随想录训练营第四天 | 题24、题19、面试题02.07、题142

1.交换链表节点 LeetCode 题 24

首先初始化虚拟头节点(一般链表题都要用到虚拟头节点),链表为偶次数节点则全部都要交换次序,奇数节点最后节点无需交换。每次交换两个节点,初始化cur指针,指向两个交换节点的再前一个节点。

交换示意图,黑箭头为原先链表顺序,红箭头为交换顺序,此处只演示第一组两节点交换:

在这里插入图片描述

代码随想录解法

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
        dummyHead->next = head; // 将虚拟头结点指向head,这样方面后面做删除操作
        ListNode* cur = dummyHead;
        while(cur->next != nullptr && cur->next->next != nullptr) {
            ListNode* tmp = cur->next; // 记录临时节点
            ListNode* tmp1 = cur->next->next->next; // 记录临时节点

            cur->next = cur->next->next;    // 步骤一
            cur->next->next = tmp;          // 步骤二
            cur->next->next->next = tmp1;   // 步骤三

            cur = cur->next->next; // cur移动两位,准备下一轮交换
        }
        return dummyHead->next;
    }
};

2.删除链表的倒数第N个节点 LeetCode 题19

题目:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

2.1自己解法:双指针法,初始化pre和cur为虚拟头节点,cur先移动n,若cur不为最后节点,pre再向前移动一位。若cur为最后节点,pre此时就处于待删除节点的前一个节点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *dummyhead =new ListNode();
        dummyhead->next = head;
        ListNode *cur = dummyhead;
        ListNode *pre = dummyhead;
        ListNode *lat = dummyhead;
        while(cur->next !=0){
            cur = pre;
            for(int i = 0; i < n; i++){
                cur = cur->next;
            }
            if(cur->next !=0){    //此处由于cur走到了最后一个,pre应该处在删除节点的前一个
                pre = pre->next;
            }
            
        } 
        ListNode *temp = pre->next;
        pre->next = pre->next->next;
        delete temp;
        return dummyhead->next;
    }
};

2.2代码随想录解法:思想一样

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* slow = dummyHead;
        ListNode* fast = dummyHead;
        while(n-- && fast != NULL) {
            fast = fast->next;
        }
        fast = fast->next; // fast再提前走一步,因为需要让slow指向删除节点的上一个节点
        while (fast != NULL) {
            fast = fast->next;
            slow = slow->next;
        }
        slow->next = slow->next->next; 
        
        // ListNode *tmp = slow->next;  C++释放内存的逻辑
        // slow->next = tmp->next;
        // delete nth;
        
        return dummyHead->next;
    }
};

3 链表相交 LeetCode 面试题02.07

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

https://programmercarl.com/%E9%9D%A2%E8%AF%95%E9%A2%9802.07.%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4.html#%E6%80%9D%E8%B7%AF

3.1 自己解法:暴力破解

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *cur1 = headA;
        ListNode *cur2 = headB;
        while(cur1 != NULL){
            //cout<<"0"<
            cur2 = headB;
            while(cur2 != NULL){
                if(cur2 == cur1){
                    return cur1;
                }
                cur2 = cur2 -> next;
            }
            cur1 = cur1 -> next;
            
        } 
        return 0;
    }
};

3.2 代码随想录 :求出A和B链表的长度,初始化cur1指向A的头节点,cur2初始化为B的头节点,cur1移动到A与B长度差值处,这样就能使得两个链表的指针末尾同时对准,这样就能一起移动指针到相等位置了。

时间复杂度O(n+m)

空间复杂度O(1)

代码随想录训练营第四天 | 题24、题19、面试题02.07、题142_第1张图片

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;
        int lenA = 0, lenB = 0;
        while (curA != NULL) { // 求链表A的长度
            lenA++;
            curA = curA->next;
        }
        while (curB != NULL) { // 求链表B的长度
            lenB++;
            curB = curB->next;
        }
        curA = headA;
        curB = headB;
        // 让curA为最长链表的头,lenA为其长度
        if (lenB > lenA) {
            swap (lenA, lenB);
            swap (curA, curB);
        }
        // 求长度差
        int gap = lenA - lenB;
        // 让curA和curB在同一起点上(末尾位置对齐)
        while (gap--) {
            curA = curA->next;
        }
        // 遍历curA 和 curB,遇到相同则直接返回
        while (curA != NULL) {
            if (curA == curB) {
                return curA;
            }
            curA = curA->next;
            curB = curB->next;
        }
        return NULL;
    }
};

4.环形链表 LeetCode 题142

题目给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。不允许修改 链表。

https://programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html#%E6%80%9D%E8%B7%AF

思路:定义快指针fast,定义慢指针slow,fast一次走两步,slow一次走一步。记下它们相遇的位置,此时从它们相遇的位置开始走与从头节点开始走就会相遇到环的起始点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast != NULL && fast->next != NULL) {
            slow = slow->next;
            fast = fast->next->next;
            // 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇
            if (slow == fast) {
                ListNode* index1 = fast;
                ListNode* index2 = head;
                while (index1 != index2) {
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index2; // 返回环的入口
            }
        }
        return NULL;
    }
};

你可能感兴趣的:(链表,leetcode,算法)