您现在的位置是:首页 >其他 >代码随想录算法训练营day3网站首页其他
代码随想录算法训练营day3
简介代码随想录算法训练营day3
Day3
移除链表元素
题目
题意:删除链表中等于给定值 val 的所有节点。
示例 1: 输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]
示例 2: 输入:head = [], val = 1 输出:[]
示例 3: 输入:head = [7,7,7,7], val = 7 输出:[]
思路
-
让节点next指针直接指向下下一个节点
-
链表操作的两种方式
- 直接使用原来的链表来进行删除操作。
- 设置一个虚拟头结点在进行删除操作。
代码
解法一:使用虚拟头结点
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode res = new ListNode(0);
res.next = head;
ListNode cur = res;
while(cur != null && cur.next != null){
if(cur.next.val == val){
cur.next = cur.next.next;
} else {
cur = cur.next;
}
}
return res.next;
}
}
解法二:原链表操作删除
class Solution {
public ListNode removeElements(ListNode head, int val) {
/**
* 原链表操作
*/
// 处理头结点相等的情况
while (head != null && head.val == val) {
head = head.next;
}
if (head == null) {
return head;
}
ListNode cur = head;
while(cur != null && cur.next != null){
if(cur.next.val == val){
cur.next = cur.next.next;
} else {
cur = cur.next;
}
}
return head;
}
}
设计链表
思路
- 在链表类中实现这些功能:
- get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
- addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
- addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
- addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
- deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。
- 移动可以通过复用addAtIndex和deleteAtIndex
链表操作的两种方式:
- 直接使用原来的链表来进行操作。
- 设置一个虚拟头结点在进行操作。
代码
class MyLinkedList {
class ListNode {
int val;
ListNode next;
ListNode(){}
ListNode(int val) { this.val = val; }
}
ListNode res = new ListNode(0);
int size;
public MyLinkedList() {
res = new ListNode(0);
size = 0;
}
public int get(int index) {
if (index < 0 || index >= size) {
return -1;
}
ListNode cur = res;
// 包含一个虚拟头节点,所以查找第 index+1 个节点
for (int i = 0; i <= index; i++) {
cur = cur.next;
}
return cur.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 > size){
return;
}
if (index < 0){
index = 0;
}
ListNode cur = res;
for (int i = 0; i < index; i++) {
cur = cur.next;
}
ListNode newNode = new ListNode(val);
newNode.next = cur.next;
cur.next = newNode;
size++;
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) {
return;
}
size--;
if (index == 0) {
res = res.next;
return;
}
ListNode cur = res;
for (int i = 0; i < index ; i++) {
cur = cur.next;
}
cur.next = cur.next.next;
}
}
反转链表
思路
首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null。
然后就要开始反转,首先要把 cur->next 节点用tmp指针保存一下,也就是保存一下这个节点。
cur->next = pre, pre移动到cur的位置,cur移动到下一个结点(tmp)
代码
双指针法
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while(cur != null){
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}
递归法
递归:
1,递归出口(cur != null)
2,这一层的处理逻辑(两结点交换)
3,去下一层的函数
class Solution {
public ListNode reverseList(ListNode head) {
return reverse(null, head);
}
public ListNode reverse(ListNode pre, ListNode cur){
if (cur == null) return pre;
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
return reverse(pre, cur);
}
}
class Solution {
public ListNode reverseList(ListNode head) {
return reverse(null, head);
}
public ListNode reverse(ListNode pre, ListNode cur){
if (cur == null) return pre;
ListNode next = cur.next;
cur.next = pre;
return reverse(cur, next);
}
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。