题目来自2021腾讯实习生招聘-技术研发综合-第三次笔试
题目描述:牛牛有一个无环的单链表,牛牛可以不停的旋转这个链表,比如链表:1->2->3->4,经过旋转后可以变成一下4中链表:
4->1->2->3
3->4->1->2
2->3->4->1
1->2->3->4
牛牛想找到一个旋转的链表,它表示序列的字典序最小。定义序列{a}的字典序小于序列{b}:存在一个位置j,满足对于所有的i<j,ai=bi,且aj<bj,这个例子的最小字典序列就是1->2->3->4。
使用go实现,思路:将单链表变成单向循环链表,枚举n(链表长度)个起始位置,记录当前字典序最小的那个起始位置。
package main
import "fmt"
type ListNode struct {
val int
next *ListNode
}
func main() {
var L *ListNode
L = CreatList(L)
solve(L)
}
func solve(L *ListNode)(*ListNode) {
if L == nil {
return L
}
len := 1 //记录链表的长度
res, q, p := L, L, L.next
//cur1, cur2 :=
for q.next != nil {
q = q.next
len++
}
q.next = L //最后一个节点的next指针指向第一个节点,将单链表变成循环链表
for ; p != L; p = p.next {
if cmp(L, res, p, len) > 0 { //维护一个最小字典序列的起始位置res,如果p开头的链表的字典序列小于res开头的链表,则res=p
res = p
}
}
w := res
for i := 0; i < len; i++ {
fmt.Printf("%d ", w.val)
w = w.next
}
return res
}
func cmp(L, p, q *ListNode, n int) int {//比较以p,q两个节点开始的,长度为n的序列的字典序列大小关系
a, b := p, q
for i := 0; i < n; i++ {
if a.val == b.val {
a = a.next
b = b.next
}else if a.val > b.val {
return 1
}else {
return -1
}
}
return 0
}
func CreatList(L *ListNode)(* ListNode) {//尾插法创建链表
var x int
L = &ListNode{}
var r *ListNode //r为表尾指针
r = L
fmt.Scan(&x)
for x != 9999 {
s := &ListNode{x, nil}
r.next = s
r = s
fmt.Scan(&x)
}
L = L.next
//f := L
//for f != nil {
// fmt.Printf("%d ", f.val)
// f = f.next
//}
return L
}