代码随想录算法训练营第三天 | 203.移除链表元素707.设计链表 206.反转链表
Posted 蔚尺丈八声
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代码随想录算法训练营第三天 | 203.移除链表元素707.设计链表 206.反转链表相关的知识,希望对你有一定的参考价值。
移除链表元素
/**
* 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 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)
/*
* 思路:添加一个虚拟头结点
* 参考:
* https://leetcode.cn/problems/remove-linked-list-elements/solutions/10957/203yi-chu-lian-biao-yuan-su-by-lewis-dxstabdzew/
* https://www.bilibili.com/video/BV18B4y1s7R9/?vd_source=accc6a9ec558fa81b34f121125d4eff0
*
*
* 对于链表,主要掌握添加一个虚拟结点的操作,才能统一删除第一个结点
* 和除第一个结点外其他结点的操作。
* 注意删除结点的核心语句cur.next = cur.next.next;
*
*/
// 设置一个虚拟头结点,便于统一操作
ListNode dummNode = new ListNode(0);
dummNode.next = head;
// 指向当前结点
// 删除结点时必须知道它的前一个结点,如果是删除第一个结点,
// 就需要知道dummyNode,所以最开始要用cur指向dummyNode而不是dummyNode.next
ListNode cur = dummNode;
// 确保当前结点后还有结点
while (cur.next != null)
// 如果碰到相同的值,则跳过,否则继续向下遍历
if (cur.next.val == val)
cur.next = cur.next.next;
else
cur = cur.next;
return dummNode.next; // 删除虚拟头结点
设计链表
// class ListNode
// int val;
// ListNode next;
// ListNode()
//
// ListNode(int val)
// this.val = val;
//
//
class MyLinkedList
/*
* 思路:
*
* 参考:
* https://programmercarl.com/0707.%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8.html#%E5
* %85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC
*
* 注意链表的index是从0开始计数的
*
* 本题的不同方法:
* 1、get:直接遍历到index的位置,返回该位置的元素。
* 2、addAtHead:相当于在index=0的位置插入元素,即addAtIndex(0,val)
* 3、addAtTail:相当于在index=链表长度的位置插入元素addAtIndex(链表长度),val)
* 4、addAtIndex:排除异常情况,然后先遍历到index-1的位置,再在index处插入元素
* 5、deleteAtIndex:排除异常情况,然后先遍历到index-1的位置,再在index处删除元素
*/
ListNode head; // 虚拟头结点
int size; // 链表长度
public MyLinkedList()
head = new ListNode(0);
size = 0;
public int get(int index)
// 排除异常:索引无效(注意链表结点的索引是0,1,……size-1,位置size没有结点)
if (index < 0 || index >= size)
return -1;
ListNode cur = head; // 所遍历的结点
// 注意为了遍历到index的位置,循环条件是i<=index,不是i<index
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)
// 排除异常:如果 index 大于链表长度,则不会插入节点。
if (index > size)
return;
// 排除异常:如果index小于0,则在头部插入节点。
if (index < 0)
index = 0;
// 开始遍历到第index-1的位置
ListNode cur = head;
for (int i = 0; i < index; i++)
cur = cur.next;
// 在第index的位置插入元素
ListNode addNode = new ListNode(val);
addNode.next = cur.next;
cur.next = addNode;
// 链表长度+1
size++;
public void deleteAtIndex(int index)
// 排除异常:索引无效
if (index < 0 || index >= size)
return;
// 开始遍历到第index-1的位置
ListNode cur = head;
for (int i = 0; i < index; i++)
cur = cur.next;
// 删除元素关键语句
cur.next = cur.next.next;
// 链表长度-1
size--;
// public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
// // 循环打印链表输出
// MyLinkedList linkedList = new MyLinkedList();
// Class myClass = linkedList.getClass();
// String methods[] = "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get",
// "get", "deleteAtIndex", "deleteAtIndex", "get", "deleteAtIndex", "get" ;
// Object params[][] = 1 , 3 , 1, 2 , 1 , 1 , 1 , 3 , 3 , 0 , 0 , 0 ,
// 0 ;
// for (int i = 0; i < methods.length; i++)
// int param_length = params[i].length;
// Class c[] = new Class[param_length];
// for (int j = 0; j < param_length; j++)
// c[j] = wrapperToPrimitive.get(params[i][j].getClass());
//
// Method method = myClass.getDeclaredMethod(methods[i], c);
// method.invoke(linkedList, params[i]);
// System.out.print(methods[i]+" ");
// for(int k=0;k<params[i].length;k++)
// System.out.print(params[i][k]+" ");
//
// System.out.println();
// for (int k=0;k<linkedList.size;k++)
// System.out.print(linkedList.get(k)+" ");
//
// System.out.println();
//
//
// private static final Map<Class, Class> wrapperToPrimitive = new HashMap<Class, Class>();
// static
// wrapperToPrimitive.put(Integer.class, int.class);
// // wrVoid.class, void.class,
// // Boolean.class, boolean.class,
// // Byte.class, byte.class,
// // Character.class, char.class,
// // Short.class, short.class,
// // , int.class,
// // Long.class, long.class,
// // Float.class, float.class,
// // Double.class, double.class)
//
反转链表
// 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)
/*
* 思路:双指针,一个指针指向原链表,另一个指针指向新的链表(倒序)
*
* 参考:
* https://programmercarl.com/0206.%E7%BF%BB%E8%BD%AC%E9%93%BE%E8%A1%A8.html#%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95
*
* 首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null
* 然后就要开始反转了,首先要把cur->next节点用tmp指针保存一下,也就是保存一下这个节点
* 为什么要保存一下这个节点呢,因为接下来要改变cur->next的指向了,将cur->next指向pre,此时已经反转了第一个节点了
* 接下来,就是循环走如下代码逻辑了,继续移动pre和cur指针
* 最后,cur指针已经指向了null,循环结束,链表也反转完毕了。此时我们return pre指针就可以了,pre指针就指向了新的头结点
*
* p.s.本质上就是每一步从旧链表中摘出头结点,加在新链表的头结点之前
*/
ListNode pre = null; // 新链表
ListNode cur = head; // 原链表
ListNode tmp = null;
while (cur != null)
tmp = cur.next;// 保存下一个节点
// 把旧链表(cur)的next从旧链表中断掉,重新连到新链表的头结点(pre)之前
cur.next = pre;
// 将pre指针移动到cur的位置,也即pre指向新链表的头结点处,
// 以待下一次旧链表中取出一个头结点与其连接
pre = cur;
// 将cur指针移动到tmp(cur.next)的位置,也即cur指向旧链表的头结点处
cur = tmp;
return pre;
以上是关于代码随想录算法训练营第三天 | 203.移除链表元素707.设计链表 206.反转链表的主要内容,如果未能解决你的问题,请参考以下文章