算法篇:链表之反转链表

算法:

反转链表的基本操作可以拆分成下面四步:

1.保存前序节点,
2.保存后续节点,
3.当前节点指向前序节点
4.偏移前序节点和当前节点

其他的变形题目,主要围绕两个关键点:

1.反转之后的前序节点的处理
2.反转之后的后续节点的保存

题目1:反转链表

https://leetcode-cn.com/problems/reverse-linked-list/

代码实现:

/*
解法:保存前序节点,
     保存后续节点,
     当前节点指向前序节点
     偏移前序节点和当前节点
     返回值 是前序节点
*/
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reverseList(head *ListNode) *ListNode {
    var pre *ListNode
    curr := head
    for curr != nil {
        // fmt.Println(":",*curr)
        tmp := curr.Next
        curr.Next = pre
        pre = curr
        curr = tmp
    }
    return pre
}

执行结果:

题目2:

https://leetcode-cn.com/problems/reverse-linked-list-ii/

代码实现:

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reverseBetween(head *ListNode, m int, n int) *ListNode {
    if head == nil || head.Next == nil || m == n{
        return head
    }
    first := head
    var begin *ListNode
    for i:= m; i>1; i-- { // 找到m节点的前序节点
        begin = first
        first = first.Next 
    }
    
    var h1 *ListNode = first
    for i:=n;i>m;i-- { // 找到第n个节点
        h1 = h1.Next   
    }
    var second *ListNode
    if h1.Next != nil { // 找到第n个节点的后续节点
        second = h1.Next
    }
    
    h1.Next = nil // 从n节点位置将链表分成两个单独的链表
   // first为反转后的前序节点,second为反转之后的后续节点,
   // 对于要反转的链表来说,second也是头节点的前序节点
    h1 = reverseList(first,second) 
    if begin != nil {
        begin.Next = h1
    } else {
        head = h1
    }
   
    return head
}
func reverseList(head *ListNode, last *ListNode) *ListNode {
    if head == nil || head.Next == nil {
        return head
    }
    curr := head
    var pre *ListNode = last
    for curr != nil { 
        tmp := curr.Next 
        curr.Next = pre
        pre = curr
        curr= tmp  
    }
    
    return pre
}
/*
解法:将需要反转的单独拉出一个列表来操作
然后,将前面的初始位置记录一下
将结尾位置作为反转之后的pre节点连接起来
备注:需要注意传入的起始和结束位置为整个链表的情况
*/

执行结果:

题目3:两两交换链表中的节点
https://leetcode-cn.com/problems/swap-nodes-in-pairs/submissions/

代码实现:

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
 // 解法:递归,1st和2nd节点反转,1st节点的next指向反转之后的链表,2nd.Next指向1st作反转处理
func swapPairs(head *ListNode) *ListNode {
    if head == nil || head.Next == nil {
        return head
    }
    // 两个临时节点定好位置
    first := head
    second:= head.Next
    // 反转处理
    first.Next = swapPairs(second.Next)
    second.Next = first
    return second
}

执行结果:

题目4:k个一组反转链表

https://leetcode-cn.com/problems/reverse-nodes-in-k-group/

代码实现:

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
 // 解法:递归,K个节点反转一次,然后头节点转换指向到下一个k链表,
 // 循环直到都操作结束
func reverseKGroup(head *ListNode, k int) *ListNode {
    if head == nil {
        return head
    }
    begin,end := head,head
    for i:=0; i<k;i++{
        if end == nil { // 小于k的链表,直接返回
            return head
        }
        end = end.Next
    }
    // end表示的是反转之后的头节点,其实就是k链表之后的那个节点
    node := reverseList(begin,end)
    // 更换头节点的指向,方便下一次反转链表
    begin.Next = reverseKGroup(end,k)
    return node
}
// 一个链表的反转,node表示反转之后的头节点
func reverseList(head *ListNode, node *ListNode) *ListNode {
    if head == nil || head.Next == nil {
        return head
    }
    curr:= head
    pre := node
    for curr != node {
        tmp := curr.Next
        curr.Next=pre
        pre = curr
        curr= tmp
    }
    return pre
}

执行结果:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值