• LeetCode 热题100——链表专题(一)


    一、俩数相加

    2.俩数相加(题目链接)

    思路:这题题目首先要看懂,以示例1为例  即  342+465=807,而产生的新链表为7->0->8.

    可以看成简单的从左向右,低位到高位的加法运算,4+6=10,逢10进1,新链表第三位为3+4+1(第二位进的1),需要注意的的点是当9->9->9和9->9->9->9相加,相当于9->9->9->0和9->9->9->9相加

    代码实现:

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * struct ListNode *next;
    6. * };
    7. */
    8. typedef struct ListNode ListNode;
    9. ListNode * ListBuyNode(int x)
    10. {
    11. ListNode * node=(ListNode*)malloc(sizeof(ListNode));
    12. if(node==NULL)
    13. {
    14. perror("malloc fail:");
    15. return NULL;
    16. }
    17. node->val=x;
    18. node->next=NULL;
    19. return node;
    20. }
    21. struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
    22. int ret=0;
    23. ListNode *head=(ListNode*)malloc(sizeof(ListNode));//带头单链表
    24. ListNode*pcur=head;
    25. while(l1||l2||ret)
    26. {
    27. if(l1)
    28. {
    29. ret=ret+l1->val;
    30. }
    31. if(l2)
    32. {
    33. ret=ret+l2->val;
    34. }
    35. ListNode *node=ListBuyNode(ret%10);
    36. pcur->next=node;
    37. pcur=pcur->next;
    38. if(l1)
    39. {
    40. l1=l1->next;
    41. }
    42. if(l2)
    43. {
    44. l2=l2->next;
    45. }
    46. ret=ret/10;
    47. }
    48. return head->next;
    49. }

    解析:这里使用的是带头单链表,不用考虑头节点初始化问题;还有一点是:当l1和l2都走完时,还要确定进位是否为0,不为0,新链表还得在加一个节点,储存进位。

    测试及结果: 

    二、回文链表

    234.回文链表(题目链接)

    思路:1)将链表内容复制到数组里面;

               2)使用双指针法判断是否为回文。

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * struct ListNode *next;
    6. * };
    7. */
    8. typedef struct ListNode ListNode;
    9. bool isPalindrome(struct ListNode* head) {
    10. assert(head);
    11. int arr[100000]={0};
    12. int k=0;
    13. ListNode*pcur=head;
    14. while(pcur)
    15. {
    16. arr[k]=pcur->val;
    17. k++;
    18. pcur=pcur->next;
    19. }
    20. for(int i=0,j=k-1;i
    21. {
    22. if(arr[i]!=arr[j])
    23. {
    24. return false;
    25. }
    26. }
    27. return true;
    28. }

    三、相交链表

    160.相交链表(题目链接)

    思路:这道题的思路比较巧妙,相交链表最关键是节点重合,所以判断条件是节点相等,不是节点的val相等 。

    若链表其中一个为NULL,则必定不相交,返回NULL.

    分类讨论:

    1)链表不相交(假设pheadA的长度为m,headB的长度为n)

    1>若m==n,俩链表同时遍历完,相等为NULL

    2>若m!=n,headA往后遍历,若遍历结束,则返回到headB的头节点,headB往后遍历,若遍历结束,则返回到headA的头节点,当遍历m+n次,他们都相等为NULL

    2)链表相交(假设pheadA的长度为m,headB的长度为n,相交点到headA的头节点距离为a,相交点到headB的头节点距离为b,相交点到末尾的长度为c)

    注:a+c=m,b+c=n

    1>若m==n,在遍历完第一遍之前,必定有headA==headB!=NULL

    2>若m!=n,headA往后遍历,若遍历结束,则返回到headB的头节点,headB往后遍历,若遍历结束,则返回到headA的头节点,当headA遍历a+c+b次,headB遍历b+c+a,同时到达相交点,headA==headB!=NULL

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * struct ListNode *next;
    6. * };
    7. */
    8. typedef struct ListNode ListNode;
    9. struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    10. ListNode *p1=headA;
    11. ListNode*p2=headB;
    12. if(p1==NULL)
    13. {
    14. return NULL;
    15. }
    16. if(p2==NULL)
    17. {
    18. return NULL;
    19. }
    20. while(p1!=p2)
    21. {
    22. p1 = p1 == NULL ? headB : p1->next;
    23. p2 = p2 == NULL ? headA : p2->next;
    24. }
    25. //p1与p2不相交,则为NULL;p1与p2相交,则为不为NULL
    26. if(p1==NULL)
    27. {
    28. return NULL;
    29. }
    30. return p1;
    31. }

    四、删除链表倒数第N个节点

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

    解法一:快慢指针(这里使用无头链表,需要对删除头节点额外考虑) 

    1. typedef struct ListNode ListNode;
    2. struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    3. assert(head);
    4. ListNode* fast,*slow;
    5. fast=slow=head;
    6. if(head->next==NULL)//只有一个节点
    7. {
    8. free(head);
    9. head=NULL;
    10. return NULL;
    11. }
    12. //至少2个节点
    13. while(n--)
    14. {
    15. fast=fast->next;
    16. }
    17. if(fast==NULL)//删除头节点
    18. {
    19. head=head->next;
    20. return head;
    21. }
    22. while(fast->next)
    23. {
    24. fast=fast->next;
    25. slow=slow->next;
    26. }
    27. ListNode *del=slow->next;
    28. slow->next=del->next;
    29. free(del);
    30. del=NULL;
    31. return head;
    32. }

    优化快慢指针,引进头节点(哑节点)

    1. typedef struct ListNode ListNode;
    2. struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    3. assert(head);
    4. ListNode* fast,*slow;
    5. ListNode*node=(ListNode*)malloc(sizeof(ListNode));
    6. node->next=head;
    7. fast=slow=node;
    8. int m=n+1;
    9. while(m--)
    10. {
    11. fast=fast->next;
    12. }
    13. while(fast)
    14. {
    15. fast=fast->next;
    16. slow=slow->next;
    17. }
    18. ListNode*del=slow->next;
    19. slow->next=del->next;
    20. free(del);
    21. del=NULL;
    22. return node->next;
    23. }

    解法二:遍历链表,找到链表节点数L,用删除指定位置节点方式删除第(L-n+1)个节点即可

  • 相关阅读:
    代码随想录算法训练营第23期day3| 203.移除链表元素 ,707.设计链表,206.反转链表
    Terraform 初始化慢~配置本地离线源
    ViLBERT—(NeurIPS-2019)
    java基础
    Easyx趣味编程7,鼠标消息读取及音频播放
    一键将Web页面保存至Anki
    根据标签名递归读取xml字符串中element
    Redis篇(3)——事件循环与io模型
    spring_aop_学习笔记
    为什么现在写论文都需要查重?
  • 原文地址:https://blog.csdn.net/zhoubancheng/article/details/134221492