203.移除链表元素
1. 第一想法:如何处理好 当前元素和下一个元素的关系。首先要判断虚拟头结点是否为空;
写出来除了判断头结点的方法
接着判断当前元素是否为空,就直接返回,不为空;判断当前元素的下一个元素是否符合条件,不符合条件就只令 当前元素 = 当前元素的下一个元素
就判断当前元素的下一个元素是否符合条件(符合条件就令node.next = node.next.next)
进行下一个循环(继续判断当前元素,因为当前元素的下一个元素是新赋值的)
- 处理头结点
方法一:单独处理头结点,直到头结点的值不符合条件或者为空
方法二:设置一个虚拟头结点,该头结点一定不符合条件,所以可以统一代码。
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func removeElements(head *ListNode, val int) *ListNode {
if head == nil{
return head
}
for head.Val == val{
head = head.Next
if head == nil{
return head
}
}
node := head
for node != nil{
if node.Next == nil{
break
}
if node.Next.Val == val{
node.Next = node.Next.Next
}else{
node = node.Next
}
}
return head
}
今日收获:处理不好当前元素和下一个元素的关系; 头节点的处理方式,没想到虚拟节点
707.设计链表
第一想法:这道题对于我来说不算很难,看了提示,选用使用虚拟头结点练习一下。
不会创建
MyLinkedList()
初始化MyLinkedList
对象。看了一下讲解- 先创建一个单节点的结构,再创建一个虚拟头节点的结构,包含一个真正的头结点和链表索引(我使用的时链表索引)
- 初始化一个链表:使用单节点的结构体创建一个头结点,在创建一个虚拟节点的结构,虚拟节点指向头结点
- 添加一个节点在头结点 (创建一个新的节点,)
- 获取一个指定位置的节点(遍历到指定节点的前一个,再获取指定结点的值)
- 添加一个节点再链表的尾部(不要使用遍历,分情况,如果是空链表就直接添加,如果不是使用判断节点的下一个值是指向nil)
- 添加一个节点在指定索引的位置(先分情况,再遍历到指定索引的前一个节点)
- 删除一个指定索引位置的节点()
-
type Node struct{ Value int Next *Node } type MyLinkedList struct { dummyHead *Node len int } func Constructor() MyLinkedList { headNode := &Node{ -999, nil, } mylinke := MyLinkedList{ dummyHead : headNode, len: -1, } return mylinke } func (this *MyLinkedList) Get(index int) int { if index > this.len || index < 0{ return -1 } // 头结点 node := this.dummyHead i := 0 // 从头结点开始遍历 for i =0; i < index;i++{ node = node.Next } return node.Next.Value } func (this *MyLinkedList) AddAtHead(val int) { NewNode := &Node{ val, this.dummyHead.Next, } this.dummyHead.Next = NewNode this.len++ } func (this *MyLinkedList) AddAtTail(val int) { NewNode := &Node{ val, nil, } node := this.dummyHead if node == nil{ node.Next = NewNode }else{ for node.Next != nil{ node = node.Next } node.Next = NewNode } // for i:=0; i < this.len ;i++{ // node = node.Next // } // for // if node.Next != nil{ // node.Next.Next = NewNode // } this.len++ } func (this *MyLinkedList) AddAtIndex(index int, val int) { if index > this.len+1{ return } if index == this.len+1{ this.AddAtTail(val) return } if index == 0{ this.AddAtHead(val) return } NewNode := &Node{ val, nil, } node := this.dummyHead for i:=0; i < index;i++{ node = node.Next } NewNode.Next = node.Next node.Next = NewNode this.len++ } func (this *MyLinkedList) DeleteAtIndex(index int) { if index > this.len{ return } node := this.dummyHead for i:=0; i < index;i++{ node = node.Next } // 有可能删除第一个节点0 此时node就是第一个结点 if node.Next != nil{ node.Next = node.Next.Next } // 此时node是要删除节点的前一个节点 this.len-- } /** * Your MyLinkedList object will be instantiated and called as such: * obj := Constructor(); * param_1 := obj.Get(index); * obj.AddAtHead(val); * obj.AddAtTail(val); * obj.AddAtIndex(index,val); * obj.DeleteAtIndex(index); */
不知道为什么 DeleteAtIndex要有判断node.next !=nil 这一步
-
今日总结:浪费了很多时间写不明白哎
第一想法:反转链表肯定是 让后面的元素 指向 前面的元素,想到了需要保存两个元素,但是没有想到使用双指针,和额外的变量
看到题解后:使用双指针指向前一个元素和后一个元素,并且使用另外一个变量保存后一个元素的下一个元素,方便后移指针。考虑特殊情况 空指针
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func reverseList(head *ListNode) *ListNode {
//空链表的情况
if head == nil{
return head
}
pre := head
cur := head.Next
// 链表只有一个值的特殊情况
if cur == nil{
return head
}
head.Next = nil
for cur.Next != nil {
tmp := cur.Next
cur.Next = pre
pre = cur
cur = tmp
}
cur.Next = pre
return cur
}
今日收获:写代码之前考虑了空链表的情况,写代码过程中 发现一个元素的链表的特殊情况也需要额外处理。