Day3| 203.移除链表元素、707.设计链表、206.反转链表

文章链接

先总结一下数组部分内容:解决问题的主要办法就是利用双指针的思想,不管是滑动窗口还是前缀和。当遇到判断遍历区间需要不断移动时,双指针就会被广泛运用。

新建链表

public class Node<T>{
    //节点存储数据
    public T Data{get;set;}
    //指向下一个节点的引用
    public Node<T> Next{get;set;}
    //节点的构造函数,用于初始化节点
    public Node(T data){
        Data=data;
        next=null;//初始没有下一个节点,所以为空
     }
}

解决针对头结点和其他结点删除操作不一致的问题:创建虚拟头结点(dummyHead)

203.移除链表元素

思路:(具体实现没有什么难度)

  1. 新建虚拟头节点、用来遍历的节点temp

  2. 遍历查找目标值val,遇到就用temp跳过

  3. 最后返回dummyHead.next

public class Solution {
    public ListNode RemoveElements(ListNode head, int val) {
        ListNode dummyNode = new ListNode(0,head);
        ListNode temp = dummyNode;
        while(temp.next!=null){
            if(temp.next.val==val){
                temp.next=temp.next.next;
            }
            else{
                temp=temp.next;
            }
        }
        return dummyNode.next;
    }
}

707.设计链表

对链表的基本操作:

  1. 初始化

  2. 获取下标结点的值

  3. 头插、尾插、指定位置插入

  4. 删除结点

在删除DeleteAtIndex方法中,一直写错,容易混淆,假设要删除的元素是b,要注意删除需要找到待删除前一个元素a,并将a指向c,所以定义的temp1应该指向虚拟头结点dummyHead而不是dummyHead.next.

public class MyLinkedList {
    ListNode dummyNode;
    int count;


    public MyLinkedList() {
        dummyNode=new ListNode(0);
        count=0;
    }

    
    public int Get(int index) {
        if(index<0||index>=count){
            return -1;
        }
        ListNode temp1=dummyNode.next;
        for(int i=0;i<index;i++){
            temp1=temp1.next;
        }
        return temp1.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;
        }
        ListNode temp1=dummyNode;
        for(int i=0;i<index;i++){
            temp1=temp1.next;
        }
        ListNode temp2=new ListNode(val);
        temp2.next=temp1.next;
        temp1.next=temp2;
        count++;
    }
    

    public void DeleteAtIndex(int index) {
        if(index<0||index>=count){
            return;
        }
        ListNode temp1=dummyNode;
        for(int i=0;i<index;i++){
            temp1=temp1.next;
        }
        temp1.next=temp1.next.next;
        count--;
    }
}

206.反转链表

双指针法:先将cur指向pre,再不断前移pre和cur指针

public class Solution {
    public ListNode ReverseList(ListNode head) {
        ListNode pre=null;
        ListNode cur=head;
        while(cur!=null){
            ListNode temp1=cur.next;
            cur.next=pre;
            pre=cur;
            cur=temp1;
        }
        return pre;
    }
}

递归:在每次ReverseList过程中,记录ReverseList(1)、ReverseList(2)、ReverseList(3)的值,在head=3时,return3。将这个3值返回给ReverseList函数,接着往下运行head.next.next=head;等语句。这时3→2调转成功,返回ListNode newNode = ReverseList(head.next);语句,将2值返回,接着运行head.next.next=head;等语句,这时3→2→1调转成功。

假设head=2

head.next.next = head; // 即 3.next = 2

head.next = null; // 断开原来的 2 → 3

表达式意思
head当前节点
head.next下一节点
head.next.next = head让“下一节点”的 next 指回当前节点,实现反转
public class Solution {
    public ListNode  ReverseList(ListNode head) {
        if(head==null||head.next==null){
            return head;
        }
        ListNode newNode = ReverseList(head.next);
        head.next.next=head;
        head.next=null;
        return newNode;
    }
}

总结:

虽然是二刷,还是有不少地方没有考虑到,一些思路没有理解透彻

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值