关于链表的一些问题

1. 如果字符串是通过单链表来存储的,那该如何来判断是一个回文串

思路1:用快慢指针先找到中点,然后把后半段链表reversed,然后一个指针在头部,一个指针再中点,开始逐个比较,时间复杂度是O(n)。

思路2:遍历链表,同时将节点入栈;再次遍历链表,同时将元素出栈进行比较,时间复杂度O(n),空间复杂度O(n)。

2. 单链表反转

3. 有序链表合并

4. 链表中环的检测

5. 两个有序的链表合并

6. 删除链表倒数第 n 个结点
思路:创建两个指针,第一个先走n-1步,然后两个指针一起走,当第一个指针走到底部时,第二个就处于倒数第n个。再把这个结点删除。

7.求链表的中间结点

关于写好链表相关代码的一点建议

1.多写多练

2.理解指针或者引用的含义

3.利用哨兵简化实现难度

首先,我们先来回顾一下单链表的插入和删除操作。如果我们在结点 p 后面插入一个新的结点,只需要下面两行代码就可以搞定。

new_node->next = p->next;
p->next = new_node;

但是,当我们要向一个空链表中插入第一个结点,刚刚的逻辑就不能用了。我们需要进行下面这样的特殊处理,其中 head 表示链表的头结点。所以,从这段代码,我们可以发现,对于单链表的插入操作,第一个结点和其他结点的插入逻辑是不一样的。

if (head == null) {
  head = new_node;
}

从前面的一步一步分析,我们可以看出,针对链表的插入、删除操作,需要对插入第一个结点和删除最后一个结点的情况进行特殊处理。这样代码实现起来就会很繁琐,不简洁,而且也容易因为考虑不全而出错。如何来解决这个问题呢?

哨兵就要登场了。哨兵,解决的是国家之间的边界问题。同理,这里说的哨兵也是解决“边界问题”的,不直接参与业务逻辑。

还记得如何表示一个空链表吗?head=null 表示链表中没有结点了。其中 head 表示头结点指针,指向链表中的第一个结点。

如果我们引入哨兵结点,在任何时候,不管链表是不是空,head 指针都会一直指向这个哨兵结点。我们也把这种有哨兵结点的链表叫带头链表。相反,没有哨兵结点的链表就叫作不带头链表。

我画了一个带头链表,你可以发现,哨兵结点是不存储数据的。因为哨兵结点一直存在,所以插入第一个结点和插入其他结点,删除最后一个结点和删除其他结点,都可以统一为相同的代码实现逻辑了。

实际上,这种利用哨兵简化编程难度的技巧,在很多代码实现中都有用到,比如插入排序、归并排序、动态规划等。

4. 留意边界条件的处理

5. 举例画图,辅助思考

原文地址:https://www.cnblogs.com/54chensongxia/p/14090360.html