(Golang)leetcode Hot100 第三部分 链表

//208.反转链表
func reverseList(head *ListNode) *ListNode {
	var pre *ListNode //重点:定义链表类型的空指针
	cur := head
	for cur != nil { //cur指向空循环结束
		temp := cur.Next //保存cur下一个结点的地址
		cur.Next = pre   //反转链表
		pre = cur        //先移动pre
		cur = temp       //再移动cur
	}
	return pre
}

 

//24.两两交换链表中的结点
func swapPairs(head *ListNode) *ListNode {
	dummyhead := new(ListNode)
	dummyhead.Next = head
	cur := dummyhead
	for cur.Next != nil && cur.Next.Next != nil { //注意顺序,如果反过来,若cur.Next为nil,则cur.Next.Next会报空指针错误
		temp := cur.Next            //保存第1个结点的地址
		temp1 := cur.Next.Next.Next //保存第3个结点的地址
		cur.Next = temp.Next
		cur.Next.Next = temp
		temp.Next = temp1
		cur = cur.Next.Next
	}
	return dummyhead.Next //返回值为虚拟头结点的Next
 
}
//19.删除链表的倒数第N个结点
func removeNthFromEnd(head *ListNode, n int) *ListNode {
	dummyhead := new(ListNode)
	dummyhead.Next = head
	fast, slow := dummyhead, dummyhead
	n++                        //让n先+1,使得fast先移动n+1步
	for n > 0 && fast != nil { //fast != nil避免n超出链表长度
		fast = fast.Next
		n--
	}
	for fast != nil { //快慢指针同时移动,最后慢指针在要删除结点的前一个结点处
		fast = fast.Next
		slow = slow.Next
	}
	slow.Next = slow.Next.Next //删除结点
	return dummyhead.Next
}
//142.环形链表
func detectCycle(head *ListNode) *ListNode {
	fast, slow := head, head
	for fast != nil && fast.Next != nil { //快指针每次走2个结点,需要保证fast.Next不为nil
		fast = fast.Next.Next //快指针每次走2个结点
		slow = slow.Next      //慢指针每次走1个结点
		if fast == slow {     //快慢指针相遇
			index1 := head         //index1从链表起始位置出发
			index2 := fast         //index2从快慢指针相遇位置出发
			for index1 != index2 { //index1和index2相遇处即为环的入口处
				index1 = index1.Next
				index2 = index2.Next
			}
			return index1
 
		}
	}
	return nil
}

// 面试题 02.07. 链表相交
func getIntersectionNode(headA *ListNode, headB *ListNode) *ListNode {
	index1, index2 := headA, headB
	for index1 != index2 { //index1和index2相交处即为链表相交的起始结点
		if index1 != nil {
			index1 = index1.Next //index1首先遍历链表headA
		} else {
			index1 = headB //然后index1遍历链表headB
		}
		if index2 != nil {
			index2 = index2.Next //index2首先遍历链表headB
		} else {
			index2 = headA //然后index2遍历链表headA
		}
	}
	return index1
}
//141.环形链表
func hasCycle(head *ListNode) bool {
	m := make(map[*ListNode]struct{}) //利用哈希表统计遍历过的元素
	cur := head
	for cur != nil {//遍历链表中所有元素
		if _, ok := m[cur]; ok {//如果出现过返回true
			return true
		}
		m[cur] = struct{}{} //如果没有出现过加入哈希表
		cur = cur.Next
	}
    return false//遍历结束后仍为返回则为false
}
//234.回文链表
func isPalindrome(head *ListNode) bool {
	// 方法:将值复制到数组中后用双指针法
	cur := head
	array := []int{}
	for cur != nil {
		array = append(array, cur.Val)
		cur = cur.Next
	}
	left, right := 0, len(array)-1 //双指针遍历数组
	for left < right {
		if array[left] == array[right] {
			left++
			right--
		} else {
			return false
		}
	}
	return true
}
//21.合并两个有序链表
func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
	dummyhead := new(ListNode)
	if list1 == nil {
		return list2
	}
	if list2 == nil {
		return list1
	}
	p, cur1, cur2 := dummyhead, list1, list2
	for cur1 != nil && cur2 != nil {
		if cur1.Val <= cur2.Val { //将较小值加入结果集然后移动该list 的指针
			p.Next = cur1
			cur1 = cur1.Next
		} else {
			p.Next = cur2
			cur2 = cur2.Next
		}
		p = p.Next
	}
	//将list1和list2剩余元素加入结果集
	if cur1 != nil {
		p.Next = cur1
	}
	if cur2 != nil {
		p.Next = cur2
	}
	return dummyhead.Next
}
//2.两数相加
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
	carry := 0 //记录进位信息
	cur1, cur2 := l1, l2
	dummyhead := new(ListNode)
	cur := dummyhead
	for cur1 != nil || cur2 != nil { //默认短的列表后面元素值为0
		n1, n2 := 0, 0
		if cur1 != nil {
			n1 = cur1.Val
			cur1 = cur1.Next
		}
		if cur2 != nil {
			n2 = cur2.Val
			cur2 = cur2.Next
		}
		sum := n1 + n2 + carry
		sum, carry = sum%10, sum/10
		cur.Next = &ListNode{Val: sum} //创建结点
		cur = cur.Next                 //移动指针

	}
	if carry > 0 { //如果有进位则需要再加一个结点
		cur.Next = &ListNode{Val: carry}
	}
	return dummyhead.Next

}
//146.LRU缓存
type node struct { //链表中的结点的Value 
	key, value int
}

