leetcode 链表(删除节点、反转、合并、回文、环形)

删除链表中的节点

请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。

现有一个链表 -- head = [4,5,1,9],它可以表示为:

    4 -> 5 -> 1 -> 9

示例 1:

输入: head = [4,5,1,9], node = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.

示例 2:

输入: head = [4,5,1,9], node = 1
输出: [4,5,9]
解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.

说明:

  • 链表至少包含两个节点。
  • 链表中所有节点的值都是唯一的。
  • 给定的节点为非末尾节点并且一定是链表中的一个有效节点。
  • 不要从你的函数中返回任何结果。

 这道题只给了一个节点,没有前驱,如何删除该节点元素?

解题方法很巧妙:

把要删除的节点,用该节点后面的节点的内容覆盖,然后删掉后面的那个节点。

如ABCDEFG,删除D,我们先用E占D的位置,变成ABCEEFG,然后把后面的E删除。

代码如下

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        ListNode* p = node->next;
        node->val=p->val;
        node->next = p->next;
        delete p;
    }
};

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

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

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5.

说明:

给定的 n 保证是有效的。

进阶:

你能尝试使用一趟扫描实现吗?

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* p1 = head;
        ListNode* p2 = head;
        ListNode* p ;
        if(head->next == NULL && n==1){
            delete head;
            return NULL;
        }
        
        for(int i=0;i<n;i++){
                p2=p2->next;
        }
        if(p2==NULL){
               p=head;
                head = head->next;
                delete p;
                return head;
        }
        while(p2->next!=NULL){
            p1=p1->next;
            p2=p2->next;
        }
       p=p1->next;
        p1->next = p->next;
        delete p;      
        
        return head;
    }
};

 反转链表

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

 迭代法:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head==NULL)return head;
        ListNode* prev=NULL,* p=head,* temp = head->next;
        while(temp!=NULL){
            p->next = prev;
            prev = p;
            p=temp;
            temp=temp->next;
        }
        p->next=prev;
        return p;

    }
};

合并两个有序链表

将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

示例:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode*head,*p;
        head = new ListNode(0);
        p=head;
        while(l1!=NULL&&l2!=NULL){
            if(l1->val<l2->val){
               p->next = l1;
                p=l1;
                l1=l1->next;
            }
            else{
                p->next = l2;
                p=l2;
                l2 = l2->next;
            }
            
        }
        if(l1!=NULL) p->next = l1;
        if(l2!=NULL) p->next =l2;
        return head->next;
        
    }
};

回文链表

请判断一个链表是否为回文链表。

示例 1:

输入: 1->2
输出: false

示例 2:

输入: 1->2->2->1
输出: true

进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

 思路:反转后半部分链表再比较

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
   ListNode* reverseList(ListNode* head) {
        if(head==NULL)return head;
        ListNode* prev = NULL,*p = head,*tmp = head->next;
        while(tmp!=NULL){
            p->next =prev;
            prev = p;
            p=tmp;
            tmp = tmp->next;           
        }
        p->next =prev;        
        return p;  
    }
    bool isPalindrome(ListNode* head) {
        if(head==NULL)return true;
        ListNode * l=head,* r=head;
        ListNode * m = head;
        while(r->next!=NULL){
            r=r->next;
            if(r->next!=NULL){
                r=r->next;
                m = m->next;
            }
        }
        m= m->next;
        m=reverseList(m);
        while(m!=NULL){
            if(m->val!=l->val)
                return false;
            m=m->next;
            l=l->next;
        }
        return true;
        
    }
};

 环形链表

给定一个链表,判断链表中是否有环。

进阶:
你能否不使用额外空间解决此题?

 思路:快慢指针即可,快指针每次走两步,慢指针每次走一步。快指针追上慢指针,则表示有环。

class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head==NULL||head->next==NULL)return false;
        ListNode * fast = head, *slow = head;
        while(fast!=NULL){
            fast = fast->next;
            if(fast){
                slow = slow->next;
                fast = fast->next;
            } 
            if(fast == slow){
                return true;
            }
                
        }
        return false;
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_41582705/article/details/81448053
今日推荐