链表的OJ题---(C++)

链表的题目

  • 206 反转链表
  • 876链表的中间结点
  • 22链表中倒数第K个结点
  • 21合并2个有序链表
  • 牛客CM11 链表分割

206 反转链表

题目链接:https://leetcode-cn.com/problems/reverse-linked-list/

链表的OJ题---(C++)_第1张图片

思路一:双指针解决

定义1个prev的前驱指针,cur来工作指针,next来保存cur的下一个,如果不保存cur的下一个,cur指向prev后则找不到cur的next了。当cur走到空时循环结束。注意返回头结点,结束时头结点是prev
如下图:
链表的OJ题---(C++)_第2张图片
代码如下:

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
    //定义1个前驱指针
     ListNode* prev = nullptr;
     ListNode* cur = head;
     while(cur)
     {
         ListNode* next = cur->next;
         //修改链接关系
         cur->next = prev; 
         //继续迭代往下走        
         prev = cur;
         cur = next;
     }
     //最后的头是prev
     return prev;
    }
};
     

链表的OJ题---(C++)_第3张图片
ok,就过了。时间复杂度即是链表的长度为O(N)。

思路二:头插法

设定义1个newhead为头指针,next保存cur的下一个,依次拿下头插,在更新头接节点即可。
链表的OJ题---(C++)_第4张图片
代码如下:

class Solution {
public:
    ListNode* reverseList(ListNode* head) {      
    ListNode* newhead = nullptr;
    ListNode* cur = head;
     while(cur)
     {
         ListNode* next = cur->next;
         //取下来头插
         cur->next = newhead;
         //更新头结点
         newhead = cur;
         cur = next;         
     }
     return newhead;
    }
};

链表的OJ题---(C++)_第5张图片
也过了,时间复杂度是O(N)。

876链表的中间结点

题目链接:https://leetcode-cn.com/problems/middle-of-the-linked-list/description/

链表的OJ题---(C++)_第6张图片
分析:快慢指针解决问题,slow走1步,fast走2步,当结点个数为奇数个,循环结束条件是fast的next为空,当结点个数为偶数个,fast走到空就结束了,总结循环结束的条件为fast且fast的next不为空
链表的OJ题---(C++)_第7张图片
代码如下:

class Solution {
public:
    ListNode* middleNode(ListNode* head) {
     ListNode* slow,*fast = head;
     while(fast && fast->next)
     {
         //慢的走1步,快的走2步
         slow=slow->next;
         fast=fast->next->next;
     }
     //最后返回慢的就是中间结点
     return slow;
    }
};

链表的OJ题---(C++)_第8张图片
就过了,时间复杂度为O(N),遍历了一遍链表。

22链表中倒数第K个结点

题目链接:https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/

链表的OJ题---(C++)_第9张图片
思路跟上面的找中间结点是一样的,快的先走K步,注意的细节是:当K大于链表的长度,fast会空指针的问题。
链表的OJ题---(C++)_第10张图片
代码如下;

class Solution {
public:
    ListNode* getKthFromEnd(ListNode* head, int k) {
        ListNode *slow = head;
        ListNode  *fast = head;
        //快的先走k步,在同时一起走
        while(k--)
        {
             if(fast == nullptr)
                 return nullptr;
            fast = fast->next;
        }
        while(fast)
        {
            slow = slow->next;
            fast = fast->next;
        }
        return slow;
    }
};

链表的OJ题---(C++)_第11张图片
时间复杂度:走链表的长度,O(N)。

21合并2个有序链表

题目链接:https://leetcode-cn.com/problems/merge-two-sorted-lists/submissions/

链表的OJ题---(C++)_第12张图片
思路:用1个带哨兵卫的来解决,比较2个链表结点的值,将小的拿下来尾插即可。
链表的OJ题---(C++)_第13张图片
tail要记录尾结点来尾插,当2个结点的值一样的随便拿哪个下来尾插都行,当其中1个链表有1个走完就将没走完全部链在后面,因为它是有序的。当其中1个链表为空,就返回另一个链表。
代码如下:
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
//当2个链表其中1个为空的情况
if(list1 == nullptr)
return list2;
if(list2 == nullptr)
return list1;
//用带哨兵卫的头结点尾插解决
ListNode* newnode=new ListNode(0);
ListNode* l1 = list1;
ListNode* l2 = list2;
//定义tail来记录尾指针
ListNode* tail = newnode;
//当有1个链表走完,循环就结束
while(l1 && l2)
{
//比较2个链表的结点值的大小
//小的拿下去尾插
if(l1->val <= l2->val)
{
tail->next = l1;
tail = l1;
l1 = l1->next;
}
else
{
tail->next = l2;
tail = l2;
l2 = l2->next;
}
}
//当2个链表中有1个走完就将剩下的全链接起来
if(l1)
tail->next = l1;
if(l2)
tail->next = l2;
//记得释放哨兵卫的头
//先记录头的下一个,在释放
ListNode* head = newnode->next;
delete(newnode);
return head;
}
};

链表的OJ题---(C++)_第14张图片
时间复杂度为O(m+n),m和n为2个链表的长度

牛客CM11 链表分割

题目链接:https://www.nowcoder.com/practice/0e27e0b064de4eacac178676ef9c9d70?tpId=8&&tqId=11004&rp=2&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking

链表的OJ题---(C++)_第15张图片

牛客的题目给的条件有点少,题目要求不能改变原来的数据顺序。思路:根据上一题的经验用带哨兵卫头结点来解决。

链表的OJ题---(C++)_第16张图片
搞2个哨兵卫,cur比x的值小就尾插到1个的后面,大的尾插到另一个哨兵后,当cur走到空时,最后less链接在graterTail的后面。
代码如下:

class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here
     //开2个哨兵卫的头结点
     ListNode* lessHead = new ListNode(0);
     ListNode* graterHead = new ListNode(0);
     ListNode* cur = pHead;
     //定义2个指针分别指向头结点
     ListNode* lessTail = lessHead;
     ListNode* gratertail = graterHead;
     while(cur)
     {
         //小的尾插到小的后面
         if(cur->val < x)
         {
             lessTail->next = cur;
             lessTail = cur;
         }
          //大的尾插到大的后面
         else
         {
             gratertail->next = cur;
             gratertail = cur;
         }
        cur = cur->next;
     }
     //分别先保存头的下一个结点,在释放哨兵卫的头
     lessTail->next = graterHead->next;
     ListNode* first = lessHead->next;
     delete(graterHead);
     delete(lessHead);
     //左后返回小的
     return first;
    }
};

提交看看:
在这里插入图片描述
他说内存不够用,我们只是开了2个结点而已。看下图:

链表的OJ题---(C++)_第17张图片
我们只是拿下来尾插,没有动结点的next,此时20的next还是指向的9,此时链表代码进入死循环了,所以要将 大的尾结点的next置空
链表的OJ题---(C++)_第18张图片

就过了。
链表的OJ题---(C++)_第19张图片
时间复杂度为O(N)。

你可能感兴趣的:(#,LeetCode链表的题,链表,c++,数据结构)