题目1: 203.移除链表元素
思路: 还记得点虚拟节点的用法,算是写出来了。
按我的理解说一下,单链表删除节点的时候,只能是查当前节点和下一个节点(也可以说是 上一个节点和当前节点)。
在链表中间的时候,这操作没问题。
但是如果头结点就是要被删除的值,那他没有头结点,就导致需要额外处理这个case。 也就是提前while循环把头结点检查到不是目标值,再写循环。
那么优化的方式二就 显而易见了:给头结点加个前置的节点(这样头结点也就有上一个节点了),就可以用一个循环解决。
// @lc code=start
/**
* Definition for singly-linked list.
* public class ListNode {
* public var val: Int
* public var next: ListNode?
* public init() { self.val = 0; self.next = nil; }
* public init(_ val: Int) { self.val = val; self.next = nil; }
* public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; }
* }
*/
class Solution {
func removeElements(_ head: ListNode?, _ val: Int) -> ListNode? {
let dummyNode = ListNode(-1, head)
var node: ListNode? = dummyNode
while let next = node?.next {
if next.val == val {
node?.next = next.next
} else {
node = node?.next
}
}
return dummyNode.next
}
}
// @lc code=end
看一下题解swift的写法,node的 optional解包操作处理的不好
node = node?.next 改成 node = next
这样就不用到处都是问号了。
题目2:707.设计链表
优化一下写法 再提个pull request 替换一下swift的题解。
// @lc code=start
class MyLinkedList {
var dummyNode = ListNode()
var size = 0
init() {}
func get(_ index: Int) -> Int {
if index < 0 || index >= size {
return -1
}
var node = dummyNode.next
var curIndex = index
while curIndex > 0 {
curIndex -= 1
node = node?.next
}
return node?.val ?? -1
}
func addAtHead(_ val: Int) {
let newNode = ListNode(val)
newNode.next = dummyNode.next
dummyNode.next = newNode
size += 1
printNodeList()
}
func addAtTail(_ val: Int) {
var curNode = dummyNode
while let nextNode = curNode.next {
curNode = nextNode
}
curNode.next = ListNode(val)
size += 1
printNodeList()
}
func addAtIndex(_ index: Int, _ val: Int) {
if index > size {
return
}
var preNode = findPreNode(index)
let newNode = ListNode(val)
// 添加节点
newNode.next = preNode?.next
preNode?.next = newNode
size += 1
printNodeList()
}
func deleteAtIndex(_ index: Int) {
print("deleteAtIndex index:\(index)")
if index < 0 || index >= size {
return
}
var preNode = findPreNode(index)
// 删除节点
preNode?.next = preNode?.next?.next
size -= 1
printNodeList()
}
// 找到index之前的元素,如果index小于0,则返回dummyNode
func findPreNode(_ index: Int) -> ListNode? {
if index > size {
return nil
}
var curNode = dummyNode
// 要找到index位置的前一个节点,因为dummyNode的存在,从index开始遍历,正好找到的是index位置的前一个节点
var curIndex = index
while curIndex > 0 {
curIndex -= 1
curNode = curNode.next!
}
return curNode
}
}
/**
* Your MyLinkedList object will be instantiated and called as such:
* let obj = MyLinkedList()
* let ret_1: Int = obj.get(index)
* obj.addAtHead(val)
* obj.addAtTail(val)
* obj.addAtIndex(index, val)
* obj.deleteAtIndex(index)
*/
// @lc code=end
题目3: 206.反转链表
// 没有理解为什么这种写法会超时。 未AC
// 第一个节点 少反转了。 导致 5 4 3 2 1 2 1 2 1 ... 死循环了。😭
func reverseList(_ head: ListNode?) -> ListNode? {
if head == nil || head?.next == nil {
return head
}
var pre: ListNode?
var cur = head
var next = head?.next
while next != nil {
print("新一轮")
pre = cur
cur = next
next = next?.next
cur?.next = pre
print("pre:\(pre?.val) cur:\(cur?.val) next:\(next?.val)")
}
print("结束")
return cur
}
// 抛弃上述想法,直接按照题解 清晰不容易出错。
func reverseList(_ head: ListNode?) -> ListNode? {
if head == nil || head?.next == nil {
return head
}
var pre: ListNode? = nil
var cur: ListNode? = head
var temp: ListNode? = nil
while cur != nil {
temp = cur?.next
cur?.next = pre
pre = cur
cur = temp
}
return pre
}