给定一个链表和一个值X,要求将链表中所有小于X的值放到左边,所有大于等于X的值放到右边,并要求原链表的节点顺序不能变。
例如:1->5->3->2->4->2,给定X=3,则要返回1->2->2->3->5->4
//key可能重复,所以需要找到前后两个分界节点F、B,先以F为分界,所有F后面比F小的都往F前移;再以B为分界,所有B之前比B大的都往B后移
class LNode {
var key: Int
var desc: String?
var next: LNode?
init(key: Int, desc: String) {
self.key = key
self.desc = desc
}
init(key: Int) {
self.key = key
}
func log() -> String {
return "\(key)" + (desc != nil ? "-\(desc!)" : "")
}
}
func reorder(header: LNode, x: Int) {
var start = header
var (sepF, sepB) = findSep(header: header, x: x)
//先以F为分界,所有F后面小的都往F前移
var temp: LNode? = sepF.next
var pre: LNode? = sepF
while let node = temp {
if node.key < sepF.key {
//这里直接将sepF改变,这样就不需要预先知道sepF的上一个节点信息了
// 用 node 替换 sepF,再将 node 赋给sepF,然后建立链接关系
pre!.next = node.next
temp = pre!.next
let next = sepF.next
let key = sepF.key
let desc = sepF.desc
sepF.key = node.key
sepF.next = node
sepF.desc = node.desc
node.key = key
node.next = next
node.desc = desc
if sepB === sepF {
sepB = node
}
if pre! === sepF {
pre = node
}
sepF = node
}
else {
pre = temp
temp = temp?.next
}
}
printList(header: start)
// print("\n")
//以B为分界,所有B之前大的都往B后移
temp = start
pre = nil
var insertAt = sepB //比B大的节点需要插入到此节点之后,默认为 sepB,因为移动后要保持原来的排序
while let node = temp, node !== sepB {
if node.key > sepB.key {
if pre == nil {
temp = temp!.next
start = temp! //头指针变了
}
else {
pre?.next = node.next
temp = pre?.next
}
node.next = insertAt.next
insertAt.next = node
insertAt = node
}
else {
pre = temp
temp = temp?.next
}
}
printList(header: start)
}
//假定节点的key可以重复、假定x不一定存在与链表中
//找到最合适的分界节点,匹配的意思是与X差距的绝对值最小的
func findSep(header: LNode, x: Int) -> (LNode, LNode) {
var sepF = header
var sepB = header
var diff: Int = abs(header.key - x)
var temp = header.next
while let node = temp {
let delta = abs(node.key - x)
if delta < diff {
sepF = node
sepB = node
diff = delta
}
else if delta == diff {
sepB = node
}
temp = temp?.next
}
print("F: \(sepF.log()), B: \(sepB.log())")
return (sepF, sepB)
}
//打印链表
func printList(header: LNode) {
print("")
var temp: LNode? = header
while let node = temp {
print("\(node.log()), ", separator: ", ", terminator: "")
temp = node.next
}
print("")
}
//测试代码
func testReorder() {
//1->5->3->2->4->2,给定X=3,则要返回1->2->2->3->5->4
let lists = [
LNode(key: 1),
LNode(key: 5),
LNode(key: 3),
LNode(key: 2),
LNode(key: 4),
LNode(key: 2)
]
// let lists = [
// LNode(key: 10, desc: "1"),
// LNode(key: 1),
// LNode(key: 2),
// LNode(key: 5),
// LNode(key: 12, desc: "1"),
// LNode(key: 12, desc: "2"),
// LNode(key: 10, desc: "2"),
// LNode(key: 14)
// ]
for idx in 0..<lists.count-1 {
lists[idx].next = lists[idx+1]
}
printList(header: lists.first!)
print("----")
reorder(header: lists.first!, x: 3)
print("----结束")
}