移除链表元素(Java)
做链表相关题目要求返回链表时,只返回头节点即可。
使用原来链表迭代
注意:
- 头节点的处理:保证头结点不能为目标值。同时链表中涉及到next,所以时刻关注head.next是不是null(尾结点的next指向null)
- 其他节点需要注意进行迭代时,需要用一个临时变量代替head,因为最后要返回head,必须保留。而临时变量代替创建时,不需要单独创建空间,直接ListNode pre = head即可。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeElements(ListNode head, int val) {
while(head != null && head.val == val){ //妙哉--保证了head不可能为val,但是可以是空
head = head.next;
}
if(head == null){
return null;
}
ListNode pre = new ListNode();
pre = head; //这两步可以直接合并
while(pre.next != null){
if(pre.next.val != val){
pre = pre.next;
}
else{
pre.next = pre.next.next;
}
}
return head;
}
}
设置虚拟头节点
方便很多,但是需要创建一个虚拟的头节点,并将其指向head;
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummyhead = new ListNode();// 需要创建:原因是目前没有
dummyhead.next = head;
ListNode temp = dummyhead;
if(head == null){
return null;
}
while(temp.next != null){ //先要保证temp本身不是null
if(temp.next.val == val){
temp.next = temp.next.next;
}
else{
temp = temp.next;
}
}
return dummyhead.next;
}
}
设计链表(Java)
单链表
注意:
- 首先要自己定义一个单链表/双链表类,常定义在外面(所有要使用head都这样);
- 定义一个类时有属性方法,属性常常在构造函数中被初始化;
- 链表操作的两种方式:直接使用原来的链表来进行操作或设置一个虚拟头结点在进行操作(常采用虚拟节点)
- 一旦有了虚拟头结点,就不用对index=0做特殊处理了
- 在链表中查找是通过循环不断找到next(只知道头节点); 如果要进行删除和增加操作,需要找到index的前一个
- 其他细节见代码
class MyLinkedList {
private Node head;
private int size; //链表中实际元素个数
//初始化指的是初始化属性
public MyLinkedList() {
this.size = 0;//(原因是初始化创建的头节点是虚拟的)
this.head = new Node(0);
}
public int get(int index) {
//判断无效情况
if(index < 0 || index >= size){ // 因此必须要将size作为属性
return -1;
}
Node temp = head; // 禁止直接使用head
for(int i = 0; i <= index; i++){
temp = temp.next;
}
return temp.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 > size){
return; // 表示直接退出该方法
}
Node newNode = new Node(val); // 需要创建该节点才能加入链表
Node temp = head;
for(int i = 0; i < index; i++){ // 当index=0或index=size都可以实现
temp = temp.next;
}
newNode.next = temp.next; //先写后边的
temp.next = newNode;
size++; //!!!不要忘记
}
public void deleteAtIndex(int index) {
if(index < 0 || index >= size){
return;
}
Node temp = head;
for(int i = 0; i < index; i++){
temp = temp.next; // 链表中进行查找的核心代码
}
temp.next = temp.next.next;
size--;
}
}
class Node{
int val;
Node next;
public Node(int val){
this.val = val;
}
}
/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList obj = new MyLinkedList();
* int param_1 = obj.get(index);
* obj.addAtHead(val);
* obj.addAtTail(val);
* obj.addAtIndex(index,val);
* obj.deleteAtIndex(index);
*/
双链表不在此赘述,需要注意的是:
- 需要在初始化时将头尾结点相连
- 查询时,可以判断index是离头更近还是离尾更近
- 增加和删除时,一定注意连接方式!!!
反转链表(Java)
核心:只改变指针方向
需要有两个变量不断循环,注意循环终止条件
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
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;
}
}
写博客的目的是每日督促并记录刷题,也欢迎大家批评指正~(day3)