Leetcode 链表部分简单题汇总

本文汇总了LeetCode中关于链表的几道简单题目,包括回文链表判断、删除倒数第n个节点、合并有序链表、检查环、删除重复元素、删除指定值节点、链表反转及成对交换节点等。每道题目都提供了解题思路。
摘要由CSDN通过智能技术生成

1. 回文链表的判断

给定一个链表,判断是否为回文链表,我的思路是利用快慢指针先找到链表的中间节点,然后将中间节点之后的部分反转,再将反转的部分和前半部分比较

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        //如果链表是空或者链表只有一个元素则必然为回文链表
        if(!head || !head->next)
            return true;
        //快慢指针法,寻找链表中心
        ListNode* slow = head;
        ListNode* fast = head;
        while(fast && fast->next){
            slow = slow->next;
            fast = fast->next->next;
        }
        //链表元素为奇数个
        if(fast){
            slow->next = reverseList(slow->next);
            slow = slow->next;
        }
        else{
            slow = reverseList(slow);
        }
        while(slow){
            if(slow->val != head->val)
                return false;
            slow = slow->next;
            head = head->next;
        }
        return true;
    }

    ListNode* reverseList(ListNode* head){
        ListNode* first, *reverse;
        first = head;
        reverse = NULL;
        while(first){
            ListNode* second = first->next;
            first->next = reverse;
            reverse = first;
            first = second;
        }
        return reverse;
    }
};

2. 删除链表的倒数第n个节点

思路,同样也是利用两个快慢指针,快指针先走n步,当快指针走到链表末尾时(fast == NULL),慢指针就指向了要删除的那个节点。注意需要一个pre指针保存慢指针的前一个节点

class Solution{
    public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* slow = head;
        ListNode* fast = head;
        ListNode* pPre = NULL;
        for(int i = 0; i < n; i++){
            if(fast == NULL)
                return head;
            fast = fast->next;
        }
        while(fast){
            pPre = slow;
            slow = slow->next;
            fast = fast->next;
        }
        //n == length of linkedlist
        if(pPre == NULL){
            head = slow->next;
            delete slow;
        }
        else{
            pPre->next = slow->next;
            delete slow;
        }
        return head;
    }
};

3. 合并两个有序的链表

/**
 * 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) {
           if (l1 == NULL)
      {
          return l2;
      }
      if (l2 == NULL) 
      {
          return l1;
      }
        ListNode* ip1 = l1;
        ListNode* ip2 = l2;
        ListNode* newHead = (l1->val < l2->val ? l1 : l2);
        if(l1->val < l2->val){
            ip1=ip1->next;
        }
        else{
            ip2=ip2->next;
        }
        ListNode* iHead = newHead;
        int i = 1;
        while(ip1 && ip2){
            iHead->next = (ip1->val < ip2->val ? ip1 : ip2);
            if(i == 1){
                newHead = iHead; //更新头部
            }
            if(ip1->val < ip2->val){
                ip1=ip1->next;
            }
            else{
               ip2=ip2->next;
            }  
            iHead = iHead->next;
            i++;
        }
        //将剩余部分添加到新的链表
        if(ip1){
            iHead->next = ip1;
            ip1 = ip1->next;
            iHead = iHead->next;
        }
        else{
            iHead->next = ip2;
            ip2 = ip2->next;
            iHead = iHead->next; 
        }
        return newHead;
    }
};

4.判断链表是否有环

快慢指针,若快指针能够遇到慢指针,说明链表有环

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

5. 在有序链表中删除重复的元素

因为是有序链表,所以只要比较前后两个节点的值就行了。

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
       ListNode* first = head;
       if(head == NULL || head->next == NULL)
           return head;
        while(first && first->next){
            ListNode* next1 = first->next;
            if(next1->val == first->val){
                first->next = next1->next;
                delete next1;
            }
            else first = first->next;
        }
        return head;
    }
 };

6.删除链表元素

题意是说给定一个值,删除链表中所有值为给定值的节点,这个题目的技巧在于给这个链表多加一个头节点,从这个头结点开始遍历查找删除

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
       ListNode* preHead = new ListNode(0);
       preHead->next = head;
       ListNode* p = preHead;
       while(p && p->next){
           ListNode* q = p->next;
           if(q->val == val){
               p->next = q->next;
               delete q;
           }
           else p = p->next;
       }
       return preHead->next;
    }
 };

7.链表反转

反转一个链表,这个问题其实不算简单,但是由于网上关于这个问题的解答是在太多了,而且估计很多面试笔试什么的也已经把这个问题问烂了,所以这个问题显得有些俗套了,但还是值得去仔细研究的。

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* first = head;
        ListNode* reverse = NULL;
        while(first){
            ListNode* second = first->next;
            first->next = reverse;
            reverse = first;
            first = second;
        }
        return reverse;

    }
};

8.成对交换链表节点

[1,2,3,4]交换后[2,1,4,3]。要求时间为线性,空间为常数,有两种方法,一种就是规规矩矩破坏链表结构交换节点,另一种就是不破坏链表结构,交换元素值

第一种方法

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head == NULL || head->next == NULL)
            return head;
        ListNode* dummy = new ListNode(-1);
        dummy->next = head;
        ListNode* prev = head;
        ListNode* cur = head->next;
        while(true){
            int t = prev->val;
            prev->val = cur->val;
            cur->val = t;
            prev = prev->next->next;
            if(prev == NULL) break;
            cur = cur->next->next;
            if(cur == NULL) break;
        }
        return dummy->next;
    }


};

第二种方法:

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head == NULL || head->next == NULL)
            return head;
        ListNode* dummy = new ListNode(-1);
        dummy->next = head;
        ListNode* prev = head;
        ListNode* cur = head->next;
        while(true){
            int t = prev->val;
            prev->val = cur->val;
            cur->val = t;
            prev = prev->next->next;
            if(prev == NULL) break;
            cur = cur->next->next;
            if(cur == NULL) break;
        }
        return dummy->next;
    }


};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值