算法-两两交换链表节点(不能使用值交换方式)

思路&代码

个人思路是,每次拆下来两个节点,进行重新拼接,但是拆节点之前,要先让后续的链表还有指针指向(否则后续造成链表丢失),如下代码中指针 m 表示每次拆节点之前,剩余链表头指指针。另外,重新拼接等介于重新构建链表,采用的尾查法,所以定义每次插入新节点前的前驱指针 t,指针 h 表示新链表的头指针(当然题目中也可以是使用head).核心处理点在,第一次拆节点组装,跟每
次要新拆的两节点的跳转条件之,以及退出循环之后的条件判断.

代码(有注释说明)

package main

import "fmt"

type ListNode struct {
	Val  int
	Next *ListNode
}

func swapPairs(head *ListNode) *ListNode {
	// 临界条件,链表为空或者只有一个节点
	if head == nil {
		return nil
	}
	if head.Next == nil {
		return head
	}

	/*
		个人思路是,每次拆下来两个节点,进行重新拼接,但是拆节点之前,要先让后续的链表还有指针指向(否则后续造成链表丢失),
		如下代码中指针 m 表示每次拆节点之前,剩余链表头指指针。另外,重新拼接等介于重新构建链表,采用的尾查法,所以重新定义每次
		插入新节点前的前驱指针 t,指针 h 表示新链表的头指针(当然题目中也可以是使用head).核心处理点在,第一次拆节点组装,跟每
		次要新拆的两节点的跳转条件之,以及退出循环之后的条件判断.

	*/
	var p, q, t, m, h *ListNode
	p = head
	q = head.Next

	for p != nil && q != nil {
		m = q.Next    // 拆节点前,让m指针指向剩余的链表节点
		if h == nil { // 第一次拆,将q作为新链表头节点,
			h = q
			t = h
			t.Next = p // 新链表的第二个节点(原来链表的头节点)
			p.Next = nil
			t = t.Next // 新链表的要插入节点的前驱节点
		} else {
			// 后续的链表构建处理
			t.Next = q
			q.Next = p
			p.Next = nil
			t = p
		}
		// 后续要拆的两个节点的指针跳转条件
		p = m
		if p != nil {
			q = m.Next
		}
	}
	if p == nil {
		return h
	}
	if q == nil {
		t.Next = p
	}
	return h
}

func (l *ListNode) Display() {
	for h := l; h != nil; h = h.Next {
		fmt.Println(h.Val)
	}
	fmt.Println("------")
}
func main() {

	var t *ListNode
	root := &ListNode{
		Val: 1, Next: nil,
	}
	t = root
	n := &ListNode{
		Val: 2, Next: nil,
	}
	t.Next = n
	t = t.Next

	n = &ListNode{
		Val: 3, Next: nil,
	}
	t.Next = n
	t = t.Next

	n = &ListNode{
		Val: 4, Next: nil,
	}
	t.Next = n
	t = t.Next

	root.Display()

	swapPairs(root).Display()
}

输出结果:
1
2
3
4
------
2
1
4
3
------

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值