链表自记小知识:因为每个节点都存在下一个节点的地址,所以我们对链表进行操作只需要找到head节点即可,但操作过程中不免会更改head存储的地址,导致无法对该链表进行重复操作,所以需要一个临时节点代替head进行操作
203.移除链表元素
该题实际是链表的删除
所以我们需要考虑头结点的删除方法
方法一:将头结点head向后移一位
public class Solution
{
public ListNode RemoveElements(ListNode head, int val)
{
while(head!=null&&head.val==val)
{
head=head.next;//符合条件,删除头结点
}
if(head==null)//指向null,提前退出
{
return head;
}
ListNode temp = head;
while(temp.next != null)//非头结点的移除
{
if(temp.next.val == val)
{
temp.next = temp.next.next;
}
else
{
temp = temp.next;
}
}
return head;
}
}
方法二:设置一个虚拟头结点
这个方法不用区分头结点还是非头结点,直接统一处理方法。
public class Solution
{
public ListNode RemoveElements(ListNode head, int val)
{
ListNode dummyHead = new ListNode(0,head);//创建虚拟头结点,并将next指针指向头结点
ListNode temp = dummyHead;
while(temp.next != null)
{
if(temp.next.val == val)
{
temp.next = temp.next.next;
}
else
{
temp = temp.next;
}
}
return dummyHead.next;
}
}
707.设计链表
class ListNode {
public int val;//存储数据
public ListNode next;//指向下一节点的 指针
public ListNode(int val){this.val=val};
//节点的构造函数,初始化节点
public ListNode(int val=0, ListNode next=null)
{
this.val = val;
this.next = next;
}
}
public class MyLinkedList
{
ListNode dummyHead;//虚拟头结点
int count;//链表长度
public MyLinkedList()
{
dummyHead =new ListNode(0);
count = 0;
}
public int Get(int index)
{
if (index < 0 || count <= index)
return -1;
ListNode cur = dummyHead;
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(count, val);
}
public void AddAtIndex(int index,int val)
{
if (index > count) return;
index = Math.Max(0, index);//小于0在头部插入节点
count++;
ListNode tmp= dummyHead;
for (int i = 0; i < index; i++)
{
tmp = tmp.next;
}
ListNode tmp2 = new ListNode(val);
tmp2.next = tmp.next;
tmp.next = tmp2;
}
public void DeleteAtIndex(int index)
{
if (index >= count || index < 0) return;
ListNode tmp = dummyHead;
for (int i = 0; i < index; i++)
{
tmp = tmp.next;
}
tmp.next = tmp.next.next;
count--;
}
}
206.反转链表
双指针法:需要两个指针改变链表的指向,看图更好理解
public class Solution {
public ListNode ReverseList(ListNode head) {
ListNode tmp;//储存cur.next确保按原链表的结构进行
ListNode cur = head;
ListNode pre=null;
while(cur!=null){
tmp=cur.next;//储存cur.next
cur.next=pre;
pre=cur;
cur=tmp;//进行下一节点反转的准备
}
return pre;
}
}
递归法:
也比较好理解,将两个参数赋值为null,head节点然后不断的向下走,直到cur节点指向null
public class Solution {
public ListNode Reverse(ListNode pre,ListNode cur){
if(cur==null)
{
return pre;
}
ListNode tmp;
tmp = cur.next;
cur.next=pre;
return Reverse(cur,tmp);//相当于双指针法后两步的赋值
}
public ListNode ReverseList(ListNode head) {
return Reverse(null,head);
}
}