当前位置:   article > 正文

链表的基本操作 及力扣典型题型_力扣单链表的基础操作

力扣单链表的基础操作

一、链表基础

链表的类型有三种:单链表、双链表、循环链表

单链表:

双链表

循环链表: 

 链表与数组的对比:

二、链表结构体的定义

  1. //初始化列表形式
  2. struct ListNode{
  3. int value;
  4. ListNode *next;
  5. ListNode(int v,ListNode *node):value(v),next(node){}
  6. ListNode(int v):value(v),next(nullptr){}
  7. ListNode():value(0),next(nullptr){}
  8. };

三、创建一个链表

  1. //创建链表方式1
  2. ListNode *head=nullptr;
  3. for(int i=0;i<5;i++){
  4. head=new ListNode(i,head);
  5. }
  6. ListNode *dummy=new ListNode(0,head);//哑指针
  7. //创建链表方式2
  8. ListNode *head1=new ListNode(1,new ListNode(2,new ListNode(3,nullptr)));
  9. ListNode *dummy1=new ListNode(0,head);//哑指针

四、链表遍历

  1. void print(){
  2. ListNode* cur=dummy;
  3. while(cur->next){
  4. cout<<cur->next->value<<endl;
  5. cur=cur->next;
  6. }
  7. cout<<endl;
  8. }

五、链表其他基本操作(插入、删除、检索)

  1. class MyLinkedList {
  2. public:
  3. struct ListNode{
  4. int val;
  5. ListNode* next;
  6. ListNode(int v,ListNode* node):val(v),next(node){}
  7. ListNode(int v):val(v),next(nullptr){}
  8. ListNode():val(0),next(nullptr){}
  9. };
  10. ListNode* dummy; //哑节点
  11. int size; //链表大小
  12. MyLinkedList() {
  13. dummy=new ListNode(0);
  14. size=0;
  15. }
  16. //获取第index个位置链表的值
  17. int get(int index) {
  18. if(index>=size || index<0) return -1;
  19. ListNode* head=dummy->next;
  20. for(int i=0;i<index;i++){
  21. head=head->next;
  22. }
  23. return head->val;
  24. }
  25. //在链表头插入一个节点
  26. void addAtHead(int val) {
  27. ListNode* head=new ListNode(val,dummy->next);
  28. dummy->next=head;
  29. size++;
  30. }
  31. //在链表尾插入一个节点
  32. void addAtTail(int val) {
  33. ListNode* tail=new ListNode(val);
  34. ListNode* head=dummy;
  35. while(head->next){
  36. head=head->next;
  37. }
  38. head->next=tail;
  39. size++;
  40. }
  41. //在链表第index个位置前插入一个节点
  42. void addAtIndex(int index, int val) {
  43. if(index>size) return;
  44. if(index<0) addAtHead(val);
  45. else if(index==size) addAtTail(val);
  46. else {
  47. ListNode* head=dummy;
  48. for(int i=0;i<index;i++){
  49. head=head->next;
  50. }
  51. ListNode* newnode=new ListNode(val,head->next);
  52. head->next=newnode;
  53. size++;
  54. }
  55. }
  56. //删除链表第index个位置的节点
  57. void deleteAtIndex(int index) {
  58. if(index<0 || index>=size) return;
  59. ListNode* head=dummy;
  60. for(int i=0;i<index;i++){
  61. head=head->next;
  62. }
  63. ListNode* del=head->next;
  64. head->next=head->next->next;
  65. delete del;
  66. size--;
  67. }
  68. };

六、力扣典型链表题

206. 反转链表

  1. //双指针法
  2. class Solution {
  3. public:
  4. ListNode* reverseList(ListNode* head) {
  5. ListNode*pre=nullptr;
  6. ListNode*cur=head;
  7. while(cur){
  8. struct ListNode* next=cur->next;
  9. cur->next=pre;
  10. pre=cur;
  11. cur=next;
  12. }
  13. return pre;
  14. }
  15. };
  16. //递归法
  17. class Solution {
  18. public:
  19. ListNode* reverse(ListNode* pre,ListNode* cur){
  20. if(!cur) return pre;
  21. ListNode* next=cur->next;
  22. cur->next=pre;
  23. return reverse(cur,next);
  24. }
  25. ListNode* reverseList(ListNode* head) {
  26. return reverse(nullptr,head);
  27. }
  28. };

