力扣链表题型

删除链表

 //使用虚拟结点
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
         //头部添加虚拟结点
         ListNode *resHead = new ListNode(-1,head);
         ListNode *p= resHead;
         while(p->next)
         {
             if(p->next->val  == val)
             {
                 p->next = p -> next ->next;
             }
             else
             {
                 p = p ->next;
             }          
         }
 		return resHead->next;
    }
};

返回链表中间结点

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

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

/**
 * 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) {

        //第一种解法   将链表遍历,放入vector数组中,取中间结点
        vector<ListNode*> A = {head};
        while(A.back()->next)
        {
            A.push_back(A.back()->next);
        }
        return A[A.size()/2];


        //第二种解法   遍历两次,第一次为获得结点数,第二次为取中间结点
        int num = 0;
        ListNode *cur = head;
        while(cur)
        {
            num++;
            cur = cur->next;
        }
        int k = 0;
        ListNode *cur2 = head;
        while(k<num/2)
        {
            ++k;
            cur2 = cur2 -> next;  
        }
        return cur2;

        //第三种解法   快慢指针 遍历,快一些的走两步,慢一些的走一步
        ListNode* slow = head;
        ListNode *fast = head;

        while(fast && fast->next)
        {
            slow  = slow -> next;
            fast = fast -> next -> next;
        }
            return slow;
    }
};

反转链表

反转一个单链表

/**
 * 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) {}
 * };
 */
 //利用一个新空间,遍历取出当前结点,利用头插法,接续到新链表head之后
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode *res = new ListNode();
        ListNode *cur = head;

        while(cur)
        {
            ListNode *temp = cur;
            cur = cur -> next;

            temp->next = res->next;
            res->next = temp;
        }
        return res->next;

    }
};

//迭代解法
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* curr = head;
        while (curr) {
            ListNode* next = curr->next;
            curr->next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
};

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-by-leetcode-solution-d1k2/


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

存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除所有重复的元素,使每个元素 只出现一次 。

返回同样按升序排列的结果链表

/**
 * 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* deleteDuplicates(ListNode* head) {
        if(!head) return head;
        ListNode *l1 = head;
       
    while(l1->next)
    {
        if (l1->val != l1->next-> val)
        {
            l1= l1->next;
        }
        else 
        {
            l1->next = l1->next->next;           
        }
    }

    return head;    

    }
};

移除未排序链表中的重复元素

移除未排序链表中的重复节点,保留最开始出现的结点

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeDuplicateNodes(ListNode* head) {
        //第一种解法 :利用两次循环  , 时间复杂度 O(N)

        ListNode *p = head;
        while(p){
            ListNode *q = p;
            while(q->next)
            {
                  if(p->val == q->next->val)
                  {
                      q->next = q->next->next;
                  }  
                  else
                  {
                      q = q->next;
                  }
            }
            p = p->next;
        }

        return head;


        //第二种解法  利用哈希表,unordered_set ,时间复杂度O(N2)
        if(head == nullptr) return head;

        unordered_set<int> occured = {head->val};

        ListNode* pos = head;
        //枚举前驱结点
        while(pos->next)
        {
            //当前待删除结点
            ListNode *cur = pos->next;
            if(!occured.count(cur->val))
            {
                occured.insert(cur->val);
                pos = pos -> next;
            }
            else
            {
                pos->next = cur -> next;
            }
        }

        //pos -> next = nullptr;
        return head;
    }
};

合并两个有序链表

将两个升序链表合并为一个新的升序链表并返回,新链表是通过拼接给定的两个链表的所有节点组成的
迭代解法

/**
 * 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* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode *head = new ListNode();
        ListNode *tail = head;

        while(l1 != nullptr && l2!= nullptr)
        {
            if (l1->val > l2->val)
            {
                tail->next = l2;
                l2 = l2->next;
            }
            else
            {  
                tail->next = l1;
                l1 = l1->next;
            }
            tail = tail -> next;
        }

        if(l1 !=nullptr) tail->next = l1;
        if(l2 !=nullptr) tail->next =l2;

        return head->next;
    }
};

递归解法

class solution{
public:
    ListNode* mergeTwoLists(ListNode *l1, ListNode *l2){
        if(l1 == nullptr)
        {
            return l2;
        }
        else if(l2 == nullptr){
			return l1;            
        }
        else if(l1->val < l2->val){
            l1->next = mergeTwoLists(l1->next,l2);
        	return l1;
        }
        else
        {
            l2->next = mergeTwoLists(l2->next,l1);
            return l2;
        }
    }
    
}

两链表对应位置相加

官方原题解释

//参考官方解法,个人写的思路
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *pre = new ListNode();
        ListNode *p =pre;

        int m = 0;
        int val;
        
        while(l1 || l2)  //遍历完两个链表
        {
            
           ListNode *cur = new ListNode();

           int n1 = l1 ? l1->val : 0;   //l1非空,取值l1->val ,否则取值为 0
           int n2 = l2 ? l2->val : 0;

            val = n1 + n2 + m;
            if(m ==1 ) m = 0;
            if (val > 9)
            {
                m = 1;
                val = val -10;
            }

            cur->val = val ;
            pre->next = cur;
            pre = cur;

            if(l1)l1 = l1->next;
            if(l2)l2 = l2->next;
        }

        if(m==1)   //当l1,l2均到链表末尾时,仍有进位产生即m==1,此时再新建结点接续
        {
            ListNode *q = new ListNode(1);
            pre->next = q ;
        }

        return p->next;
    }
};

//官方解法
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *head = nullptr, *tail = nullptr;
        int carry = 0;
        while (l1 || l2) {
            int n1 = l1 ? l1->val: 0;
            int n2 = l2 ? l2->val: 0;
            int sum = n1 + n2 + carry;
            if (!head) {
                head = tail = new ListNode(sum % 10);
            } else {
                tail->next = new ListNode(sum % 10);
                tail = tail->next;
            }
            carry = sum / 10;
            if (l1) {
                l1 = l1->next;
            }
            if (l2) {
                l2 = l2->next;
            }
        }
        if (carry > 0) {
            tail->next = new ListNode(carry);
        }
        return head;
    }
};
链接:https://leetcode-cn.com/problems/add-two-numbers/solution/liang-shu-xiang-jia-by-leetcode-solution/

回文链表

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
 //利用栈 后进先出 的特性来存储结点,并比较原链表与栈内链表结点val值是否相等
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        ListNode *p  = head;
        stack<ListNode >  *s  = new stack<ListNode>;
        int elem;
        while(p!= nullptr)
        {
            s->push(*p);
            p = p->next;
        }

        while(head!=nullptr)
        {
            elem = s->top().val;     //取栈顶元素,取val值
            s->pop();                  //出栈
            if  (head->val != elem)
                return false;

            head = head ->next;
        }

        return true;
    }
};

** 力扣官方解答**
1.取值复制到数组中,比较前后是否相等

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        vector<int> vals;
        while (head != nullptr) {
            vals.emplace_back(head->val);
            head = head->next;
        }
        for (int i = 0, j = (int)vals.size() - 1; i < j; ++i, --j) {
            if (vals[i] != vals[j]) {
                return false;
            }
        }
        return true;
    }
};

总的时间复杂度:O(2n) = O(n)O(2n)=O(n)。

2.整个流程可以分为以下五个步骤:
找到前半部分链表的尾节点。
反转后半部分链表。
判断是否回文。
恢复链表。
返回结果。

跳转链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值