[力扣02]linkedList

目录


一、常用函数

package main

import (
	"fmt"
)

/**
golang实现单链表
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。
链表中的数据以节点来表示,每个节点的构成:元素(数据元素的映像)+ 指针(指向后继元素存储位置)。
元素是存储数据的存储单元,指针是连接每个节点的地址数据。
节点结构:
|--data--|--next--|
data域存放节点值的数据域,next域存放节点的直接后继地址(位置)的指针域(链域)
头指针head和终端节点
单链表中每个几点的存储地址是存放在其前趋节点next域中。而开始节点无前趋,所以应该设置头指针head指向开始节点。
链表由头指针唯一确定,单链表可以用头指针的名字来命名。
终端节点无后继,所以终端节点的指针域为空,即NULL。
*/

type Node struct {
	// 值
	Data interface{}
	// 后继节点指针
	Next *Node
}

// 链表是否为空
func IsEmpty(node *Node) bool {
	return node== nil
}


// 是否是最后一个节点
func IsLast(node *Node) bool  {
	return node.Next == nil
}

// 查找指定节点的前一个节点
func FindPrevious(data interface{}, node *Node) *Node  {
	tmp := node
	for tmp!=nil && tmp.Next != nil && tmp.Next.Data != data {
		tmp = tmp.Next
	}
	return tmp
}
// 查找某个值在哪个节点
func Findx(data interface{},node *Node) *Node {
	p := node
	for ;p != nil;p=p.Next {
		if(p.Data == data) {
			return p
		} 
	}
	return nil
}
// 查找某个值在哪个节点
func Find(data interface{}, node *Node) *Node  {
	tmp := node
	for tmp!=nil && tmp.Data != data {
		tmp = tmp.Next
	}
	return tmp
}
// 插入节点:在指定节点插入节点
/**
position:指定的节点位置
*/
func Insert(data interface{}, position *Node)  {
	// 新建一个节点
	tmpCell := new(Node)
	if tmpCell == nil {
		fmt.Println("err: out of space")
	}
	// 给新建的节点的值域赋值为传入的data值
	tmpCell.Data = data
	// 新建的节点的next指针指向的是指定节点position的next
	tmpCell.Next = position.Next
	// 指定节点position的后继节点变成了新建的节点
	position.Next = tmpCell
}

// 删除节点
func Delete(data interface{}, node *Node)  {
	tmp := node
	for tmp.Next!=nil {
		if(tmp.Next.Data == data){
			p := tmp.Next
			tmp.Next = p.Next
			p.Next = nil
			break;
		}
		tmp = tmp.Next
	}
}

// 删除链表
// func DeleteList(node **Node)  {
// 	p := node
// 	for *p != nil {
// 		tmp := *p
// 		*p = nil
// 		*p = tmp.Next
// 	}
// }
func DeleteList(node *Node)  {
	p := node
	for p != nil {
		tmp := p
		p = tmp.Next
		tmp.Next = nil
	}
	node = nil
}
//反转链表 递归
func ReverseList(node *Node) *Node{
	p :=node
	if p.Next==nil{
		return p
	}
	q:=ReverseList(p.Next)
	p.Next.Next=p
	p.Next=nil
	return q
}

//返回倒数第k个数 双指针法
func kthToLast(k int,node *Node) *Node{
	p := node
	q := node
	for ;k>0;k--{
		p=p.Next
	}
	for p!=nil{
		p=p.Next
		q=q.Next
	}
	return q
}

//返回倒数第k个数 递归
var size int //全局变量记录向后递归次数
func ZkthToLast(k int,node *Node) *Node{
	p:=node
	if p==nil{
		return p
	}
	t:=ZkthToLast(k,p.Next)
	size++
	if size==k{
		return p
	}
	if size<k{
		return t
	}
	if size>k{
		return t
	}
	return t
}
//反转链表 非递归
func NReverseList(node *Node) *Node{
	p :=node
	var cre *Node =nil
    for p!=nil{
		t:=p.Next
		p.Next=cre
		cre=p
		p=t
	}
	return cre
}