type LRUCache struct {
	cap       int
	objectMap map[int]*list.Element
	list      *list.List
}

func Constructor(capacity int) LRUCache {
	return LRUCache{
		cap:  capacity,
		objectMap: map[int]*list.Element{},
		list:      list.New(),
	}
}

func (this *LRUCache) Get(key int) int {
	if _, ok := this.objectMap[key]; ok {
		e := this.objectMap[key]
		this.list.MoveToFront(e)
		return e.Value.(node).value
	} else {
		return -1
	}
}

func (this *LRUCache) Put(key int, value int) {
	if _, ok := this.objectMap[key]; ok {
		e := this.objectMap[key]
		e.Value = node{key, value}
		this.list.MoveToFront(e) //MovetoFront移动旧结点
		return
	}
     //PushFront加入新节点,并加入到objectMap中
	this.objectMap[key] = this.list.PushFront(node{key, value})
	
	if len(this.objectMap) > this.cap {
		oldnode := this.list.Back()
		this.list.Remove(oldnode)                   //从list中删除元素
		delete(this.objectMap, oldnode.Value.(node).key) //从objectMap中删除元素
	}
	return
}
//146.LRU缓存
package main

import (
	"container/list"
	"fmt"
)

type Node struct { //链表中的结点的Value
	key, value int
}
type LRUCache struct {
	cap       int
	objectMap map[int]*list.Element
	lrulist   *list.List
}

func Constructor(capacity int) LRUCache {
	return LRUCache{
		cap:       capacity,
		objectMap: map[int]*list.Element{},
		lrulist:   list.New(),
	}
}

func (this *LRUCache) Get(key int) int {
	if _, ok := this.objectMap[key]; ok {
		e := this.objectMap[key]
		//将该节点移到链表首部
		this.lrulist.MoveToFront(e) //MovetoFront移动旧结点
		return e.Value.(Node).value
	} else {
		return -1
	}
}

func (this *LRUCache) Put(key int, value int) {
	if _, ok := this.objectMap[key]; ok {
		e := this.objectMap[key]
		e.Value = Node{key, value} //赋新值
		//将该节点移到链表首部
		this.lrulist.MoveToFront(e)
		return
	}
	//PushFront加入新节点,并加入到objectMap中
	this.objectMap[key] = this.lrulist.PushFront(Node{key, value})
	if len(this.objectMap) > this.cap {
		oldnode := this.lrulist.Back()
		this.lrulist.Remove(oldnode)                     //Remove移除旧结点
		delete(this.objectMap, oldnode.Value.(Node).key) //删除objectMap中的key
	}
	return
}

func main() {
	L := Constructor(2)
	L.Put(1, 1)
	L.Put(2, 2)
	fmt.Printf("L.Get(1): %v\n", L.Get(1))
	L.Put(3, 3)
	fmt.Printf("L.Get(2): %v\n", L.Get(2))
	L.Put(4, 4)
	fmt.Printf("L.Get(1): %v\n", L.Get(1))
	fmt.Printf("L.Get(3): %v\n", L.Get(3))
	fmt.Printf("L.Get(4): %v\n", L.Get(4))
	/* 	L.Get(1): 1
	L.Get(2): -1
	L.Get(1): -1
	L.Get(3): 3
	L.Get(4): 4 */
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值