Leetcode ---- 链表简单题

复习了一下链表。下面做了一些简单题。

237. 删除链表中的元素

题目:

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

现有一个链表 -- 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.

说明:

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

思路:

这道题很巧妙,函数只给了一个结点。题目要求是删除该结点。那么我们只需要将上个结点的后继指向下一个结点。然而上一结点的信息我们并不知道。所以,我们只能将这一结点替代下一结点,下一结点没有结点指向。

程序:

/**
 * 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;
    }
};

203. 移除链表元素

题目:

删除链表中等于给定值 val 的所有节点。

示例:

输入: 1->2->6->3->4->5->6, val = 6
输出: 1->2->3->4->5

思路:

由于这是一个单链表,删除节点需要上一非目标节点指向该节点后续的非目标节点,因此,需要两个指针,指针一是只指向非目标节点的,而指针二是用来判断节点的。

程序:

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

83. 删除排序链表中的重复元素

题目:

给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。

示例 1:

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

示例 2:

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

思路:

这题思路比较简单,有序、不重复,直接判断当前值和下一值即可。

程序

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

876. 链表的中间结点

题目:

给定一个带有头结点 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

示例 1:

输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.

示例 2:

输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。

提示:

  • 给定链表的结点数介于 1 和 100 之间。

思路:

这道题求中点,很容易想到快慢指针,速度快一倍,当快指针指向NULL时,慢指针正好指向中点。

程序:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        ListNode *fast,*slow;
        fast = head;
        slow = head;
        while (fast != NULL && fast->next != NULL){
            slow = slow->next;
            fast = fast->next->next;
        }
        
        return slow;
    }
};

141. 环形链表

题目:

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

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

思路:

依题意,我们可知道,该环只能在链表末尾的,不可能在中间和首。那么,可以想象,当一个指针进入环后会无限循环下去。我们只需再放一个指针从头进入,且速度比第一个指针慢即可。它们最终会在环内相遇。若没环,则指针会指向NULL。

程序:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {  
        ListNode *fast,*slow;
        fast = head;
        slow = head;
          
        while (fast && fast->next){
            fast = fast->next->next;
            slow = slow->next;
            if (fast == slow){
                return true;
            }
        }
        return false;
        
/*        if (!head || !head->next)         // 判断是循环链表,理解错误
            return false;
        ListNode *p = head;
        while (p->next){
            if (p->next == head)
                return true;
            p = p->next;
        }
        return false;
*/        
        
    }
};

160. 相交链表

题目:

编写一个程序,找到两个单链表相交的起始节点。

例如,下面的两个链表

A:          a1 → a2
                   ↘
                     c1 → c2 → c3
                   ↗            
B:     b1 → b2 → b3

在节点 c1 开始相交。

注意:

  • 如果两个链表没有交点,返回 null.
  • 在返回结果后,两个链表仍须保持原有的结构。
  • 可假定整个链表结构中没有循环。
  • 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

思路:

这题有两个思路:

1. 得到两个链表的长度,然后删去长链表的头,使得两个链表相等。随后从头开始比对。

2. 若两链表长度不相等,则正常比对到NULL也不会得到相等的。然而,两个长度不一的链表各自加上对方,则会得到两个相等长度的链表。由此,我们可以 第一次遇到NULL的时候,转向另一条链表的头,若相交,必会在交点相遇。

程序:

/**
 * 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) {
        ListNode *p,*q;
        p = headA;
        q = headB;
        
        while (p != q){
            
            if (p == NULL){
                p = headB;
            }
            else{
                p = p->next;
            }
            
            if (q == NULL){
                q = headA;
            }
            else{
                q = q->next;
            }
        }
        return p;

      /*  int i = 0,j = 0;
        ListNode *p = headA,*q = headB;
        
        if (p == NULL || q == NULL)
            return NULL;
        
        while (p != NULL){
            p = p->next;
            i++;
        }
        while (q != NULL){
            q = q->next;
            j++;
        }
        
        int dis = i - j; 
        p = headA;
        q = headB;
        
        if (dis >= 0){
            while (dis != 0 && p != NULL){
                p = p->next;
                dis--;
            }
        }
        else{
            while (dis != 0 && q != NULL){
                q = q->next;
                dis++;
            }
        }
        while (p != NULL){
            if (p == q){
                return p;
            }
            p = p->next;
            q = q->next;
        }
        return NULL;*/
    }
};

21. 合并两个有序链表

题目:

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

示例:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

思路:

1.  直接创建一个新链表,比对两条链表,小的往里面放即可。

2. 递归

程序:

/**
 * 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 = new ListNode(-1);
        ListNode *p = head;
        if (l1 == NULL)
            return l2;
        if (l2 == NULL)
            return l1;
        
        while (l1 != NULL && l2 != NULL){
            if (l1->val < l2->val){
                p->next = l1;
                p = p->next;
                l1 = l1->next;
            }
            else{
                p->next = l2;
                p = p->next;
                l2 = l2->next;
            }
        }
        
        if (l1 == NULL && l2 != NULL){
            p->next = l2;
        }
        if (l2 == NULL && l1 != NULL){
            p->next = l1;
        }       
        return head->next;
        
        
        
/*        if (l1 == NULL)       // 递归
            return l2;
        if (l2 == NULL)
            return l1;
        
        if (l1->val < l2->val){
            l1->next = mergeTwoLists(l1->next,l2);
            return l1;
        }
        else{
            l2->next = mergeTwoLists(l2->next,l1);
            return l2;
        }*/

    }
};

206. 反转链表

题目:

反转一个单链表。

示例:

输入: 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||head->next == NULL){
            return head;
        }
        
        ListNode *ans = reverseList(head->next);
        head->next->next = head;
        head->next = NULL;
        return ans;     
        
/*        if (!head || !head->next)
            return head;
        
        ListNode *p = head;
        ListNode *tmp,*q;
        q = p->next;
        p->next = NULL;
        while (q){
            tmp = q->next;
            q->next = p;
            p = q;
            q = tmp;
        }
        return p;*/
    }
};

猜你喜欢

转载自blog.csdn.net/hc372893308/article/details/83474252