//打印列表
func PrintList(list *Node) {
	p := list
	for p != nil {
		fmt.Printf("%d ", p.Data)
		// fmt.Printf("%d-%v-%p ", p.Data, *p, p.Next)
		p = p.Next
	}
	fmt.Println()
}
/**LRU算法***************************************************/
//哈希表
type LRUCache struct {
	size int
	capacity int
	cache map[int]*DLinkedNode
	head, tail *DLinkedNode
}
//双向链表
type DLinkedNode struct {
	key, value int
	prev, next *DLinkedNode
}

func initDLinkedNode(key, value int) *DLinkedNode {
	return &DLinkedNode{
		key: key,
		value: value,
	}
}
//建一个空的双向链表
func Constructor(capacity int) LRUCache {
	l := LRUCache{
		cache: map[int]*DLinkedNode{},
		head: initDLinkedNode(0, 0),
		tail: initDLinkedNode(0, 0),
		capacity: capacity,
	}
	l.head.next = l.tail
	l.tail.prev = l.head
	return l
}
//取一个数
func (this *LRUCache) Get(key int) int {
	if _, ok := this.cache[key]; !ok {
		return -1
	}
	node := this.cache[key]
	//放到最前边
	this.moveToHead(node)
	return node.value
}

//加一个数
func (this *LRUCache) Put(key int, value int)  {
	//如果没有
	if _, ok := this.cache[key]; !ok {
		node := initDLinkedNode(key, value)
		this.cache[key] = node
		this.addToHead(node)
		this.size++
		if this.size > this.capacity {
			removed := this.removeTail()
			delete(this.cache, removed.key)
			this.size--
		}
	} else {
		node := this.cache[key]
		node.value = value
		this.moveToHead(node)
	}
}
//在前边添加
func (this *LRUCache) addToHead(node *DLinkedNode) {
	node.prev = this.head
	node.next = this.head.next
	this.head.next.prev = node
	this.head.next = node
}
//删除节点
func (this *LRUCache) removeNode(node *DLinkedNode) {
	node.prev.next = node.next
	node.next.prev = node.prev
}
//移到前方
func (this *LRUCache) moveToHead(node *DLinkedNode) {
	this.removeNode(node)
	this.addToHead(node)
}
//删除尾部
func (this *LRUCache) removeTail() *DLinkedNode {
	node := this.tail.prev
	this.removeNode(node)
	return node
}

/*!!!!!!!!!!!!!!!!!!!判断是否有环,判断入环点*/
//快慢指针
func detectCycle(head *Node) *Node {
	fast,slow:=head,head
	if fast==nil{
		return nil
	}
	for fast!=nil{
		if fast.Next==nil{
			return nil
		}
		fast = fast.Next.Next
		slow = slow.Next
		if fast==slow{
			break
		}
	}
	if fast==nil{
		return nil
	}
	for slow=head;slow!=fast;slow=slow.Next{
		fast=fast.Next
	}
	return fast
}
//*****************回文链表
// type ListNode struct {
//	 Val  int
//	 Next *ListNode
// }
//反转链表
func reverseList(head *Node) *Node {
	var prev, cur *Node = nil, head
	for cur != nil {
		nextTmp := cur.Next
		cur.Next = prev
		prev = cur
		cur = nextTmp
	}
	return prev
}
//找到前一半链表
func endOfFirstHalf(head *Node) *Node {
	fast := head
	slow := head
	for fast.Next != nil && fast.Next.Next != nil {
		fast = fast.Next.Next
		slow = slow.Next
	}
	return slow
}
//判断是否是回文链表
func isPalindrome(head *Node) bool {
	if head == nil {
		return true
	}

	// 找到前半部分链表的尾节点并反转后半部分链表
	firstHalfEnd := endOfFirstHalf(head)
	secondHalfStart := reverseList(firstHalfEnd.Next)

	// 判断是否回文
	p1 := head
	p2 := secondHalfStart
	result := true
	for result && p2 != nil {
		if p1.Data != p2.Data {
			result = false
		}
		p1 = p1.Next
		p2 = p2.Next
	}

	// 还原链表并返回结果
	firstHalfEnd.Next = reverseList(secondHalfStart)
	return result
}
//反转链表mn
func reverseBetween(head *Node, m int, n int) *Node {
	// 关键点是m的前一个节点
	dummy := &Node{
		Next: head,
	}
	prem := dummy
	for i := 1; i <= m-1; i++ {
		prem = prem.Next
	}

	// m和n区间内反转
	current := prem.Next
	var pre *Node
	for i := m; i <= n; i++ {
		tempNext := current.Next
		current.Next = pre
		pre = current
		current = tempNext
	}

	// prem.Next为m节点,原始m节点应该指向n+1节点
	prem.Next.Next = current
	// prem指向pre(反转之后的头节点)
	prem.Next = pre

	return dummy.Next
}

