代码随想录算法训练营第四天|24,19,面试02.27,142

24两两交换链表中的节点

注意使用虚拟头节点,操作接待你在前一位

注意保存指针

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* Head=new ListNode(0);
        Head->next=head;
        ListNode* cur=Head;
        while(cur->next!=nullptr&&cur->next->next!=nullptr)//注意顺续,cur->next==nullptr时cur->next->next越界违法
        {
            ListNode* temp1=cur->next;
            ListNode* temp2=cur->next->next;
            cur->next=temp2;
            temp1->next=temp2->next;
            temp2->next=temp1;
            cur=cur->next->next;
        }
        return Head->next;
    }
};

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

虚拟头节点

双指针,先走n+1(操作节点)

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *Head=new ListNode(0);
        Head->next=head;
        ListNode* temp1=Head;
        ListNode* temp2=Head;
        while(n--&&temp1!=nullptr)
        {
            temp1=temp1->next;
        }
        temp1=temp1->next;
        while(temp1!=nullptr){
            temp1=temp1->next;
            temp2=temp2->next;
        }
        temp2->next=temp2->next->next;
        return Head->next;
    }
};

面试题 02.07. 链表相交

数值相同不一定指针相同

  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;
    }
};
  1. 双指针从两头遍历,到头跳到另一个链表继续,若有交集则遍历一次必然相遇在交点位置,若没有则不相交

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;

    }
};
  1. hash

/**
 * 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) {
        unordered_set<ListNode *> visited;
        ListNode *temp = headA;
        while (temp != nullptr) {
            visited.insert(temp);
            temp = temp->next;
        }
        temp = headB;
        while (temp != nullptr) {
            if (visited.count(temp)) {
                return temp;
            }
            temp = temp->next;
        }
        return nullptr;
    }
};

142.环形链表II

  1. 快慢指针相遇即可证明有环

  1. 从开始和相遇处同时移动,相遇即为入口

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) {//x=z
                ListNode* index1 = fast;
                ListNode* index2 = head;
                while (index1 != index2) {
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index2; // 返回环的入口
            }
        }
        return NULL;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值