代码随想录算法Day03-移除链表元素、设计链表、反转链表
移除链表元素
- 移除链表元素操作其实就是:
node.next = node.next.next,将当前元素的上一个元素指针指向当前元素的下一个元素,所以删除一个元素需要知道他的上一个元素。 - 方法一:因为需要知道上一个元素,所以头结点是一种特殊情况,需要单独处理;然后再处理剩余节点,遍历过程中指针始终指向要处理的节点的上一个节点,所以
cur初始化为head,而不是head.next。 - 方法二:使用统一的处理逻辑,也就是链表中常用的虚拟头结点的概念。创建一个虚拟节点,这个节点没有实质性的作用,只是方便我们处理头结点,让所有节点都可以找到他的前一个节点,中间处理过程和方法一相同。
public class ListNode{
int val;
ListNode next;
ListNode(int val){this.val = val;}
ListNode(int val,ListNode next){this.val = val; this.next = next;}
}
public ListNode removeNode(ListNode head,int val){
//方法一:不使用头结点
while(head != null && head.val == val){
head = head.next;
}
ListNode cur = head;
while(cur != null && cur.next != null ){
if(cur.next.val == val){
cur.next = cur.next.next;//注意这里已经将不合理元素给删除了,cur.next目前就指向要处理的元素,cur不用移动
}else{
cur = cur.next;
}
}
return head;
}
public ListNode removeNode(ListNode head,int val) {
//使用虚拟头结点
ListNode dummy = new ListNode(0,head);
ListNode cur = dummy;
while(cur != null && cur.next != null){
if(cur.next.val == val) {
cur.next = cur.next.next;
} else {
cur = cur.next;
}
}
return dummy.next;
}
设计链表
这道题做的时候总是出错,边界条件处理的时候还是没有得心应手
- 首先是整体的设计,要求是写一个MyLinkedList类,这个类要求实现几个方法,一开始这个设计这个类成员变量的时候以为是写
val、next这些呢,后面又想着链表得需要头节点吧head,处理的时候还需要虚拟头节点dummy,殊不知这其实应该设计成两个类,一个类用来存放节点的信息,外面的类用来存放链表的特殊节点(头节点或者虚拟头节点)。 - 然后是边界上处理的时候,提交了好几次都是空指针,是因为遍历寻找目标节点的时候没有边遍历边验证一下节点是否是空的。
下面再重新手撕下代码
public class ListNode {
int val;
ListNode next;
public ListNode(int val) {
this.val = val;
}
}
public class MyLinkedList{
ListNode dummy;
public MyLinkedList(){
dummy = new ListNode(0);
}
//1. 找到第index节点
public int get(int index){
ListNode cur = dummy.next;
for(int i = 0;i < index;i++){
if(cur == null) {
//这里需要验证
return -1;
}
cur = cur.next;
}
// 返回的时候也需要验证,因为当前cur是否为null不清楚
return cur == null ? -1 : cur.val;
}
//2. 头结点前添加节点
public int addBeforeHead(int val) {
ListNode node = new ListNode(val);
node.next = dummy.next;
dummy.next = node;
}
//3. 第n个节点前添加节点
public void addBeforeIndex(int index){
//找到第index-1的节点,所以cur初始化为dummy
ListNode cur = dummy;
for(int i = 0;i < index;i++){
if(cur == null) {
//验证cur不等于null
return;
}
}
// 验证inbdex处的节点是否合理
if(cur.next == null) {
return;
}
ListNode node = new ListNode(val);
node.next = cur.next;
cur.next = node;
}
//4. 尾部添加节点
public void addTail(int val) {
ListNode node = new ListNode(val);
// 寻找尾节点
ListNode cur = dummy;
while(cur.next != null) {
cur = cur.next;
}
cur.next = node;
}
//5. 删除第index节点
public void deleteIndex(int index){
ListNode cur = dummy;
for(int i = 0;i < index;i++) {
if(cur == null) {
return;
}
}
if(cur.next == null) {
return;
}
cur.next = cur.next.next;
}
}
反转链表
这道题写过很多次了,这里写一个之前没写过的方法
public ListNode reverseList(ListNode head){
return reverse(head,null);
}
public ListNode reverse(ListNode cur,ListNode pre){
//递归终止条件
if(cur == null) {
return pre;
}
ListNode t = cur.next;
cur.next = pre;//反转
return reverse(t,cur);
}
浙公网安备 33010602011771号