给定一个链表和一个值X,要求将链表中所有小于X的值放到左边,所有大于等于X的值放到右边,并要求原链表的节点顺序不能变。

给定一个链表和一个值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("----结束")
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值