参考文献链接:代码随想录
本人代码是Java版本的,如有别的版本需要请上代码随想录网站查看。
203. 移除链表元素
[力扣题目链接](https://leetcode.cn/problems/binary-search/)
解题思路
这道题目还是比较简单的,目的是为了练习链表的删除操作。题目简要意思就是把链表中对应值的节点删除。
还记得第一次做这道题的时候一看题目这么简单,不就是把上一个节点的next指向下一个节点吗,结果操作一顿之后发现还是不能通过。后来看了题解才明白。
这次做的话就很清晰了,在思考这类问题时要多想想头和尾这些特殊部位。比如这道题的头节点都没有上一个节点,你还怎么让他的上一个节点指向下一个节点呢?
所以要么特殊处理,要么加入虚拟头节点
虚拟头节点
虚拟头节点的意思就是去给当前链表加一个头节点,这样你的剩余节点都可以当作普通节点处理。
代码如下
/**
* 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) {
if(head == null){
return head;
}
//定义一个虚拟头节点,让其指向head真正的头节点
ListNode vir = new ListNode();
vir.next = head;
//定义一个临时节点去进行循环操作
ListNode tmp = vir;
while(tmp.next != null){
//如果临时节点的下一个节点val值等于目标值,那么就进行删除操作。
if(tmp.next.val == val){
tmp.next = tmp.next.next;
}else{
//否则tmp++
tmp = tmp.next;
}
千万不要把else忘记,我做的时候以为不管怎么样都得tmp++,后来思考发现如果进行了删除操作后,那么tmp的下一个节点变化了,还得继续判断它,不能tmp++。
}
return vir.next;
}
}
707.设计链表
解题思路
这道题目是刚接触链表一个很好的练手题,因为它涵盖了链表几乎所有操作。我们直接来上代码吧!
代码
要学会怎么定义链表,平时做题都是力扣帮忙定义好了,但面试万一不会定义就糟糕了。
其实只要明白了一个方法,其余的相差无几。中心思想就是通过节点.next去移动,直到自己想操作的位置进行操作,思路简单,注意一些特殊位置的判断即可
class ListNode {
int val;
ListNode next;
ListNode(){}
ListNode(int val) {
this.val=val;
}
}
class MyLinkedList {
//长度
int size;
//虚拟头节点
//为了操作方便统一我们还是引入虚拟头节点
ListNode head;
public MyLinkedList() {
//初始化,size为0,只有一个虚拟头节点
size = 0;
head = new ListNode();
}
public int get(int index) {
//判断index的合法性
if(index < 0 || index >= size){
return -1;
}
//通过index移动tmp,直到想要的节点
ListNode tmp = head.next;
for(int i = 0;i < index;i++){
tmp = tmp.next;
}
return tmp.val;
}
public void addAtHead(int val) {
//虚拟头节点立大功,不用考虑别的,直接添加即可
ListNode add = new ListNode(val);
ListNode tmp = head.next;
head.next = add;
add.next = tmp;
size++;
}
public void addAtTail(int val) {
//如果size为0,直接交给头节点处理就好
if(size == 0){
addAtHead(val);
return;
}
//其实跟get方法本质一样,移动到相应位置进行操作即可
ListNode tmp = head.next;
for(int i = 0;i < size - 1;i++){
tmp = tmp.next;
}
tmp.next = new ListNode(val);
size++;
}
public void addAtIndex(int index, int val) {
if(index > size){
return;
}
if(index == 0){
addAtHead(val);
return;
}
ListNode tmp = head.next;
for(int i = 0;i < index - 1;i++){
tmp = tmp.next;
}
ListNode next = tmp.next;
tmp.next = new ListNode(val);
tmp.next.next = next;
size++;
}
public void deleteAtIndex(int index) {
if(index < 0 || index >= size){
return;
}
ListNode tmp = head;
for(int i = 0;i < index;i++){
tmp = tmp.next;
}
tmp.next = tmp.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);
*/
206.反转链表
解题思路
对于这种反转类的题目我想到的是栈和递归法。具体如何反转很简单,难的是想法和栈的使用。
栈
首先先介绍一下栈的概念和基本使用:
它是Package java.util下的Class Stack,它是一个先进后出的数据结构。
构造方法:
Stack() Creates an empty Stack.
方法
Modifier and Type | Method | Description |
---|---|---|
boolean | empty() | 判断栈是否为空 |
E | peek() | 查看栈顶部的对象并返回 |
E | pop() | 移除栈顶部的对象并返回 |
E | push(E item) | 压栈:将一个元素放入栈顶 |
int | search(Object o) | 查找对象。 |
相信看完这些官方api就很好解决这道题目了
代码如下:
/**
* 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) {
if(head == null){
return head;
}
Stack<ListNode> stack = new Stack<>();
//将每个节点依次放入栈中
while(head != null){
stack.push(head);
head = head.next;
}
//创建新的头节点,并依次接收弹出的元素排成新的链表
ListNode newHead = stack.pop();
ListNode tmp = newHead;
while(stack.size()!=0){
tmp.next = stack.pop();
tmp = tmp.next;
if(stack.size()==0){
tmp.next = null;
}
}
return newHead;
}
}
递归法
/**
* 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) {
reverse(null,head);
}
public ListNode reverse(ListNode pre,ListNode cur){
if(cur == null){
return pre;
}
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
return reverse(pre,cur);
}
}