链表

leetcode2
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

对链表排序

链表排序:在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
归并排序 快慢指针,从中间拆分,排序,合并

func sortList(head *ListNode) *ListNode {
    if head == nil || head.Next == nil {
		return head
	}
	fast := head.Next
	slow := head

	for fast != nil && fast.Next != nil {
		slow = slow.Next            //findmiddle list
		fast = fast.Next.Next
	}

	tmp := slow.Next
    slow.Next=nil
	left := sortList(head)
	right := sortList(tmp)
	h := new(ListNode)
	res := h
	for left != nil && right != nil {
		if left.Val < right.Val {
			h.Next = left
			left = left.Next
		} else {
			h.Next = right
			right = right.Next
		}
		h = h.Next
	}
	if left != nil {
		h.Next = left
	} else if right != nil {
		h.Next = right
	}
	return res.Next
}

旋转链表

给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。

示例 1:

输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL

先成环,新的链表的头节点是第n-k%n个节点,新链表的尾节点就是头节点前一个节点,所以是n-k%n-1个节点

func rotateRight(head *ListNode8, k int) *ListNode8 {
	if head == nil {
		return nil
	}
	if head.Next == nil {
		return head
	}

	oldTail := head
	n := 1
	for n = 1; oldTail.Next != nil; n++ {
		oldTail = oldTail.Next
	}
	oldTail.Next = head

	newTail := head
	for i := 0; i < n-k%n-1; i++ {
		newTail = newTail.Next
	}
	newHead := newTail.Next

	newTail.Next = nil
	return newHead
}

环形链表

给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数pos来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环
https://github.com/labuladong/fucking-algorithm/blob/master/%E7%AE%97%E6%B3%95%E6%80%9D%E7%BB%B4%E7%B3%BB%E5%88%97/%E5%8F%8C%E6%8C%87%E9%92%88%E6%8A%80%E5%B7%A7.md
经典解法就是用两个指针,一个跑得快,一个跑得慢。如果不含有环,跑得快的那个指针最终会遇到 null,说明链表不含环;如果含有环,快指针最终会超慢指针一圈,和慢指针相遇,说明链表含有环。

快慢指针法

func hasCycle(head *ListNode) bool {
    fast, slow := head, head
	for fast != nil && fast.Next != nil {
		fast = fast.Next.Next
		slow = slow.Next

		if fast == slow {
			return true
		}
	}

	return false
}

环形链表的起点

func detectCycle(head *ListNode10) *ListNode10 {
	fast, slow := head, head
	if fast == nil || fast.Next == nil {
		return nil
	}
	for fast != nil && fast.Next != nil {
		fast = fast.Next.Next
		slow = slow.Next

		if fast == slow {
			break
		}
	}

	slow = head
	for slow != fast {
		fast = fast.Next
		slow = slow.Next
	}
	return slow
}

链表的中间节点

func middleNode(head *ListNode) *ListNode {
fast, slow := head, head
for fast != nil && fast.Next != nil {
fast = fast.Next.Next
slow = slow.Next
}
return slow
}

面试题22. 链表中倒数第k个节点

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。
示例:
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.

func getKthFromEnd(head *ListNode, k int) *ListNode {
    fast, slow := head, head

	for i := 0; i < k; i++ {
		fast = fast.Next
	}

	for fast != nil {
		slow = slow.Next
		fast = fast.Next
	}
	return slow
}

面试题18. 删除链表的节点

给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
注意:此题对比原题有改动
示例 1:
输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.

删除值为 val 的节点可分为两步:定位节点、修改引用。
定位节点: 遍历链表,直到 head.val == val 时跳出,即可定位目标节点。
修改引用: 设节点 cur 的前驱节点为 pre ,后继节点为 cur.next ;则执行 pre.next = cur.next ,即可实现删除 cur 节点。
在这里插入图片描述

func deleteNode(head *ListNode, val int) *ListNode {
    if head.Val == val {
		return head.Next
	}
	pre := head
	cur := head.Next
	for cur != nil && cur.Val != val {
		pre = cur
		cur = cur.Next
	}
	if cur != nil {
		pre.Next = cur.Next
	}
	return head
}

面试题24. 反转链表

定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

func reverseList(head *ListNode) *ListNode {
    var (
		pre *ListNode = nil
		tmp *ListNode = nil
	)
	cur := head

	for cur != nil {
		tmp = cur.Next //临时变量缓存cur的下一个节点
		cur.Next = pre //cur指向新节点
		pre = cur      //新节点前进
		cur = tmp      //cur前进
	}
	return pre
    
}

面试题25. 合并两个排序的链表

输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
示例1:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
	mergedList := new(ListNode)
	tempList := mergedList

	for l1 != nil && l2 != nil {
		if l1.Val <= l2.Val {
			tempList.Next = l1
			l1 = l1.Next
		} else {
			tempList.Next = l2
			l2 = l2.Next
		}
		tempList = tempList.Next
	}

	tempList.Next = l1
	if l1 == nil {
		tempList.Next = l2
	}

	return mergedList.Next
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值