链表所有的遍历都只能从头节点开始!
203 移除链表元素
删除链表中等于给定值 val 的所有节点。
思路:1.在原链表上进行操作 2.使用虚拟头节点进行操作 这个移除链表没啥难度 画图理解下就好了
方法一:在原链表上进行操作
class Solution {
public ListNode removeElements(ListNode head, int val) {
//头节点是要删除的值
while(head != null && head.val == val){
head = head.next;
}
//定义一个临时指针,使它指向头节点
ListNode current = head;
while(current!=null && current.next!=null){
if(current.next.val==val){
current.next = current.next.next;
}else{
current = current.next;
}
}
return head;
}
}
方法二:使用虚拟头节点操作
class Solution {
public ListNode removeElements(ListNode head, int val) {
//new一个虚拟结点
ListNode dummyNode = new ListNode();
dummyNode.next = head;
ListNode currernt = dummyNode;
while(currernt.next!=null){
if(currernt.next.val == val){
currernt.next = currernt.next.next;
}else{
currernt = currernt.next;
}
}
return dummyNode.next;
}
}
707 设计链表
在链表类中实现这些功能:
get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。
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);
}
//获取第n个节点的数值
public int get(int index) {
if(index <0 || index >= size) return -1;
ListNode current = head;
//查找index结点 因为包含虚拟头节点 所以是小于等于
for(int i =0;i<=index;i++){
current = current.next;
}
return current.val;
}
//头部插入结点
public void addAtHead(int val) {
ListNode current = head;
ListNode newNode = new ListNode(val);
newNode.next = current.next;
current.next = newNode;
size++;
}
//尾部插入结点
public void addAtTail(int val) {
ListNode newNode = new ListNode(val);
ListNode current = head;
while(current.next != null){
current = current.next;
}
current.next = newNode;
size++;
}
//第n个结点前插入
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;
}
//删除第n个结点
public void deleteAtIndex(int index) {
if(index<0|| index >= size){
return;
}
size--;
ListNode pred = head;
for(int i =0;i<index; i++){
pred = pred.next;
}
pred.next = pred.next.next;
}
}
206 反转链表
反转一个单链表。
思路:设计一个pre结点,使其指向null,反转是 current的下一个结点指向null,也就是pre,pre再等于current现在的值,current再等于current的下一个结点。 链表题强烈建议画图理解
方法一 双指针
class Solution {
public ListNode reverseList(ListNode head) {
ListNode tmp; //保存current的下一个结点
ListNode current = head;
ListNode pre = null;
while(current!=null){
tmp = current.next;
current.next = pre;
pre = current;
current = tmp;
}
return pre;
}
}
方法二 递归
递归的方式还是多需要去理清概念
class Solution {
public ListNode reverseList(ListNode head) {
return reverse(null,head);
}
private ListNode reverse(ListNode pre,ListNode cur){
if(cur == null) return pre;
ListNode tmp = null;
tmp = cur.next;
cur.next = pre;
return reverse(cur,tmp);
}
}
链表这三道题我感觉没啥难度,多画图去理解一下,递归的方法还是需要多去思考思考