算法62-链表的快慢指针

题目:
在这里插入图片描述

以上四种情况类似,均通过快慢指针的初始点,以及移动条件控制最终的输出

代码:

package main
import (
	"fmt"
)
//链表本身,包含长度,头结点和尾节点,对于一个双向链表,
//我们只关注它的haea和tail,head和tail是一个个具体的节点
type LinkedList struct {
	len  int
	head *LinkedNode
	tail *LinkedNode
}
//链表中的一个节点的结构,包含节点的数据,前向指针,后向指针,指向的也是一个节点本身
type LinkedNode struct {
	data int
	next *LinkedNode
	prev  *LinkedNode
}
// type Data struct{
// 	key string
// 	data int
// }
//所有的操作都基于指针
func NewLinkedList() *LinkedList {
	return &LinkedList{
		len:  0,
		head: nil,
		tail: nil,
	}
}
//追加一个节点,链表没有头结点就把自己设为链表的头结点,头尾指针都指向自己
//有头结点就把自己放在最后,1先把自己的prev指向原来的tail,2把原来的tail的next指向自己,3把链表的tail设为自己
func (ll *LinkedList)Add(node *LinkedNode) {
	// node := &LinkedNode{
	// 	data: data,
	// }
	// fmt.Printf("hhhhhhead%v\n", ll.head)

	if ll.head==nil{
		ll.tail=node

		ll.head=node
	}else{
		// fmt.Printf("tttttail%v\n", ll.tail)
		node.prev=ll.tail

		ll.tail.next=node
		ll.tail=node
		
	}
	
	ll.len++//记得更新长度
}
//奇数返回中点 偶数返回上中点
func Midorupmid(head LinkedNode) LinkedNode{
	if &head ==nil || head.next == nil || head.next.next == nil{//只有一个节点或两个节点时,返回头结点
		return head
	}
	//慢指针一个定位在第二个节点,快指针定位在第三个节点
	slow:=head.next
	fast:=head.next.next
	for fast.next != nil && fast.next.next !=nil{
		slow=slow.next
		fast=fast.next.next
	}
	return *slow
}	
//1 for里面的条件是&,不是||
//2 slow和 fast在前进过程中是不等距的,不能混淆
func Midordownmid(head LinkedNode) *LinkedNode{
	if &head ==nil || head.next == nil {//控制节点大于1,就可以进入下面的循环
		return &head//当head等于nil,head的next也等于nil,
	}
	//两个指针都初始化在head.next
	slow:=head.next
	fast:=head.next
	//节点数大于1进入
	for   fast.next !=nil && fast.next.next !=nil {//注意是and,必现同时满足
		slow=slow.next
		fast=fast.next.next//slow和fast不等距,所以不能用slow.next.next代替
		// fmt.Println(slow,fast)
	}
	return slow
}	

func beforeMidorupmid(head LinkedNode) *LinkedNode{
	if &head ==nil || head.next == nil || head.next.next == nil{//节点数小于3,均不成立
		return nil
	}
	//两个指针都定位在头节点,返回slow的前置节点
	slow:=&head
	fast:=&head
	//节点数大于2才成立
	for fast.next != nil && fast.next.next !=nil{
		slow=slow.next
		fast=fast.next.next
	}
	return slow.prev
}
func aftereMidordownmid(head LinkedNode) *LinkedNode{
	if &head ==nil || head.next == nil || head.next.next == nil{//节点数小于3,均不成立
		return nil
	}
	//两个指针都定位在头节点,返回slow的前置节点
	slow:=head.next
	fast:=head.next
	//节点数大于2才成立
	for fast.next != nil && fast.next.next !=nil{
		slow=slow.next
		fast=fast.next.next
	}
	return slow.next
}


func main(){
	var head LinkedNode
	head.data=18

	var l1 LinkedNode
	l1.data=5

	var l2 LinkedNode
	l2.data=20

    var l3 LinkedNode
	l3.data=4

  
    var l4 LinkedNode
    l4.data=3

	var l5 LinkedNode
    l5.data=8

	var l6 LinkedNode
    l6.data=12

	var l7 LinkedNode
	l7.data=15

	list := NewLinkedList()
	list.Add(&head)
	list.Add(&l1)
	list.Add(&l2)
	list.Add(&l3)
	list.Add(&l4)
	list.Add(&l5)

	// fmt.Println(list.head)
	// fmt.Println(list.head.next)

	// fmt.Println(list.head.next.next)
	// fmt.Println(list.head.next.next.next)
	// fmt.Println(list.tail)

	fmt.Println(Midorupmid(head))
	fmt.Println(Midordownmid(head))
	fmt.Println(beforeMidorupmid(head))
	fmt.Println(aftereMidordownmid(head))
}

链表-18 ,5,20, 4,3, 8
输出:

{20 0xc0000960a8 0xc000096078}
&{4 0xc0000960c0 0xc000096090}
&{5 0xc000096090 0xc000096060}
&{3 0xc0000960d8 0xc0000960a8}

总结:
该类题型的重点在于

1 快慢指针初始在那个点上,同一个点or一前一后
2 移动条件,何时移动,何时不移动,控制输出的节点一直落在一个快慢指针相关的点上

coding上
1,两个指针移动过程中可能不是等距的,不能互相赋值
2,for循环条件中是&

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值