142. 环形链表 II

  1. //哈希表
  2. class Solution {
  3. public:
  4. ListNode *detectCycle(ListNode *head) {
  5. unordered_set<ListNode*> hashmap;
  6. while(head){
  7. if(hashmap.count(head)) //如果哈希表中有这个节点,说明为环的入口节点
  8. return head;
  9. hashmap.emplace(head);
  10. head=head->next;
  11. }
  12. return NULL;
  13. }
  14. };
  15. //双指针法
  16. class Solution {
  17. public:
  18. ListNode *detectCycle(ListNode *head) {
  19. ListNode* slow=head;
  20. ListNode* fast=head;
  21. while(fast && fast->next){
  22. slow=slow->next;
  23. fast=fast->next->next;
  24. if(slow==fast){ //快慢指针相遇
  25. ListNode* circlenode=fast;
  26. ListNode* cur=head; //从head开始往前走,与circlenode相遇位置就是环的入口
  27. while(cur!=circlenode){
  28. cur=cur->next;
  29. circlenode=circlenode->next;
  30. }
  31. return cur;
  32. }
  33. }
  34. return NULL;
  35. }
  36. };

19. 删除链表的倒数第 N 个结点

  1. class Solution {
  2. public:
  3. ListNode* removeNthFromEnd(ListNode* head, int n) {
  4. ListNode *dummy=new ListNode(0,head);
  5. ListNode *fast=head; //注意这快慢指针的设定
  6. ListNode *slow=dummy;
  7. for(int i=0;i<n;i++){
  8. fast=fast->next;
  9. }
  10. while(fast){
  11. fast=fast->next;
  12. slow=slow->next;
  13. }
  14. ListNode *del=slow->next;
  15. slow->next=slow->next->next;
  16. delete del;//要在改变链表结构之后删除
  17. return dummy->next;
  18. }
  19. };

23. 合并K个升序链表

  1. class Solution {
  2. public:
  3. ListNode* mergetwo(ListNode* l1,ListNode* l2){
  4. ListNode* merged=new ListNode(0);
  5. ListNode* head=merged;
  6. while(l1&&l2){
  7. if(l1->val<l2->val){
  8. merged->next=l1;
  9. l1=l1->next;
  10. }
  11. else {
  12. merged->next=l2;
  13. l2=l2->next;
  14. }
  15. merged=merged->next;
  16. }
  17. merged->next=(l1?l1:l2);
  18. return head->next;
  19. }
  20. ListNode* mergeKLists(vector<ListNode*>& lists) {
  21. ListNode* result=new ListNode(INT_MIN); //注意INT_MIN,因为有负数
  22. for(int i=0;i<lists.size();i++){
  23. result=mergetwo(result,lists[i]);
  24. }
  25. return result->next;
  26. }
  27. };

148. 排序链表

  1. class Solution {
  2. public:
  3. //链表排序一般使用归并排序
  4. ListNode* sortList(ListNode* head) {
  5. return sortList(head,nullptr);
  6. }
  7. ListNode* sortList(ListNode* head,ListNode* tail){
  8. if(head==nullptr){ //注意!!
  9. return head;
  10. }
  11. if(head->next==tail){ //注意!!
  12. head->next=nullptr;
  13. return head;
  14. }
  15. ListNode* slow=head;
  16. ListNode* fast=head;//注意这快慢指针的写法!!
  17. while(fast!=tail){
  18. slow=slow->next;
  19. fast=fast->next;
  20. if(fast!=tail) fast=fast->next;
  21. }
  22. ListNode* mid=slow;
  23. return merged(sortList(head,mid),sortList(mid,tail));
  24. }
  25. ListNode* merged(ListNode* l1,ListNode* l2){
  26. ListNode* merged=new ListNode(0);
  27. ListNode* dummy=merged;
  28. while(l1&&l2){
  29. if(l1->val<l2->val){
  30. merged->next=l1;
  31. l1=l1->next;
  32. }
  33. else{
  34. merged->next=l2;
  35. l2=l2->next;
  36. }
  37. merged=merged->next;
  38. }
  39. merged->next=(l1?l1:l2);
  40. return dummy->next;
  41. }
  42. };

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/438954
推荐阅读
相关标签
  

闽ICP备14008679号