LeetCode 链表[L1]

2020-03-07  本文已影响0人  Tsukinousag

面试题18. 删除链表的节点

写法一:
因为有可能会删掉链表的head节点,为了避免讨论这种情况,引入一个头节点(-1),解决链表题目的常规操作了。

class Solution {
public:
    ListNode* deleteNode(ListNode* head, int val) {
        ListNode *p=new ListNode(-1);
        ListNode *cur=p;
        p->next=head;
        while(cur->next!=NULL)
        {
            if(cur->next->val==val)
            {
                cur->next=cur->next->next;
                deleteNode(cur->next,val);
                break;
            }
            cur=cur->next;
        }
        return p->next;
    }
};

写法二:
cur用于探测,让探测的先走

class Solution {
public:
    ListNode* deleteNode(ListNode* head, int val) {
        ListNode *pre=nullptr;
        ListNode *cur=head;
        while(cur&&cur->val!=val)
        {
            pre=cur;
            cur=cur->next;
        }
        if(cur==head) return cur->next;
        pre->next=cur->next;
        return head;
    }
};

876. 链表的中间结点

当用慢指针 slow 遍历列表时,让另一个指针 fast 的速度是它的两倍。
当 fast 到达列表的末尾时,slow 必然位于中间。

class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        ListNode* slow = head;
        ListNode* fast = head;
        while (fast != NULL && fast->next != NULL) {
            slow = slow->next;
            fast = fast->next->next;
        }
        return slow;
    }
};

时间复杂度:
O(N)。

空间复杂度:
O(1),slow 和 fast 用去的空间。


206.反转链表

不画图真的挺抽象的

翻转:将所有节点的next指针指向前驱节点。
由于是单链表,我们在迭代时不能直接找到前驱节点,所以我们需要一个额外的指针保存前驱节点。同时在改变当前节点的next指针前,不要忘记保存它的后继节点。

空间复杂度:
遍历时只有3个额外变量,所以额外的空间复杂度是 O(1)。

时间复杂度:
O(n)。

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode *pre=nullptr;
        ListNode *cur=head;
        while(cur)
        {
            ListNode *next=cur->next;
            cur->next=pre;
            pre=cur;
            cur=next;
        }
        return pre;
    }
};

reverseList 函数它可以翻转一个链表,并返回新链表的头节点,也就是原链表的尾节点。
所以我们可以先递归处理 reverseList(head->next),这样我们可以将以head->next为头节点的链表翻转,并得到原链表的尾节点tail,此时head->next是新链表的尾节点,我们令它的next指针指向head,并将head->next指向空即可将整个链表翻转,且新链表的头节点是tail。

空间复杂度:
总共递归 n 层,系统栈的空间复杂度是 O(n),所以总共需要额外 O(n) 的空间。

时间复杂度:
链表中每个节点只被遍历一次,所以时间复杂度是 O(n)。

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
      if(!head||!head->next) return head;
      ListNode *tail=reverseList(head->next);
      //找到尾巴后递归返回;
      head->next->next=head;
      head->next=nullptr;
      return tail
    }
};

相交链表

现代浪漫算法。。。。。

假设把两个链表长度合并,路程一样,速度一样,两个指针总会跑到一起。❤

具体的情况可以分析一下→


开始写的时候这样写,没有公共部分,就一直跑死循环了,所以我们设置最后一个NULL结点是为了保证让他俩一定能相遇
if(p1->next==NULL)
       p1=headB; 
else
       p1=p1->next;

空间复杂度: O(1)
时间复杂度为: O(n)

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(!headA||!headB)  return NULL;
        ListNode *p1=headA,*p2=headB;
         while (p1 != p2) {
        p1 = p1 == NULL ? headB : p1->next;
        p2 = p2 == NULL ? headA : p2->next;
       }
        return p1;
    }
};
上一篇下一篇

猜你喜欢

热点阅读