func main() {
	//定义头结点
	headNode := &Node{
		Data:0,
		Next:nil,
	}
	list := headNode
	//1.指定位置插入结点1
	Insert(1, headNode)
	//2.打印列表
	PrintList(list)
    //3.判断是否为空
	fmt.Println(IsEmpty(list))
	//4.是否是最后一个节点
	fmt.Println(IsLast(headNode))
	//5.根据值查找节点
	p := Find(1, list)
	fmt.Printf("pos: %#v\n",p)
	//插入数据
	Insert(2, p)
	Insert(3, p)
	PrintList(list)
	//删除结点
	// Delete(3, list)
	// PrintList(list)
	//删除链表
	// DeleteList(list)
	// PrintList(list)
	//反转链表递归
	Reverselist:=ReverseList(list)
	PrintList(Reverselist)
	//反转链表非递归
	NReverselist:=NReverseList(Reverselist)
	PrintList(NReverselist)
	//返回倒数第k个数 双指针法
	kthToLast :=kthToLast(3,NReverselist)
	fmt.Println(kthToLast)
	//返回倒数第k个数 递归
	kthToLast = ZkthToLast(3,NReverselist)
	fmt.Println(kthToLast)
    //判断是否有环
    fmt.Println(detectCycle(NReverselist))
	//判断回文链表
	fmt.Println(isPalindrome(NReverselist))
	//反转链表mn
	PrintList(reverseBetween(NReverselist,0,1))
}

二、习题

1.Add Two Numbers

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
    var res ListNode
    var t *ListNode = &res
    var p *ListNode = l1
    var q *ListNode = l2
    var c int = 0
    for ;p!=nil || q!=nil; {//有节点
        var temp *ListNode = new(ListNode)
        t.Next = temp
        t = t.Next
        if(p!=nil && q==nil){
            tval := p.Val + c
            temp.Val = tval % 10
            c = tval / 10
            p = p.Next
        }else if(p==nil && q!=nil){
            tval := q.Val + c  
            temp.Val = tval % 10
            c = tval / 10        
            q = q.Next
        }else{
            tval := (p.Val + q.Val + c) 
            temp.Val = tval % 10
            c = tval / 10
            p = p.Next
            q = q.Next
        } 
        
    }
    if(c > 0){
        temp := ListNode{Val:c,Next:nil}
        t.Next = &temp
    }

    return res.Next
    
}

2.Remove Nth Node From End of List

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
 //法一 查长度
// func removeNthFromEnd(head *ListNode, n int) *ListNode {
//     var headNode *ListNode = &ListNode{Val:0,Next:head}
//     var q,t = headNode,headNode
//     var p *ListNode = head
    
//     len := 1
//     for p != nil {
//         len++
//         p = p.Next
//     }
//     for i := len - n -1;i > 0 ;i-- {
//         q = q.Next
//     }
//     t = q.Next
//     q.Next = t.Next
//     t.Next = nil
//     return headNode.Next
// }

//法二 双指针法
// 间隔n 
func removeNthFromEnd(head *ListNode, n int) *ListNode {
    dummyHead := &ListNode{Next:head}
    preSlow,slow,fast := dummyHead,head,head//preSlow.Next指向待删除节点
    for fast != nil {
        if n <= 0 { //fast point tail or nil move slow keep distance
            preSlow = slow
            slow = slow.Next
        }
        n--
        fast = fast.Next
    }
    preSlow.Next = slow.Next
    return dummyHead.Next
}

3.Merge Two Sorted Lists

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
 //法一: 选小合并
