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

数组与链表的区别:

①数组是在内存中是连续分布的,但是链表在内存中可不是连续分布的。

②链表是通过指针域的指针链接在内存中各个节点。 所以链表中的节点在内存中不是连续分布的 , 而是散乱分布在内存中的某地址上,分配机制取决于操作系统的内存管理。

③链表动态变化长度,只有数组才是长度固定,所以不用for循环遍历长度

链表定义:

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; }
  }

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 

输出:[] 

 示例 3:

输入:head = [7,7,7,7], val = 7 

输出:[] 

问题分析:

链表动态变化长度,只有数组才是长度固定,所以不用for循环

单向链表,头和中间节点两种删法。 例如:head[1,1,1,1] val=1

虚拟节点,头结点与中间节点统一删法。

③双向链表。

方法一:单向链表无虚节点

class Solution {
    public ListNode removeElements(ListNode head, int val) {
            ListNode p=head;
            while(head!=null&&head.val==val){//注意判空
                head=head.next;
            }
            while(p!=null&&p.next!=null){//持续查找val的过程,所以用while而不是if。
                                        //要删除一个元素,要找到前一个元素,所以head.next!=null
                if (p.next.val==val){
                    p.next=p.next.next;
                }
                else {
                    p=p.next;
                }
            }
            return head;
    }
}

方法二:单向链表带虚节点

class Solution {
    public ListNode removeElements(ListNode head, int val) {
           ListNode node=new ListNode(-1,head);
             node.next=head;
            ListNode cur=node;//虚节点指针,要想删下一个节点要先知道上一个节点的指针
                                //如果不加cur最后node一直向后遍历,返回空链表
           while (cur.next!=null){
               if (cur.next.val==val){
                   cur.next=cur.next.next;
               }
               else
                   cur=cur.next;
           }
           return node.next;//不能return head,有可能head已被删除
    }
}

707.设计链表

        设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 nextval 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。(第0个节点是头节点)

在链表类中实现这些功能:

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

示例 1:

MyLinkedList linkedList = new MyLinkedList();

linkedList.addAtHead(1);

linkedList.addAtTail(3);

linkedList.addAtIndex(1,2); //链表变为1-> 2-> 3

linkedList.get(1); //返回2

linkedList.deleteAtIndex(1); //现在链表是1-> 3

linkedList.get(1); //返回3

 方法一:单向链表

class MyLinkedList {
        int size;
        ListNode node;//虚拟

        public MyLinkedList() {
            size = 0;
            node = new ListNode(0);//设置虚拟节点的值为0
        }

        public int get(int index) {
            if (index < 0 || index >= size) {
                return -1;
            }
            ListNode cur = node;//虚拟节点的指针
            while (index >= 0) {
                cur = cur.next;
                index--;
            }

            return cur.val;

        }

        public void addAtHead(int val) {
            addAtIndex(0, val);
        }

        public void addAtTail(int val) {
            addAtIndex(size, val);
        }

        public void addAtIndex(int index, int val) {
            if (index < 0) {
                index = 0;
            }

            if (index > size) {
                return;
            }
            ListNode cur = node;

            for (int i = 0; i < index; i++) {
                cur = cur.next;
            }
            ListNode add = new ListNode(val);//增加新节点,值位val
            add.next = cur.next;
            cur.next = add;
            size++;
        }

        public void deleteAtIndex(int index) {
            if (index < 0 || index >= size) {
                return;
            }
            if (index == 0) {
                node = node.next;
                return;
            }
            ListNode cur = node;
            for (int i = 0; i < index; i++) {
                cur = cur.next;
            }
            cur.next = cur.next.next;
            size--;

        }

    }

206.反转链表 

        

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

示例 1:

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

输出:[5,4,3,2,1]

 示例 2:

输入:head = [1,2]

输出:[2,1]

示例 3:

输入:head = []

输出:[]

 

问题分析:

双指针法,首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null。

然后就要开始反转了,首先要把 cur->next 节点用tmp指针保存一下,也就是保存一下这个节点。

为什么要保存一下这个节点呢,因为接下来要改变 cur->next 的指向了,将cur->next 指向pre ,此时已经反转了第一个节点了。

递归法

方法一:双指针法

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode cur=head;
        ListNode pre=null;
        ListNode temp;
        while(cur!=null){
            temp=cur.next;//保存一下 cur的下一个节点,因为接下来要改变cur->next
            cur.next=pre;
            pre=cur;
            cur=temp;

        }
        return pre;

    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值