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

简介: LeetCode 热题100——链表专题(一)

一、俩数相加

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


2c6308ef1cd536f6dca3cdd46109478c_5d10fa641e7d4f3a898c9b921bb0bf29.png

思路:这题题目首先要看懂,以示例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相加


代码实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef  struct ListNode  ListNode;
 ListNode * ListBuyNode(int x)
 {
     ListNode * node=(ListNode*)malloc(sizeof(ListNode));
     if(node==NULL)
     {
         perror("malloc fail:");
         return NULL;
     }
     node->val=x;
     node->next=NULL;
     return  node;
 }
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
   int ret=0;
   ListNode *head=(ListNode*)malloc(sizeof(ListNode));//带头单链表
   ListNode*pcur=head;
    while(l1||l2||ret)
    {
       if(l1)
       {
           ret=ret+l1->val;
       }
       if(l2)
       {
           ret=ret+l2->val;
       }
       ListNode *node=ListBuyNode(ret%10);
       pcur->next=node;
       pcur=pcur->next;
       if(l1)
       {
           l1=l1->next;
       }
      if(l2)
      {
           l2=l2->next;
      }
       ret=ret/10;
    }
    return head->next;
}


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

测试及结果:


二、回文链表

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


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

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

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct   ListNode   ListNode;
bool isPalindrome(struct ListNode* head) {
    assert(head);
     int arr[100000]={0};
     int k=0;
     ListNode*pcur=head;
     while(pcur)
     {
           arr[k]=pcur->val;
           k++;
           pcur=pcur->next;
     }
      for(int i=0,j=k-1;i<j;i++,j--)
      {
          if(arr[i]!=arr[j])
          {
              return false;
          }
      }
      return true;
}


三、相交链表

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

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct  ListNode  ListNode;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    ListNode *p1=headA;
    ListNode*p2=headB;
    if(p1==NULL)
    {
        return NULL;
    }
    if(p2==NULL)
    {
        return NULL;
    }
   while(p1!=p2)
  {
    p1 = p1 == NULL ? headB : p1->next;
    p2 = p2 == NULL ? headA : p2->next;
  }
   //p1与p2不相交,则为NULL;p1与p2相交,则为不为NULL
   if(p1==NULL)
   {
       return NULL;
   }
    return p1;
}


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

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

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

typedef struct ListNode ListNode;
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
   assert(head);
   ListNode* fast,*slow;
  fast=slow=head;
  if(head->next==NULL)//只有一个节点
  {
      free(head);
      head=NULL;
      return NULL;
  }
  //至少2个节点
  while(n--)
  {
    fast=fast->next;
  }
  if(fast==NULL)//删除头节点
  {
     head=head->next;
     return head;
  }
   while(fast->next)
   {
        fast=fast->next;
        slow=slow->next;
   }
   ListNode *del=slow->next;
    slow->next=del->next;
    free(del);
    del=NULL;
    return head;
}


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

 typedef struct ListNode ListNode;
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
   assert(head);
   ListNode* fast,*slow;
   ListNode*node=(ListNode*)malloc(sizeof(ListNode));
   node->next=head;
  fast=slow=node;
  int m=n+1;
  while(m--)
  {
      fast=fast->next;
  }
  while(fast)
  {
      fast=fast->next;
      slow=slow->next;
  }
  ListNode*del=slow->next;
    slow->next=del->next;
    free(del);
    del=NULL;
    return node->next;
}

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

相关文章
|
1月前
【力扣】-- 移除链表元素
【力扣】-- 移除链表元素
35 1
|
1月前
Leetcode第21题(合并两个有序链表)
这篇文章介绍了如何使用非递归和递归方法解决LeetCode第21题,即合并两个有序链表的问题。
48 0
Leetcode第21题(合并两个有序链表)
|
1月前
LeetCode第二十四题(两两交换链表中的节点)
这篇文章介绍了LeetCode第24题的解法,即如何通过使用三个指针(preNode, curNode, curNextNode)来两两交换链表中的节点,并提供了详细的代码实现。
18 0
LeetCode第二十四题(两两交换链表中的节点)
|
1月前
Leetcode第十九题(删除链表的倒数第N个节点)
LeetCode第19题要求删除链表的倒数第N个节点,可以通过快慢指针法在一次遍历中实现。
44 0
Leetcode第十九题(删除链表的倒数第N个节点)
|
1月前
|
索引
力扣(LeetCode)数据结构练习题(3)------链表
力扣(LeetCode)数据结构练习题(3)------链表
78 0
|
1月前
【LeetCode 10】142. 环形链表 II
【LeetCode 10】142. 环形链表 II
21 0
|
1月前
【LeetCode 09】19 删除链表的倒数第 N 个结点
【LeetCode 09】19 删除链表的倒数第 N 个结点
17 0
|
1月前
【LeetCode 08】206 反转链表
【LeetCode 08】206 反转链表
12 0
|
1月前
【LeetCode 06】203.移除链表元素
【LeetCode 06】203.移除链表元素
30 0
|
3月前
|
C++ 索引
leetcode 707.设计链表
本文提供了解决LeetCode 707题"设计链表"的C++实现,包括单链表的节点定义和类方法实现,如添加节点、获取节点值、删除节点等。