以下残缺的代码,及测试代码均可从这里获取github
删除单向链表倒数第n个结点
办法一:快慢指针法
思路
删除倒数第N个结点,假如反过来看,要删除第N个节点。那么,一个指向头结点(头结点中也是一个数据结点)的指针向前挪动N-1个结点后,指向的就是第N个结点
当初再看删除倒数第N个结点,假如此时有两个指针(快指针fastPtr、慢指针lowPtr)均指向头结点,快指针fastPtr向后遍历N-1个结点之后,慢指针和快指针开始一起向后遍历,当快指针达到最初一个结点的时候,慢指针指向的地位,就是倒数第N个结点的地位
代码实现
func (list *List) DelLastNNode1(lastN int) { if lastN > list.Length() || lastN <= 0 { fmt.Println("输出的待删结点地位不非法") return } //删除尾结点 if lastN == 1 { list.RemoveLastNode() return } //删除头结点 if lastN == list.Length() { //删除链表头结点 list.headNode = list.headNode.Next return } lowNode := list.headNode fastNode := list.headNode prevNode := list.headNode fastStep := lastN-1 for fastNode.Next != nil { if fastStep > 0 { fastNode = fastNode.Next fastStep-- continue } fastNode = fastNode.Next prevNode = lowNode lowNode = lowNode.Next } prevNode.Next = lowNode.Next}
办法二:结点地位和结点数量的关系法
思路
不晓得怎么删除倒数第N个结点,想方法晓得它是第几个不就行了。所以,要害是通过链表长度以及N来找到倒数第N个结点是负数第几个节点,通过观察能够失去,倒数第N个结点就是负数第length-N+1个结点,length为链表长度
代码实现
func (list *List) DelLastNNode2(lastN int) { if lastN > list.Length() || lastN <= 0{ fmt.Println("输出的待删结点地位不非法") return } length := list.Length() position := length-lastN+1 if position == 1 { //删除链表头结点 list.headNode = list.headNode.Next } else if position == length { //删除链表的尾结点 list.RemoveLastNode() } else { //删除链表中指定地位的结点 list.RemovePosition(position) }}
阐明:删除单链表头结点、尾结点、指定地位的节点实现,能够参考我的这一篇文章,或者这里
https://github.com/Rain-Life/data-struct-by-go
两个有序的单链表合并
该题也是LeetCode上第21题
办法一:惯例办法
思路
惯例思路就是,创立一个新的链表,而后遍历待合并的两个链表,比拟遍历到的两个结点值的大小,假如要合并之后的链表依照从小到大排序,值小的那个结点插入到新的链表中,并将值小的那个结点向后遍历一位,值大的那个结点放弃不变,而后持续比拟,反复上边步骤,如图(留神:为了展现过程,下图中未思考链表是否为空的状况)
代码实现
func (list *List) MergeLinkedList(list1 List, list2 List) { if list1.HeadNode == nil && list2.HeadNode == nil { fmt.Println("两个链表均为空") return } else if list1.HeadNode == nil { list.HeadNode = list2.HeadNode return } else if list2.HeadNode == nil { list.HeadNode = list1.HeadNode return } curr1 := list1.HeadNode curr2 := list2.HeadNode if curr1.Data.(int) < curr2.Data.(int) { list.HeadNode = curr1 curr1 = curr1.Next } else { list.HeadNode = curr2 curr2 = curr2.Next } newHead := list.HeadNode currNew := newHead for curr1 != nil && curr2 != nil { if curr1.Data.(int) < curr2.Data.(int) { currNew.Next = curr1 curr1 = curr1.Next } else { currNew.Next = curr2 curr2 = curr2.Next } currNew = currNew.Next } if curr1 == nil { currNew.Next = curr2 } if curr2 == nil { currNew.Next = curr1 }}
办法二:递归
思路
将上边的惯例解法用递归来实现,次要是递归的终止条件
代码实现
func RecursionMergeList(head1 *Node, head2 *Node) *Node { newNode := &Node{} if head1 == nil { return head2 } else if head2 == nil { return head1 } else { if head1.Data.(int) < head2.Data.(int) { newNode = head1 newNode.Next = RecursionMergeList(head1.Next, head2) } else { newNode = head2 newNode.Next = RecursionMergeList(head1, head2.Next) } return newNode }}