代码随想录算法训练营第三天 | LeetCode203.移除链表元素 ,707.设计链表,206.反转链表
一、 LeetCode203.移除链表元素
2. 学习资料:
3. 思路
- 因为头结点的值可能与目标值相等,因此我们需要使用虚拟头结点。
- 需要用到两个指针pre指针(指向前驱节点)和cur指针(指向当前节点)
- 循环链表
- 遇到与目标值相同值的节点:
a. pre.next指向cur.next ( 当前节点的下一节点 )
b. 用临时节点(t)存储cur.next(当前节点的下一个节点)
c. 然后让当前节点指向 null (cur.next = null)
d. 移动cur指针指向下一节点 ( cur = t) - 遇到与目标值不同的节点:
a. pre移动到一下个节点
b. cur 移动到下一个节点
- 返回虚拟头结点的下一个节点(dummyHead.next)
4. 代码
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head == null){
return null;
}
ListNode dummyHead = new ListNode(Integer.MIN_VALUE);
dummyHead.next = head;
ListNode pre = dummyHead;
ListNode cur = head;
while(cur!=null){
if(cur.val == val){
ListNode temp = cur.next;
cur.next = null;
pre.next = temp;
cur = temp;
}else{
pre = pre.next;
cur = cur.next;
}
}
return dummyHead.next;
}
}
二、 LeetCode707.设计链表
2. 学习资料:
3. 思路
- 这个自己实现的链表我用了一个虚拟头节点,相当于浪费了一个节点的空间,好处是简化了删除头节点时的步骤。
- 因为有虚拟头结点,所以在获取元素的时候,要考虑索引为0的意思是获取真正的头节点,所以需要让虚拟头节点往后移动一个节点。
- 因为有虚拟头节点的原因,所以要考虑到的边界问题就是当索引等于size的情况,有可能会是非法的。
- 因为要实现在指定索引位置插入节点,所以实现在插入头节点方法和插入尾节点方法时可以复用这个方法,减少代码的书写。
4. 代码
class ListNode{
int val;
ListNode next;
public ListNode(){
}
public ListNode(int val){
this.val = val;
}
}
class MyLinkedList {
int size;
ListNode head;
public MyLinkedList() {
size = 0;
head = new ListNode(-1);
}
public int get(int index) {
if(index < 0 || index >= size){
return -1;
}
ListNode cur = head;
for(int i=0;i<=index;i++){
cur = cur.next;
}
return cur.val;
}
public void addAtHead(int val) {
addAtIndex(0,val);
}
public void addAtTail(int val) {
addAtIndex(size,val);
}
public void addAtIndex(int index, int val) {
if(index <0){
index = 0;
}
if(index > size){
return ;
}
size++;
ListNode pre = head;
for(int i = 0; i < index; i++){
pre = pre.next;
}
ListNode t = pre.next;
ListNode node = new ListNode(val);
pre.next = node;
node.next=t;
}
public void deleteAtIndex(int index) {
if(index < 0 || index >= size){
return ;
}
size--;
ListNode pre = head;
for(int i=0;i<index;i++){
pre = pre.next;
}
ListNode deleteNode = pre.next;
ListNode tempNode = deleteNode.next;
deleteNode.next = null;
pre.next = tempNode;
}
}
三、 LeetCode206.反转链表
2. 学习资料:
3. 思路
- pre 指向前一个元素,初始化时为null。
- cur指针指向当前元素
- 循环链表,让临时结点temp 存储当前节点的下一个节点
- cur.next 指向 前一个元素pre
- 移动pre指针到下一个节点,就是pre = cur
- 移动cur到下一个节点,就是cur = temp
- 这里需要注意,因为pre指针初始化时是null,所以移动pre指针是pre=cur而不是使用pre.next = cur, 后者会造成空指针异常
4. 代码
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while(cur != null){
ListNode temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
}