详解链表oJ<反转链表,链表的中间节点及链表的回文>

简介: 详解链表oJ<反转链表,链表的中间节点及链表的回文>

一,链表的中间节点

  1. 链接:链表的中间节点

分析:

 如果想要得到链表的中间节点,最简单的思路就是从头结点遍历整个链表,就可以知道链表的长度,假设为num个,要求是如果为偶数个数,返回第二个节点。得到个数后要创建新的节点,往后走num/2个位置。如果num为奇数,如5,往后next两步,如果是偶数如6,往后next3步,皆满足要求。

实现:

struct ListNode* middleNode(struct ListNode* head){
    struct ListNode* ret = head;
    int len = 0;
    int k = 0;
    while(ret)
    {
        ret = ret -> next;
        len++;
    }
    ret = head;
    while(k < len / 2)
    {
        k++;
        ret = ret -> next;
    }
    return ret;
}

此题还有一种双指针的方法

思路:

 设置快慢指针,快指针一次走两步,慢指针一次走一步,还是分偶数和奇数的情况。

如果是奇数的话

如果是偶数的话

要注意观察fast的最终位置

实现如下

struct ListNode* middleNode(struct ListNode* head) {
  struct ListNode* val = NULL;
  struct ListNode* baga = NULL;
  val = head;
  baga = head;
  while (val->next != NULL && val->next->next != NULL)
  {
    val = val->next->next;
    baga = baga->next;
  }
  if (val->next == NULL)
  {
    return baga;
  }
  else
  {
    return baga->next;
  }
}

二,反转链表

链接:反转链表

这道题的介绍很简单,给定一个链表head,将链表反转过来。就像这样。

需要注意的是,这个链表的长度有可能为零。

思路:

 解决这道题,不可冒昧更改一个节点的指向,要记录后续节点,同时还要保留前一个节点,好让这个节点可以指向前一节点,所以要设置三个结构体指针变量,分别表示要修改的节点,要修改节点的前一节点,该节点的后边的节点。

实现

struct ListNode* reverseList(struct ListNode* head){
    struct ListNode*n1,*n2,*n3;
    n1=NULL;//设置n1为空
    n2=head;//n2为head,首先指向空
    if(n2)
    {
        n3=n2->next;//判断n2是否为空,若为空则没有next      
    }
    while(n2)
    {
        n2->next=n1;
        n1=n2;
        n2=n3;
        if(n3)//判断n3是否为空
        {
            n3=n3->next;
        }
    }
    return n1;
}

下边的动图可以帮助大家理解

对比代码看完这些动图就可以很清晰的理解。

三,链表的回文

链接:链表的回文

设计时间复杂度为O(N),空间复杂度为O(1)的算法

时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法的时间复杂度。

 空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。

 上边已经说了链表的长度有限制,空间复杂度为O(1)无疑,只要写出的代码中不使用两层以上循环遍历,用有限的多个循环,时间复杂度都为O(1)

判断是否为回文结构

如用例中的1-2-2-1,从中间分割后两边对称。

再如

1-2-3-2-1,仍然为回文结构。

如何判断是否为回文结构呢?好像很难,因为不是双向链表,我们比较的时候找不到尾的前一个,如果硬要一个一个判断的话,时间复杂度一定不符合要求。

如果使用上边的两个题目的思路

 上边的找中间节点,刚好为后一个中间节点,找到中间节点后,记录中间节点后,将中间结点之后的链表反转,反转后就可以进行比较了。这也是这三道题放在一起的原因。直接cv,将函数复制过来,判断函数内容十分简单,大家可以对照观察。

思路已经十分清楚了

实现如下:

class PalindromeList {
public:
struct ListNode* middleNode(struct ListNode* head) {
  struct ListNode* val = NULL;
  struct ListNode* baga = NULL;
  val = head;
  baga = head;
  while (val->next != NULL && val->next->next != NULL)
  {
    val = val->next->next;
    baga = baga->next;
  }
  if (val->next == NULL)
  {
    return baga;
  }
  else
  {
    return baga->next;
  }
}
struct ListNode* reverseList(struct ListNode* head){
    struct ListNode*n1,*n2,*n3;
    n1=NULL;
    n2=head;
    if(n2)
    {
        n3=n2->next;
    }
        while(n2)
         {
             n2->next=n1;
            n1=n2;
            n2=n3;
             if(n3)//判断n3是否为空
              n3=n3->next;
         }
    return n1;
}
    bool chkPalindrome(ListNode* A) {
        // write code here
        struct ListNode*mid=middleNode(A);
        struct ListNode* rmid =reverseList(mid);
        while(rmid&&A)
        {
            if(rmid->val!=A->val)
            {
                return false;
            }
            rmid=rmid->next;
        A=A->next;
        }
        return true;
    }
};

鄙人才疏学浅,如果有更好的方法欢迎评论区留言。

 这三道题讲到这里就结束啦,如果有帮助的话希望大家三连支持哇

目录
相关文章
|
1天前
|
算法 搜索推荐 索引
数据结构与算法⑥(第二章OJ题,下)后八道链表面试题(下)
数据结构与算法⑥(第二章OJ题,下)后八道链表面试题
4 0
|
1天前
|
算法 程序员 索引
数据结构与算法⑥(第二章OJ题,下)后八道链表面试题(中)
数据结构与算法⑥(第二章OJ题,下)后八道链表面试题
11 0
|
1天前
|
算法 C语言 C++
数据结构与算法⑥(第二章OJ题,下)后八道链表面试题(上)
数据结构与算法⑥(第二章OJ题,下)后八道链表面试题
12 0
|
1天前
|
算法 测试技术
数据结构与算法⑤(第二章OJ题,上)前五道链表面试题(下)
数据结构与算法⑤(第二章OJ题,上)前五道链表面试题
8 0
|
1天前
|
算法
数据结构与算法⑤(第二章OJ题,上)前五道链表面试题(上)
数据结构与算法⑤(第二章OJ题,上)前五道链表面试题
9 0
|
1天前
剑指 Offer 18. 删除链表的节点
剑指 Offer 18. 删除链表的节点
9 0
|
1天前
11道链表oj题
11道链表oj题
5 0
链表遍历,链表查找和统计节点,链表插入新节点,链表删除节点,链表修改指定节点,链表头插法,尾插法总结
链表遍历,链表查找和统计节点,链表插入新节点,链表删除节点,链表修改指定节点,链表头插法,尾插法总结
|
6天前
|
存储 Java
高效删除链表倒数节点最优实现
要删除链表的倒数第 n 个节点,并返回链表的头节点,我们可以使用一趟扫描的方法来实现。这个方法涉及使用两个指针:快指针和慢指针。
|
6天前
|
算法
LeetCode刷题---19. 删除链表的倒数第 N 个结点(双指针-快慢指针)
LeetCode刷题---19. 删除链表的倒数第 N 个结点(双指针-快慢指针)