206、反转链表
基本思想:
双指针迭代
具体实现:
1、申请两个指针,一个叫pre,一个叫cur
cur代表的是当前节点,pre是cur的前一个节点
刚开始,pre指向null,cur是第一个节点
然后cur和pre共同往后走,
cur每走完一步就要指向pre
cur变成none了,就迭代完了
2、cur如何往后走
tmp记录cur当前节点的下一个节点
tmp = cur.next
cur = tmp
代码:
class Solution(object): def reverseList(self, head): """ :type head: ListNode :rtype: ListNode """ # 申请两个节点,pre和 cur,pre指向None pre = None cur = head # 遍历链表,while循环里面的内容其实可以写成一行 # 这里只做演示,就不搞那么骚气的写法了 while cur: # 记录当前节点的下一个节点 tmp = cur.next # 然后将当前节点指向pre cur.next = pre # pre和cur节点都前进一位 pre = cur cur = tmp return pre
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public ListNode reverseList(ListNode head) { ListNode prev = null; ListNode cur = head; ListNode temp = null; while (cur != null){ temp = cur.next; cur.next = prev; prev = cur; cur = temp; } return prev; } }
递归法
1.递归参数以及返回值
递归参数:前后指针
返回值:新链表的头结点
2.确认终止条件:
cur指针(走的快的指针)指向null,递归终止
3.单层递归逻辑
和上一种方法的思想一致
class Solution { public ListNode reverseList(ListNode head) { return reverse(null,head); } private ListNode reverse(ListNode prev, ListNode cur){ if (cur == null){ return prev; } ListNode temp = null; temp = cur.next; cur.next = prev; prev = cur; cur = temp; return reverse(prev, cur); } }
92、反转链表的一部分
基本思想:
将需要反转的的地方先反转,
然后与原来的链表拼接起来
具体实现:
left是需要反转的地方的第一个节点
right是最后一个
1、将pre放到left的前面一个节点
2、将curr放到right后面一个节点
3、切断连接
4、将子链表反转,用单调的方式
5、接回到原来的链表中
代码:
class Solution: def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode: def reverse_linked_list(head: ListNode): # 也可以使用递归反转一个链表 pre = None cur = head while cur: next = cur.next cur.next = pre pre = cur cur = next # 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论 dummy_node = ListNode(-1) dummy_node.next = head pre = dummy_node # 第 1 步:从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点 # 建议写在 for 循环里,语义清晰 for _ in range(left - 1): pre = pre.next # 第 2 步:从 pre 再走 right - left + 1 步,来到 right 节点 right_node = pre for _ in range(right - left + 1): right_node = right_node.next # 第 3 步:切断出一个子链表(截取链表) left_node = pre.next curr = right_node.next # 注意:切断链接 pre.next = None right_node.next = None # 第 4 步:同第 206 题,反转链表的子区间 reverse_linked_list(left_node) # 第 5 步:接回到原来的链表中 pre.next = right_node left_node.next = curr return dummy_node.next
递归思想
25、k个一组反转链表
基本思想:
递归+迭代
1、递归:把前k个节点反转,后面的节点也是一条链表,
而且规模比原来链表小,就是子问题
子问题与原问题的结构相同
2、迭代:同206题反转链表
具体实现:
1、先反转以head开头的k个元素
2、将第k+1个元素作为head再递归调用
3、将上述两个过程的结果连接起来
就是反转完后的链表的尾结点连上下一次递归完后的新头节点
反转完后的链表的尾结点是原链表的头结点
代码:
class Solution: def reverseKGroup(self, head: ListNode, k: int) -> ListNode: if head is None: return None a = b = head for _ in range(k): if b is None: return head b = b.next def reverse(a,b): pre = None cur = a next = a while cur != b: next = cur.next cur.next = pre pre = cur cur = next return pre newhead = reverse(a,b) a.next = self.reverseKGroup(b,k) return newhead