代码随想录算法训练营第三天 | 203.移除链表元素,206.反转链表,707.设计链表 9.23
链表概念
- 数组是在内存中是连续分布的,但是链表在内存中可不是连续分布的
- 链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)
203. 移除链表元素
虚拟头节点
- 在Head前创建一个虚拟头节点指向head 这样删除操作就可以统一
- 用一个cur去遍历链表
- 判断cur.next.val是否等于 target
- 注意点是 在做删除操作时 cur一定是在需要删除指针的前一个节点
- 返回的时候要注意 原来的Head可能已经被删除 所以需要返回dummyhead.next
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummyHead = new ListNode(-1,head);
ListNode cur = dummyHead;
while(cur.next!=null){
if(cur.next.val==val){
cur.next=cur.next.next;
}else{
cur=cur.next;
}
}
return dummyHead.next;
}
}
206.反转链表
双指针
- 首先想清楚反转后链表尾结点指向null 所以一开始slow指针指向Null 然后fast指向head 将fast.next指向slow进行反转操作
- 反转操作就是 将后一位节点指向前一位节点 但是必须先用一个变量暂存 后一位节点的后一位节点
class Solution {
public ListNode reverseList(ListNode head) {
ListNode fast = head;
ListNode slow = null;
ListNode temp;
while(fast!=null){
temp = fast.next;
fast.next = slow;
slow = fast;
fast = temp;
}
return slow;
}
}
递归法
- 思路与双指针一致 只不过循环遍历操作用函数递归来实现
class Solution {
public ListNode reverseList(ListNode head) {
return reverse(head,null);
}
public ListNode reverse(ListNode fast,ListNode slow){
if(fast==null){
return slow;
}
ListNode temp;
temp = fast.next;
fast.next = slow;
return reverse(temp,fast);
}
}
707.设计链表
统一使用虚拟头节点操作
获取链表中第n个值
- 用一个循环遍历链表 找到Index位置的节点
在第n个位置插入新节点
- 首先要遍历到第n个位置前一个位置,这样才能做插入操作
删除第n个位置的节点
- 遍历到第n个位置前一个位置 可以从dummyhead开始遍历
class ListNode {
int val;
ListNode next;
ListNode(){}
ListNode(int val) {
this.val=val;
}
}
class MyLinkedList {
int size;
ListNode head;
public MyLinkedList() {
size = 0;
head = new ListNode(0);
}
public int get(int index) {
if (index < 0 || index >= size) {
return -1;
}
ListNode currentNode = head;
for (int i = 0; i <= index; i++) {
currentNode = currentNode.next;
}
return currentNode.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 > size) {
return;
}
if (index < 0) {
index = 0;
}
size++;
ListNode pred = head;
for (int i = 0; i < index; i++) {
pred = pred.next;
}
ListNode toAdd = new ListNode(val);
toAdd.next = pred.next;
pred.next = toAdd;
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) {
return;
}
size--;
if (index == 0) {
head = head.next;
return;
}
ListNode pred = head;
for (int i = 0; i < index ; i++) {
pred = pred.next;
}
pred.next = pred.next.next;
}
}
总结
- 对于边界范围条件的处理 可以用边界值代入 看看变量结果为多少 判断是否正确
- 比如代入index = 0 看看cur 遍历到哪里
|