代码随想录Day4|24.两两交换链表中的节点|19.删除链表中的倒数第N个节点|面试题 02.07.链表相交|142.环形链表 ||

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

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

思路

        25题有一个通用的模板(出自讨论区的某位大神),可以直接套用在这道题中,具体来说就是先定义一个指向头部的指针p,并向链表后移2位,再将前面的链表进行反转。再使用递归函数不断进行反转链表,若最后剩余的没有反转的节点个数少于2个,则不进行操作。最后输出链表头结点即可。

代码

/**
 * 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* swapPairs(ListNode* head) {
        ListNode* p=head;
        for(int i=0;i<2;i++){
            if(p==NULL) return head;
            p=p->next;
        }
        ListNode* pre = NULL;
        ListNode* cur = head;
        while(cur!=p){
            ListNode* tmp=cur->next;
            cur->next=pre;
            pre=cur;
            cur=tmp; 
        }
        head->next = swapPairs(p);
        return pre;
    }
};

时间复杂度:O(n)

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

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

思路

        暴力一点的想法就是先使用一个指针从头到尾遍历,计算链表长度len,然后创建一个新指针,并移动len-n-1步,使其位于删除元素之前,然后进行删除操作就行了。

        也可以使用双指针,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。

代码

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* virtualhead = new ListNode(0,head);
        ListNode* fastindex=virtualhead;
        ListNode* slowindex=virtualhead;
        while(n--)
        fastindex=fastindex->next;
        while(fastindex->next!=NULL){
            fastindex=fastindex->next;
            slowindex=slowindex->next;
        }
        ListNode* tmp=slowindex->next;
        slowindex->next=slowindex->next->next;
        delete tmp;
        return virtualhead->next;
    }
};

  时间复杂度:O(n)

面试题 02.07. 链表相交

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

思路

        用哈希表存储链表A中的所有节点,再对链表B进行遍历,并每次查询B的节点是否在哈希表中,若存在,则相交,并返回相交节点。若不存在,则返回空节点。

代码

        

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        unordered_set set;
        ListNode* cur=headA;
        while(cur!=NULL){
            set.insert(cur);
            cur=cur->next;  
        }
        ListNode* curr=headB;
        while(curr!=NULL){
            if(set.find(curr)!=set.end())  //发现相交元素
                return curr;
            curr=curr->next;
        }
        return NULL;  //没找到,返回空集
    }
};

时间复杂度:O(m+n),m,n分别为链表A和链表B的长度。

142. 环形链表 II

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

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

不允许修改 链表。

思路

        跟上题有些相似,使用哈希表来遍历存储链表中的节点,当出现重复节点时,说明到达了环的头部节点,输出第一个重复节点即可,若不存在重复结点,则输出空值。

代码

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* cur=head;
        unordered_set  set;
        while(cur){
            if(!set.count(cur)){
                set.insert(cur);
            }
            else return cur;
            cur=cur->next;
        }
        return NULL;
    }
};

时间复杂度:O(n)

        

你可能感兴趣的:(算法题练习,链表,算法)