C#力扣链表题目逐行讲解 初学者必看(题目会更新)

在大部分程序员眼里是不起眼的小题目,我自己是做了挺久的,希望能帮到你
203. 移除链表元素
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例 1:
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

分析:不知道初学者有没有next左右两边分不清什么意思的情况,我是这样理解的,比如这道题中的temp它本质上就是一个节点,所以temp = xxxx,这里就代表的是temp节点的值等于xxxx;那temp.next = xxxx,这里temp.next可以理解为temp指向下一个节点的指针,xxxx此时代表的是目标节点。再简单点来说,左边.next都是代表指针,右边.next都是代表节点。
回到题目,本题利用虚拟头节点的思想,将头节点的前一个节点设置为虚拟头,同时对temp节点赋值虚拟头节点,为什么要有temp这个临时节点呢?因为题目最终要返回的就是头节点,所以用temp代表头节点,参与运算,最后返回头节点的值,值也不会被改变。
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public int val;
 *     public ListNode next;
 *     public ListNode(int val=0, ListNode next=null) {
 *         this.val = val;
 *         this.next = next;
 *     }
 * }
 */
public class Solution {
    public ListNode RemoveElements(ListNode head, int val) {
        ListNode dummyHead = new ListNode(0,head);
        ListNode temp = dummyHead;
        while(temp.next != null)
        {
            if(temp.next.val == val)
            {
                temp.next = temp.next.next;
            }
            else
            {
                temp = temp.next;
            }
        }
        return dummyHead.next;
    }
}
    }
}

206. 反转链表
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

分析:pre(preview)用来代表前一个节点(null),curr(current)代表当前节点,比如从第一个节点 也就是1开始反转,需要用temp先记录一下2的值(因为1反转的时候,连接2的这个指针会断开)将curr.next指针指向prev,将pre = curr,也就是对pre节点赋值curr节点,将pre节点移动到curr节点,同时curr也移动到temp节点。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public int val;
 *     public ListNode next;
 *     public ListNode(int val=0, ListNode next=null) {
 *         this.val = val;
 *         this.next = next;
 *     }
 * }
 */
public class Solution {
    public ListNode ReverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while(curr != null)
        {
            ListNode temp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = temp;
        }
        return prev;
    }
}

707. 设计链表

你可以选择使用单链表或者双链表,设计并实现自己的链表。

单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。

如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。

实现 MyLinkedList 类:

MyLinkedList() 初始化 MyLinkedList 对象。
int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。
void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。
void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。
void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。

示例:

输入
[“MyLinkedList”, “addAtHead”, “addAtTail”, “addAtIndex”, “get”, “deleteAtIndex”, “get”]
[[], [1], [3], [1, 2], [1], [1], [1]]
输出
[null, null, null, null, 2, null, 3]

解释
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.addAtHead(1);
myLinkedList.addAtTail(3);
myLinkedList.addAtIndex(1, 2); // 链表变为 1->2->3
myLinkedList.get(1); // 返回 2
myLinkedList.deleteAtIndex(1); // 现在,链表变为 1->3
myLinkedList.get(1); // 返回 3

分析:题目很长 但是别害怕,本质其实就是实现几个方法
1.获取链表第index个节点的数值
2.在链表的最前面插入一个节点
3.在链表的最后面插入一个节点
4.在链表第index个节点前面插入一个节点
5.删除链表的第index个节点
本题我使用的是单链表,具体都在代码中逐行分析了

public class ListNode
{
	//首先,我们需要创建一个“概念”,也就是类,就是节点
	//节点中需要包含两个元素,一个是值val,一个是next代表下一个节点
    public int val;
    public ListNode next;
    //构造函数中初始化两个变量,next指向null就行,节点我们自己赋值
    public ListNode(int val) 
    {
        this.val = val;
        this.next = null;
    }
}
public class MyLinkedList
{
	//链表需要头节点和元素数量
    ListNode head;
    int count;

	//构造函数初始化
    public MyLinkedList()
    {
        head = null;
        count = 0;
    }
	
	//首先是根据索引得到元素
    public int Get(int index)
    {
    	//index在本题中是从0开始的,index = count = 1 是错的
    	//而不是其他题目中index从1开始,所以此处是>=,都要返回-1
        if(index < 0 || index >= count) return - 1;
        ListNode curr = head;
        //for循环就是用来移动curr节点的,如果上面两道题也会做的话,这里可以看懂
        for(int i = 0; i < index; i++)
        {
            curr = curr.next;
        }
        //头节点不会进入for循环,所以直接会返回值
        return curr.val;
    }

    public void AddAtHead(int val)
    {
        AddAtIndex(0, val);
    }

    public void AddAtTail(int val)
    {
        AddAtIndex(count, val);
    }
	
	//上面两个方法都可以由下面这个方法来实现
	
	//在链表第index个节点前面插入一个节点
    public void AddAtIndex(int index, int val)
    {
    	//注意这里是不能=的,因为AddAtHead是添加头节点的方法,会传入index = 0
        if(index > count) return;
		//以下三行是固定的,就是声明一个虚拟头节点,让它的指针指向头节点
		//同时curr拿到虚拟头节点,开始进行运算
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        ListNode curr = dummyHead;
		//创建要插入的节点
        ListNode newNode = new ListNode(val);
        for(int i = 0; i < index; i++)
        {
            curr = curr.next;
        }
        //这里举个例子,比如链表是虚拟头,4,5,6,要在4前插入一个节点
        //那就需要让新节点指向4,虚拟头指向新节点即可(这个顺序不能变)
        //如果让虚拟头直接指向新节点的话,那4就会丢失
        //****************************************
        //将新节点的下一个指针 指向 头节点
        newNode.next = curr.next;
        //头节点的下一个指针 指向 新节点
        curr.next = newNode;
        //链表元素+1
        count++;
        //将头节点更新一下
        head = dummyHead.next;
    }

	//删除链表的第index个节点
    public void DeleteAtIndex(int index)
    {
    	//自己尝试理解一下
        if(index >= count) return;
        //上述一样的几行代码
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        ListNode curr = dummyHead;
        for(int i = 0; i < index; i++)
        {
            curr = curr.next;
        }
        //移除头节点其实就是将虚拟头节点指向 头节点的下一个节点即可
        //头节点就会丢失
        //然后赋值新的头节点
        curr.next = curr.next.next;
        count--;
        head = dummyHead.next;
    }
}

/**
 * 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);
 */
  • 26
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值