package jianzhi
import (
"fmt"
"github.com/emirpasic/gods/maps/hashmap"
"github.com/emirpasic/gods/stacks/linkedliststack"
"sort"
)
//给定链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
//Definition for singly-linked list.
type ListNode struct {
Val int
Next *ListNode
}
// 方法:先将链表遍历,并读取val,存入数组中,对数组排序后,依次将值赋到链表中
func sortList(head *ListNode) *ListNode {
if head == nil{
return nil
}
var arr []int
for node := head;node != nil; node = node.Next{
arr = append(arr, node.Val)
}
sort.Ints(arr)
for node ,index:= head,0;node != nil; node = node.Next{
node.Val = arr[index]
index++
}
return head
}
/*
给定一个单链表 L 的头节点 head ,单链表 L 表示为:
L0 → L1 → … → Ln-1 → Ln
请将其重新排列后变为:
L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换
*/
//先遍历一遍,将结点全部入栈,并记录个数,得到N的值,之后再遍历,每次新插入一个出栈的元素,对末尾的next指向空
func reorderList(head *ListNode) {
if head == nil{
return
}
stack1 := linkedliststack.New()
var n int = 0
for node := head;node != nil; node = node.Next{
stack1.Push(node)
n++
}
var node = head
for index := 0;index < n; node = node.Next{
index ++
if index == n {
break
}
res, ok := stack1.Pop()
if ok {
lastNode := res.(*ListNode)
lastNode.Next = node.Next
node.Next = lastNode
node = node.Next
index ++
}
}
node.Next = nil
}
/*
给定单链表的头节点 head ,请反转链表,并返回反转后的链表的头节点
*/
func reverseList(head *ListNode) *ListNode {
if head == nil{
return nil
}
stack1:= linkedliststack.New()
for node := head;node != nil; node = node.Next{
stack1.Push(node)
}
var revHead *ListNode
top, ok := stack1.Pop()
if ok{
revHead = top.(*ListNode)
}
var node = revHead
for ;!stack1.Empty();{
top, ok := stack1.Pop()
if ok{
topNode := top.(*ListNode)
node.Next = topNode
node = node.Next
}
}
node.Next = nil
return revHead
}
/*
给定一个链表的 头节点 head ,请判断其是否为回文链表。
如果一个链表是回文,那么链表节点序列从前往后看和从后往前看是相同的。
*/
//先遍历一遍 入栈, 再遍历一遍并同时与出栈的元素进行对比,如果都相等 则是回文
func isPalindrome(head *ListNode) bool {
if head == nil{
return true
}
stack1:= linkedliststack.New()
for node := head;node != nil; node = node.Next{
stack1.Push(node)
}
for node := head;!stack1.Empty();node = node.Next{
top, ok := stack1.Pop()
if ok{
topNode := top.(*ListNode)
if topNode.Val != node.Val{
return false
}
}
}
return true
}
/*
给定一个链表数组,每个链表都已经按升序排列。
请将所有链表合并到一个升序链表中,返回合并后的链表。
*/
func mergeKLists(lists []*ListNode) *ListNode {
if len(lists) == 0 {
return nil
}
var headNode []*ListNode
var head *ListNode = nil
for _, list := range lists{
if list == nil{
continue
}
if head == nil || list.Val < head.Val{
head = list
}
headNode = append (headNode,list)
}
if head == nil{
return nil
}
for curNode:= head;len(headNode) > 0 ;{
minNodeIndex := 0
for index, pNode := range headNode{
if pNode.Val < headNode[minNodeIndex].Val{
minNodeIndex = index
}
}
if curNode != headNode[minNodeIndex]{
curNode.Next = headNode[minNodeIndex]
curNode=curNode.Next
}
headNode[minNodeIndex] = headNode[minNodeIndex].Next
if headNode[minNodeIndex] == nil{
headNode = append(headNode[:minNodeIndex],headNode[minNodeIndex+1:]...)
}
}
return head
}
/*
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
*/
type Node struct {
Val int
Next *Node
Random *Node
}
//先遍历一遍, 把每个结点复制出来,并将复制结点存入map中, 【老结点】:新节点
func copyRandomList(head *Node) *Node {
if head == nil{
return nil
}
nodeMap := hashmap.New() // empty
for node := head; node != nil; node=node.Next{
var newNode = Node{node.Val,nil,nil}
nodeMap.Put(node,&newNode)
}
for node := head; node != nil; node=node.Next{
newNodeRes, _ := nodeMap.Get(node)
newNode := newNodeRes.(*Node)
if node.Next != nil{
newNextNodeRes, _ := nodeMap.Get(node.Next)
newNode.Next = newNextNodeRes.(*Node)
}
if node.Random != nil{
newRdmNodeRes, _ := nodeMap.Get(node.Random)
newNode.Random = newRdmNodeRes.(*Node)
}
}
newNodeRes, _ := nodeMap.Get(head)
return newNodeRes.(*Node)
}
/*
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
*/
func deleteNode(head *ListNode, val int) *ListNode {
if head == nil{
return nil
}
var resHead = head
//先确定头结点没有要删除的
for node:= head;node != nil && node.Val == val;node = node.Next{
resHead = node.Next
}
if resHead == nil{
return nil
}
for pre, node := resHead,resHead.Next;node != nil;node = node.Next{
if node.Val == val{
if node.Next != nil{
node.Val = node.Next.Val
node.Next = node.Next.Next
}else{
pre.Next = nil
}
}
pre = node
}
return resHead
}
func TestMergeOrderList(){
list1 := ListNode{1,&ListNode{2,&ListNode{4,&ListNode{4,&ListNode{5,nil}}}}}
list2 := ListNode{0,&ListNode{1,&ListNode{1,&ListNode{1,nil}}}}
list3 := ListNode{3,&ListNode{7,&ListNode{8,nil}}}
var listArr = []*ListNode{&list1,&list2,&list3}
res := mergeKLists(listArr)
for ;res != nil;res =res.Next{
fmt.Print(res.Val,"->")
}
fmt.Print("nil\n")
}
/*
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
*/
func reversePrint(head *ListNode) []int {
if head == nil{
return []int{}
}
mstack := linkedliststack.New()
var revVal []int
for node := head;node != nil;node = node.Next{
mstack.Push(node)
}
for; !mstack.Empty();{
top, ok :=mstack.Pop()
if ok{
node := top.(*ListNode)
revVal = append(revVal,node.Val)
}
}
return revVal
}
func reversePrint1(head *ListNode) []int {
if head == nil{
return []int{}
}
var revVal []int
for node := head;node != nil;node = node.Next{
revVal = append([]int{node.Val},revVal...) //相当于每次插入都把数组的所有元素后移一位,时间复杂度O(N2)
}
return revVal
}
/*
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
*/
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
if l1 == nil{
return l2
}else if l2 == nil{
return l1
}
var (
resHead *ListNode = &ListNode{}
p1 = l1
p2 = l2
p = resHead
)
for ;p1!= nil && p2!= nil; p = p.Next{
newNode := ListNode{Next: nil}
if p1.Val <= p2.Val{
newNode.Val = p1.Val
p1 = p1.Next
}else{
newNode.Val = p2.Val
p2= p2.Next
}
p.Next = &newNode
}
if p1!=nil{
p.Next = p1
}else if p2 != nil{
p.Next = p2
}
return resHead.Next
}
/*
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
*/
//长度记为N 倒数第K个 是正数的第N-K+1;需遍历两遍 第一遍统计长度,然后第二遍找出结点
//两个指针一起走,p1先走K-1步,接着p1p2一起移动 当p1走到最后,p2指向倒数第k
//边界情况 head=nil, k>len链表总长
func getKthFromEnd(head *ListNode, k int) *ListNode {
if head == nil{
return nil
}
var (
index = 0
p1,p2 = head,head
)
for ;p1!=nil;p1=p1.Next{
if index > k-1{
p2 = p2.Next
}
index ++
}
if index <= k-1{
return nil
}
return p2
}
func TestGetKthFromEnd(){
fmt.Println(getKthFromEnd(&ListNode{1,&ListNode{2,&ListNode{3,&ListNode{4,&ListNode{5,&ListNode{6,nil}}}}}},6).Val)
}
/*
输入两个链表,找出它们的第一个公共节点。
*/
//入栈 并对比两个栈顶元素,不一致时,下一个为公共结点
//边界情况:1 链表为空 2 其中一个链表是另一个的子集 2 完全相等 3 完全不等
func getIntersectionNode(headA, headB *ListNode) *ListNode {
if headA == nil || headB == nil{
return nil
}
stackA := linkedliststack.New()
stackB := linkedliststack.New()
for node := headA;node != nil;node = node.Next{
stackA.Push(node)
}
for node := headB;node != nil;node = node.Next{
stackB.Push(node)
}
for;(!stackA.Empty()) && (!stackB.Empty());{
topA, _ := stackA.Peek()
nodeA := topA.(*ListNode)
topB, _ := stackB.Peek()
nodeB := topB.(*ListNode)
if nodeA != nodeB {
break
}
stackA.Pop()
stackB.Pop()
}
if !stackA.Empty(){
topA, _ := stackA.Peek()
return topA.(*ListNode).Next
}
if !stackB.Empty(){
topB, _ := stackB.Peek()
return topB.(*ListNode).Next
}
//完全相等
return headA
}
func TestGetIntersectionNode(){
headA := &ListNode{1,&ListNode{2,&ListNode{3,&ListNode{4,&ListNode{5,&ListNode{6,nil}}}}}}
headB := headA
res := getIntersectionNode(headA,headB)
if res == nil{
fmt.Println("nil")
} else{
fmt.Println("完全相等:",res.Val)
}
headB = &ListNode{4,&ListNode{5,&ListNode{6,nil}}}
headA = &ListNode{1,&ListNode{2,&ListNode{3,headB}}}
res = getIntersectionNode(headA,headB)
if res == nil{
fmt.Println("nil")
} else{
fmt.Println("子集:",res.Val)
}
headC := &ListNode{5,&ListNode{6,nil}}
headA = &ListNode{1,&ListNode{2,&ListNode{3,&ListNode{4,headC}}}}
headB = &ListNode{8,headC}
res = getIntersectionNode(headA,headB)
if res == nil{
fmt.Println("nil")
} else{
fmt.Println("Y型:",res.Val)
}
headA = &ListNode{1,&ListNode{2,&ListNode{3,&ListNode{4,&ListNode{5,&ListNode{6,nil}}}}}}
headB = &ListNode{6,&ListNode{5,&ListNode{4,&ListNode{3,&ListNode{2,&ListNode{1,nil}}}}}}
res = getIntersectionNode(headA,headB)
if res == nil{
fmt.Println("nil")
} else{
fmt.Println("完全不等:",res.Val)
}
}
剑指 链表相关
最新推荐文章于 2022-01-24 18:23:27 发布