代码随想录算法训练营第4天| 24. 两两交换链表中的节点 、 19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II

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

题目链接:Leetcode 24 两两交换链表中的节点

思想:其实找到每两个结点的操作步骤之后,就会发现这些步骤是循环的,其次,为了方便操作第一个节点,也要设置虚拟头节点。同时由于节点原来的next被更换后,原来指向的节点会被断开,所以要提前设置一个临时的指针指向原来的next节点。同时,如果交换之后如果只剩一个节点,那么这个节点就会被跳过。

代码:

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        // 实际交换两个点的操作上是循环的 只要一直交换就好了
        ListNode* cur = new ListNode;
        cur->next = head;
        ListNode* newhead = cur; // 新的头结点
        while (cur->next != nullptr && cur->next->next != nullptr) {
            ListNode* first = cur->next;
            ListNode* second = cur->next->next;

            cur->next = second;
            ListNode* temp = second->next;
            second->next=first;
            first->next = temp;

            cur = cur->next->next;
        }
        return newhead->next;
    }
};

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

题目链接:Leetcode 19 删除链表的倒数第N个节点

思路:找出这个数是正数第几个就可以了 之后找到他的前一个节点 使其next域指向下下个节点

同时为了避免头节点的的特殊处理,设置一个虚拟头节点

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        //首先先找到倒数第n个节点是正数第几个
        ListNode* newhead = new ListNode;//虚拟头节点
        newhead->next=head;
        ListNode* p = head;
        int size=0;//链表元素个数
        while(p != nullptr){
            size++;
            p=p->next;
        }
        int counter = size - n + 1;//计算该节点是正数第几个
        if(counter<=0||counter>size) return nullptr;
        p = newhead;
        //找到该节点的前一个节点
        for(int i=0;i<counter-1;i++){
            p=p->next;
        }
        p->next=p->next->next;
        return newhead->next;
    }
};

Leetcode 面试题 02.07 链表相交

题目链接:Leetcode 面试题 02.07 链表相交

思路:只要看结尾是不是同一个节点就可以判断有没有交点,同时得出两个链表的长度。求出两个链表的长度之差diff,让长的那个链表从diff往后遍历,短的那个从头往后遍历。现在这两个链表剩下未访问的节点数相同,令他们同时往后遍历,遇到的第一个相同节点就是答案。

难点:想出来怎么解决这个问题,其实看到时间复杂度可以是o(n)的时候可以想到应该是需要靠遍历。

代码:

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
     //只要看结尾是不是同一个节点就可以判断有没有交点
     //同时 得出两个链表的长度
     ListNode* p = headA;
     ListNode* q = headB;
     int lenA = 0,lenB = 0;
     while(p!=nullptr){
        p = p->next;
        lenA++;
     }
     //lenA++;//此时最后一个节点并没有被算进去所以再加一次
     while(q!=nullptr){
        q = q->next;
        lenB++;
     }
     //lenB++;//另一个同理
     //最后返回了就返回p和q之中的任意一个就可以
     //从短的那个链表的第一个节点开始看两个链表的节点是否相同
     //不相同则同时后移
     if(p==q){
        p = headA;
        q = headB;
        if(lenA<lenB){
            for(int i = 0;i<lenB-lenA;i++) q=q->next;
        } 
        else{
            for(int i =0;i<lenA-lenB;i++) p=p->next;
        }

        while(p!=q){
            p=p->next;
            q=q->next;
        }
        return p;
     }
     else return nullptr;   
    }
};

Leetcode 142 环形链表II 

题目链接:Leetcode 142 环形链表II 

思想:利用快慢指针确定是否有环。如果fast和slow两个指针能够相遇,则有环。

根据最后一行等式,可以发现 x的长度 等于 两个指针相遇的点到环的入口加(n-1)个环的长度

所以只需要在这两个点设置指针index和index1就可以,他们相遇的地方就是环的入口。

代码:

class Solution {
public:
    ListNode* detectCycle(ListNode* head) {
        // 先判断有没有环
        ListNode* fast = head;
        ListNode* slow = head;
        while (fast != nullptr && fast->next != nullptr) {
            fast = fast->next->next;
            slow = slow->next;
            if (slow == fast) {
                ListNode* index = head;
                ListNode* index1 = fast;
                while(index!=index1){
                    index = index->next;
                    index1 = index1->next;
                }
                return index;
            }
        }

        return nullptr;
    }
};

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值