// func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
//     p,q := list1,list2
//     dummy := &ListNode{}
//     cur := dummy
//     for p != nil && q != nil {
//         if p.Val <= q.Val {
//             t := &ListNode{Val:p.Val}
//             cur.Next = t
//             cur = cur.Next
//             p = p.Next
//         }else{
//             t := &ListNode{Val:q.Val}
//             cur.Next = t
//             cur = cur.Next
//             q = q.Next
//         }
//     }
//     if p == nil {
//         cur.Next = q
//     }else{
//         cur.Next = p
//     }
//     return dummy.Next
// }

//法二:递归,每两个节点选小的返回,然后选小的下一个进行递归。 结束条件是:其中一个遍历完,将剩余链表返回
func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
    if list1 == nil {
        return list2
    }
    if list2 == nil {
        return list1
    }
    if list1.Val < list2.Val {
        list1.Next = mergeTwoLists(list1.Next,list2)
        return list1
    }
    list2.Next = mergeTwoLists(list1,list2.Next)
    return list2
}

4. Merge k Sorted Lists

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
 // 分治法:递归合并子k链表
func mergeKLists(lists []*ListNode) *ListNode {
    length := len(lists)
    if length < 1{
        return nil
    }
    if length == 1 {
        return lists[0]
    }
    half := length/2
    left := mergeKLists(lists[:half])
    right := mergeKLists(lists[half:])
    return mergeTowLists(left,right)
}

func mergeTowLists(l1 *ListNode,l2 *ListNode) *ListNode {
    if l1 == nil {
        return l2
    }
    if l2 ==nil {
        return l1
    }
    if l1.Val < l2.Val {
        l1.Next = mergeTowLists(l1.Next,l2)
        return l1
    }
    l2.Next = mergeTowLists(l1,l2.Next)
    return l2
}

5.Swap Nodes in Pairs

在这里插入图片描述
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */

func swapPairs(head *ListNode) *ListNode {
    dummyNode := &ListNode{Next:head}
    for pre:=dummyNode; pre!=nil && pre.Next!=nil && pre.Next.Next!=nil; {
        cur:=pre.Next
        next:=cur.Next
        pre.Next,cur.Next,next.Next,pre = next,next.Next,cur,cur
    }
    return dummyNode.Next
}

6.Reverse Nodes in k-Group

在这里插入图片描述
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reverseKGroup(head *ListNode, k int) *ListNode {
    node := head
    for i:=0; i < k; i++ {
        if node== nil {
            return head
        }
        node = node.Next
    }
    newHead := reverse(head,node)
    head.Next = reverseKGroup(node,k)
    return newHead
}

func reverse(first *ListNode,last *ListNode) *ListNode{
    prev := last
    for first!=last {
        tmp := first.Next
        first.Next = prev
        prev = first
        first = tmp
    }
    return prev
}

7.Rotate List

Example 2:

Input: 0->1->2->NULL, k = 4
Output: 2->0->1->NULL
Explanation:
rotate 1 steps to the right: 2->0->1->NULL
rotate 2 steps to the right: 1->2->0->NULL
rotate 3 steps to the right: 0->1->2->NULL
rotate 4 steps to the right: 2->0->1->NULL

题目大意 #
旋转链表 K 次。

解题思路 #
这道题需要注意的点是,K 可能很大,K = 2000000000 ,如果是循环肯定会超时。应该找出 O(n) 的复杂度的算法才行。由于是循环旋转,最终状态其实是确定的,利用链表的长度取余可以得到链表的最终旋转结果。

这道题也不能用递归,递归解法会超时。

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func rotateRight(head *ListNode, k int) *ListNode {
    if head == nil || head.Next== nil || k ==0  {
        return head
    }
    dummyNode := &ListNode{Next:head}
    len:=0
    cur := dummyNode
    //count and make chain
    for cur.Next!=nil{
        len++
        cur = cur.Next
    }

    if (k % len) == 0{
        return head
    }
    //find res and remove chain  
    cur.Next = head
    cur = dummyNode
    for i := len - k%len;i > 0;i-- {//time of move forward
        cur = cur.Next
    }
    res := &ListNode{Next:cur.Next}
    cur.Next = nil
    return res.Next
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值