代码随想录LeetCode刷题第三天---------203. 移除链表元素707. 设计链表206. 反转链表

链表专题

	public class ListNode {
	    // 结点的值
	    int val;
	    // 下一个结点
	    ListNode next;
	    // 节点的构造函数(无参)
	    public ListNode() {
	    }
	    // 节点的构造函数(有一个参数)
	    public ListNode(int val) {
	        this.val = val;
	    }
	    // 节点的构造函数(有两个参数)
	    public ListNode(int val, ListNode next) {
	        this.val = val;
	        this.next = next;
	    }
	}

203. 移除链表元素

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

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

  • 当前思路:

    还是要先遍历这个链表,然后通过if语句判断相等不相等,
    再对链表中的相应元素进行删除后返回链表

  • 看完题解一:

    思路和迭代法一样,但要注意的是头结点有可能会被删除,
    因此可以定一个节点指向头结点

     /**
      * 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 Solution {
         public ListNode removeElements(ListNode head, int val) {
             ListNode a = new ListNode();
             a.next = head;
             ListNode temp = new ListNode();
             temp = a;
             while(temp.next!=null){
                 if(temp.next.val==val){
                     temp.next= temp.next.next;
                 }else{
                     temp=temp.next;
                 }
             }
             return a.next;
     
         }
     }
    
  • 看完题解二

用递归的方法,链表的很多操作都可以用递归的思想。这个递归看不明白,想不明白,也写不出来

	 class Solution {
	    public ListNode removeElements(ListNode head, int val) {
	        if (head == null) {
	            return head;
	        }
	        head.next = removeElements(head.next, val);
	        return head.val == val ? head.next : head;
	    }
	}

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 的节点。

  • 链表注意点:

1.每一个节点都是对象,都有两个属性,一个data,一个next,通过一个类来表示一个结点,在类中声明数据及下一个结点next,也就是ListNode类。MyLinkedList这个类存放链表的头和长度。
2.有无头结点,看是否初始化,

	 public class MyLinkedList {
	    //head 是 MyLinkedList的一个成员属性,代表整个链表的头
	    public Node head;  //保存单链表头节点的引用  值默认为null

初始化单链表(无参和有参)
· 无参构造理解为初始化单链表(包含头结点)
· 有参构造理解为初始化单链表和首元结点(包含头结点和首元结点)

	 public SingleLinkList(){
	        this.head = new LinkListNode();
	    }
	    	this.head = new LinkListNode(0);
	    }

关于刚写代码时的一些疑问:

	class MyLinkedList {
	    int size;//定义size有啥用呢?通过头插法和尾插法插入元素时,记录size
	    ListNode head;
	    public MyLinkedList() {
	        head = new ListNode(0);
	        size=0;
	    }
	 public int get(int index) {
	        if(index<0||index>size-1){
	            return -1
	        }
	        ListNode p=head;
	        for(int i=0;i<=index;i++){//要是p=head,这不应该是i<index吗
	                                //因为这里head已经初始化了,第一个节点就是head
	            p=p.next;
	        }
	        return p.val;
	    }
	    /*这个get方法为什么是i<=index呢,逻辑不对呢 */
	    //p=head,p直接指head,p相当于head;和p.next=head,p节点的下一个元素是head
	 public void addAtHead(int val) {
	        ListNode p = head;//为什么不是p.next = head
	        size++;//这里size是几啊,size得通过循环次数是自己数出来吧?
	                                         //可以是根据插入次数累加出来的成员变量
	        ListNode n = new ListNode(val);
	        n.next=p.next;
	        p.next=n;
	    }
	   public void addAtTail(int val) {//这里的size知道真实的长度啊?
	                        //初始是0,随着元素的增多,size也在计数,因此知道
	     }

自己代码:

	/**
	 * 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);
	 */
	class MyLinkedList {
	    Node head;
	    int size;
	    public MyLinkedList() {
	        head = new Node(0);
	        size = 0;
	    }   
	    public int get(int index) {
	        Node p = head;
	        if(index<0||index>=size){
	            return -1;
	        }else{
	            for(int i=0;i<=index;i++){
	                p=p.next;
	            }
	            return p.val;
	        }
	    } 
	    public void addAtHead(int val) {
	         Node p = head;
	         Node ad = new Node(val);
	        ad.next=p.next;
	        p.next=ad;
	        size++;
	    }
	    
	    public void addAtTail(int val) {
	         Node p = head;
	         Node adt = new Node(val);
	         for(int i=0;i<size;i++){
	             p=p.next;
	         }
	         p.next=adt;
	         size++;
	    }  
	    public void addAtIndex(int index, int val) {
	        if(index<0||index>size)
	            return;
	        Node addi = new Node(val);
	        Node p = head;
	        for(int i=0;i<index;i++){
	            p=p.next;
	        }
	        addi.next=p.next;
	        p.next=addi;
	        size++;
	    } 
	    public void deleteAtIndex(int index) {
	         if(index<0||index>=size)
	            return;
	        Node p = head;
	        for(int i=0;i<index;i++){
	            p=p.next;
	        }
	        p.next=p.next.next;
	        size--; 
	}
	}
	 class Node{
	     int val;
	     Node next;
	     public Node(int val){
	         this.val=val;
	     }
	     
	 }

206. 反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
/**这里我想的是遍历每个元素,用头插法再插回去,但是没能写出来。也可以利用外部空间比如说栈 */

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

这个是看题解之后想明白的迭代法,cur.next用于改变当前链指的方向,pre用于改变当前链指的方向后指的节点,pre = cur用于跟上cur,tep用于帮cur锁定下一个节点。最后cur和tep都指向null,pre指向操作的最后一个节点,这是链表已经反过来了,所以直接返回pre即可。
用这个图很容易理解:
在这里插入图片描述

还有一个递归的方法,看题解能明白,但是也是自己写不出来

	class Solution {
		public ListNode reverseList(ListNode head) {
			//递归终止条件是当前为空,或者下一个节点为空
			if(head==null || head.next==null) {
				return head;
			}
			//这里的cur就是最后一个节点
			ListNode cur = reverseList(head.next);
			//如果链表是 1->2->3->4->5,那么此时的cur就是5
			//而head是4,head的下一个是5,下下一个是空
			//所以head.next.next 就是5->4
			head.next.next = head;
			//防止链表循环,需要将head.next设置为空
			head.next = null;
			//每层递归函数都返回cur,也就是最后一个节点
			return cur;
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值