代码随想录算法训练营第三天 | 203.移除链表元素 707.设计链表 206.反转链表

203.移除链表元素 ,707.设计链表,206.反转链表

  • 203.移除链表元素
    • 1.思路
    • 2.代码实现
  • 707.设计链表
    • 1.思路
    • 2.代码实现
  • 206.反转链表
    • 1.思路
    • 2.代码实现

203.移除链表元素

题目链接: link
视频
文字

1.思路

方法一:直接使用原来的链表来进行删除操作。

  • 时间复杂度 O(n)
  • 空间复杂度 O(1)

移除头结点和移除其他节点的操作是不一样的,因为链表的其他节点都是通过前一个节点来移除当前节点,而头结点没有前一个节点。
头结点如何移除呢,其实只要将头结点向后移动一位就可以,这样就从链表中移除了一个头结点。

方法二:设置一个虚拟头结点在进行删除操作。

  • 时间复杂度 O(n)
  • 空间复杂度 O(1)

设置一个虚拟头结点,这样原链表的所有节点就都可以按照统一的方式进行移除了。

2.代码实现

不使用虚拟结点,原列表操作:
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        while((head!=null)&&(head.val==val)){
            head=head.next;
        }
        ListNode cur=head;
        while((cur!=null)&&(cur.next!=null)){
            if(cur.next.val==val){
                cur.next=cur.next.next;
            }
            else{
                cur=cur.next;
            }
        }
        return head;
    }
}
使用虚拟结点:
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        if(head==null)
            return head;
        ListNode dummy= new ListNode(-1,head);
        ListNode cur=dummy;
        while(cur.next!=null){
            if(cur.next.val==val){
                cur.next=cur.next.next;
            }
            else{
                cur=cur.next;
            }
        }
        return dummy.next;
    }
}

707.设计链表

题目链接: link
视频
文字

1.思路

使用了虚拟结点,无论在头结点,中间结点还是尾结点删除或者增加结点都是同样的操作。

2.代码实现

class ListNode{
    int val;
    ListNode next;
    ListNode(){}
    ListNode(int val){
        this.val=val;
        this.next=null;
    }

}
class MyLinkedList {
    int size;//存放的结点个数
    ListNode head;//虚拟头节点
    public MyLinkedList(){
        //初始化链表
        size=0;
        head=new ListNode(0);
    }

    public int get(int index) {
        //判断index是否合法
        if(index<0 || index > size-1){//这里原来写成了size
            return -1;
        }
        else{
            ListNode cur=head;
            while((index--)!=0){//遍历到index的前一个结点
                cur=cur.next;//指针指向index的前一个结点
            }
            return cur.next.val;
        }
    }
    
    public void addAtHead(int val) {
        ListNode cur=new ListNode(val);
        cur.next=head.next;//注意赋值顺序
        head.next=cur;
        size++;
    }
    
    public void addAtTail(int val) {
        ListNode newNode=new ListNode(val);
        ListNode cur=head;
        while(cur.next!=null){
            cur=cur.next;
        }
        cur.next=newNode;
        size++;
    }
    
    public void addAtIndex(int index, int val) {
        /*判断index是否合法
        index=0 在头部插入新结点
        index=size 在尾部插入结点
        index>size  则不会插入结点
        index <0 在头部插入新结点
        */
        if(index>size){
            return;
        }
        else{
            if(index<0){
            index=0;
        }
            ListNode cur=head;
            while(index--!=0){
                cur=cur.next;//此时指向index前一个结点
            }
            ListNode newNode= new ListNode(val);
            newNode.next=cur.next;
            cur.next=newNode;
            size++;
        }
        
    }
    
    public void deleteAtIndex(int index) {
        if(index<0 || index>= size){
            return;
        }
        ListNode cur=head;
        while(index--!=0){
            cur=cur.next;//指向index的前一个结点
        }
        cur.next=cur.next.next;
        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);
 */

206.反转链表

题目链接: link
视频
文字

1.思路

方法一:双指针法
遍历链表,用两个指针改变每个结点的next,需要注意改变每个结点的next时要提前把后一个结点的地址保存在tmp里,其次要注意遍历的中止条件,还要注意改变结点指针方向时的赋值顺序。

方法二:递归
递归法实现这道题的逻辑和双指针法相同

2.代码实现

双指针法;
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode cur=head;
        ListNode pre=null;
        ListNode tmp;
        while(cur!=null)//修改cur指向的结点的指针方向
        {
            tmp=cur.next;
            cur.next=pre;
            //前后指针都向后移一个结点
            pre=cur;
            cur=tmp;
        }
        return pre;
    }
}
递归:
class Solution {
    private ListNode reverse(ListNode cur, ListNode pre){//翻转cur指向的结点
        if(cur==null)
            return pre;
        else{
            ListNode tmp=cur.next;
            cur.next=pre;
            return reverse(tmp,cur);//前后指针后移一位并反转
        }
    }
    public ListNode reverseList(ListNode head) {
        return reverse(head,null);
    }
}

你可能感兴趣的:(力扣,链表,java,力扣)