经典链表oj题

返回链表中倒数第K个节点

题目描述 链接:倒数第K个节点
实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。

注意:本题相对原题稍作改动

示例:

输入: 1->2->3->4->5 和 k = 2
输出: 4
说明:

给定的 k 保证是有效的。

这道题我们可以用快慢指针的方式来解决,这里的快慢指针不是fast走两步,或者slow走一步的那种快慢指针,而是快指针先走K步,走完之后在让慢指针走,为什么这样做,因为我们这样做先让两个指针拉开K步的差距,让两个指针同时走,等到快指针走完链表最后,走完链表,最后slow就距离链表尾部就差k个距离,因为他们两个之间的距离是恒等不变的。
下面画图来看看
在这里插入图片描述在这里插入图片描述
下面是代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

typedef struct ListNode ListNode;
int kthToLast(struct ListNode* head, int k){
ListNode* fast = head;
ListNode* slow = head;
for(int i = 0;i<k;i++)
{
    fast = fast->next;
}
while(fast != NULL)
{
    fast = fast->next;
    slow = slow->next;
}
return slow->val;
}

链表的回文结构

链表的回文
描述
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。

给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。

测试样例:
1->2->2->1
返回:true

这道题我们的思路是先找到链表的中点,在反转链表中间节点后面的部分,最后让两个链表一个从中间节点开始,另一个从头节点开始,同时往后面遍历,当从中间节点往后遍历为空的时候就结束。这里链表分奇数和偶数个的情况,我们这里偶数恰好满足题目要求,返回后一个节点。
下面我们画图来看看

在这里插入图片描述
我们链表的反转用的是,改变指针的指向来反转的,下面是思路
在这里插入图片描述
代码

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
struct ListNode* find_mid(struct ListNode* head)
{
   struct ListNode* fast = head;
    struct ListNode* slow = head;
    while(fast->next !=NULL && fast)
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}
struct ListNode* revse_mid(struct ListNode* mid)
{
    struct ListNode* p1 = NULL;
    struct ListNode* p2 = mid;
    struct ListNode* p3 = p2->next;
    while(p2)
    {
       p2->next = p1;
        p1 = p2;
       p2 = p3;
       if(p3 != NULL)
       {
        p3 = p3->next;
       }
    }
  return p1;
}
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
       struct ListNode* mid =  find_mid(A);
       struct ListNode* rervse = revse_mid(mid);
       struct ListNode* pcur1 = rervse;

       while(A != NULL && pcur1 != NULL)
       {
        if(A->val != pcur1->val)
        {
            return false;
        }
          A = A->next;
          pcur1 = pcur1->next;
       }
      return true;
    }
};

相交链表

相交链表
题目描述;
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

图示两个链表在节点 c1 开始相交:

在这里插入图片描述

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。

自定义评测:

评测系统 的输入如下(你设计的程序 不适用 此输入):

intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0
listA - 第一个链表
listB - 第二个链表
skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数
skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数
评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA 和 headB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。

这道题我们采用的方法是,先判断链表中,那个链表是长链表,哪个链表是短链表,在拿长链表的节点数去减短链表的节点数,获得差值,最后让长链表先走差值,走完之后让短链表和长链表一起走,他们相遇的地方就是交点,如果没有就是没有交点
在这里插入图片描述
下面是代码

/**
 * 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* pcur1 = headA;
    listnode* pcur2 = headB;
    int leng1 = 0;
    int leng2 = 0;
    while(pcur1 != NULL)
    {
        pcur1 = pcur1->next;
        leng1++;
    }
    while(pcur2 != NULL)
    {
        pcur2 = pcur2->next;
        leng2++;
    }
    if(pcur1 != pcur2)
    {
        return NULL;
    }
    listnode* longlist = headA;
    listnode* shortlist = headB;
  int gap = abs(leng1 - leng2);//取绝对值,长度不可能是负数,假设法第一个链表是长链表,第二个是短链表
  if(leng1>leng2)
  {
    longlist = headA;
    shortlist = headB;
  }
  else
  {
    longlist = headB;
    shortlist = headA;
  }
  while(gap--)
  {
    longlist = longlist->next;
  }
  while(longlist != shortlist)
  {
    longlist = longlist->next;
    shortlist = shortlist->next;
  }
  return longlist;
}

以上就是本文的内容了,如果有什么错误欢迎指正。

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值