1. 链表的定义
public class ListNode {
// 结点的值
int val;
// 下一个结点
ListNode next;
// 节点的构造函数(无参)
public ListNode() {
}
// 节点的构造函数(有一个参数)
public ListNode(int val) {
this.val = val;
}
// 节点的构造函数(有两个参数)
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
力扣题目链接:移除链表元素
有三种解法:
- 遍历链表并删除,这样需要单独讨论头节点,这就引出解法2
- 虚拟头节点,在头节点前加一个,这样就可以统一操作
- 递归,对节点进行递归讨论
/**
* 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 = head.next;
}
ListNode prev = head;
while(prev != null && prev.next != null){
if(prev.next.val == val){
prev.next = prev.next.next;
}else{
prev = prev.next;
}
}
return head;
}
}
//解法二
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummy = new ListNode();
dummy.next = head;
ListNode pre = dummy;
while(pre != null && pre.next != null){
if(pre.next.val == val){
pre.next = pre.next.next;
}else{
pre = pre.next;
}
}
return dummy.next;
}
}
//方法三
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head == null){
return head;
}else if(head.val == val){
return removeElements(head.next,val);
}else{
head.next = removeElements(head.next,val);
return head;
}
}
}
2. 设计链表
注意使用虚拟头节点。
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 MyLinkedList {
int size;
//此处的head是虚拟头节点,方便后续操作
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) {
ListNode node = new ListNode(val);
node.next = head.next;
head.next = node;
size++;
}
public void addAtTail(int val) {
ListNode currentNode = head;
ListNode node = new ListNode(val);
while(currentNode.next != null){
currentNode = currentNode.next;
}
currentNode.next = node;
size++;
}
public void addAtIndex(int index, int val) {
if(index > size){
return;
}
if(index < 0){
index = 0;
}
ListNode node = new ListNode(val);
ListNode pre = head;
for(int i = 0;i < index; i++){
pre = pre.next;
}
node.next = pre.next;
pre.next = node;
size++;
}
public void deleteAtIndex(int index) {
if(index < 0 || index >= size){
return;
}
ListNode pre = head;
for(int i = 0;i < index; i++){
pre = pre.next;
}
pre.next = pre.next.next;
size--;
}
}
/**
* 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);
*/
3. 反转链表
- 注意pre节点不需要连上next
- 用递归的思想。出口是cur == null,每次的返回值并没有被用到,要层层返回给调用处。
//解法一
class Solution {
public ListNode reverseList(ListNode head) {
ListNode cur = head;
ListNode temp = null;
ListNode pre = null;
while(cur != null){
temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
}
class Solution {
public ListNode reverseList(ListNode head) {
return reverse(null, head);
}
public ListNode reverse(ListNode pre, ListNode cur){
if(cur == null){
return pre;
}
ListNode temp = new ListNode();
temp = cur.next;
cur.next = pre;
return reverse(cur, temp);
}
}