首页 > 编程语言 >代码随想录算法训练营第三天|力扣203.移除链表元素、力扣707.设计链表、力扣206.反转链表

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

时间:2023-07-30 11:36:26浏览次数:37  
标签:力扣 head ListNode cur val current 随想录 next 链表

链表

  • 定义:通过指针串联在一起的线性结构,每一个节点由两个部分组成:数据域和指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null,即为空指针。

链表类型

1. 单链表
2. 双链表
3. 循环链表,即链表首尾相连,可以解决约瑟夫环问题

链表的存储方式

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

链表的定义

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.)

1. 有虚拟节点方式;记得head为val值的边缘条件,以及target指针的空指针问题
/**
 * 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 low = new ListNode();
        low.next = head;
        ListNode target = head;
        if(head == null){
            return null;
        }
        while(head.val == val){
            head = head.next;
            if(head==null){
                return head;
            }
        }
        while(target != null){
            while(target.val == val){
                low.next = target.next;
                target = target.next;
                if(target == null){
                    return head;
                }
            }
            low = low.next;
            if(target!=null){
            target = target.next;}
        }
        return head;
    }
}
  1. 无虚拟节点方式;先对head指向的值处理,在运行到非val值后扫描后指针
/**
无虚拟节点方式;先对head指向的值处理,在运行到非val值后扫描后指针
 */
class Solution {
    public ListNode removeElements(ListNode head, int val) {
       //先将head指针处理至不为val值的地方
       while(head != null && head.val == val){
           head = head.next;
       }
       //head为空,则直接返回
       if(head == null){
           return head;
       }
        ListNode pre = head;
        ListNode post = head.next;
        while(post != null){
            if(post.val == val){
                pre.next = post.next;
            }else{
                pre = post;
            }
            post = post.next;
        }
        return head;
    }
}

设计链表:实现五个函数(力扣707.)

获取第n个节点的数值

  • 使用虚拟头结点的方式 dummynode
  • while(n)
  • cur = cur.next;
  • n--

头部插入节点

  • new一个新node
  • newNode.next=dummyHead.next;(注意顺序)
  • dummyhead.next=newNode;
  • size++;

尾部插入节点

  • cur = dummyhead;
  • while(cur.next == null)
  • cur = cur.next;
  • cur.next = newNode

第n个节点的插入

  • cur应该指向第n个节点的前一个结点
  • cur = dummyhead
  • while(n)
  • cur = cur.next;
  • n--;
  • newNode.next=cur.next;
  • cur.next=newNode;
  • size++;

第n个节点的删除

  • 判断n的合法性
  • cur= dummyhead;
  • while(n)
  • cur = cur.next;
  • n--;
  • cur.next=cur.next.next;
  • return dummyhead.next;
class ListNode{
    int val;
    ListNode next;
    ListNode(){}
    ListNode(int val){
        this.val = val;
    }
}

class MyLinkedList {//带有头结点的链表
    //容量大小
    int size;
    //虚拟头结点
    ListNode dummyhead;

    public MyLinkedList() {
        //初始化单链表
        size = 0;
        dummyhead = new ListNode(0);
    }
    
    public int get(int index) {
        if(index < 0 || index >= size){
            return -1;
        }
        ListNode current = dummyhead;
        while(index >= 0){
            current = current.next;
            index --;
        }
        return current.val;
    }
    
    public void addAtHead(int val) {
        ListNode current = dummyhead;
        ListNode target = new ListNode(val);
        target.next = current.next;
        current.next = target;
        size++;
    }
    
    public void addAtTail(int val) {
        ListNode current = dummyhead;
        while(current.next != null){
            current = current.next;
        }
        ListNode target = new ListNode(val);
        target.next = null;
        current.next = target;
        size++;
    }
    
    public void addAtIndex(int index, int val) {
        if(index < 0 || index >= size + 1){
            return;
        }
        ListNode current = dummyhead;
        while(index > 0){
            current = current.next;
            index--;
        }
        ListNode target = new ListNode(val);
        target.next = current.next;
        current.next = target;
        size++;
    }
    
    public void deleteAtIndex(int index) {
        if(index < 0 || index >= size){
            return;
        }
        ListNode current = dummyhead;
        while(index > 0){
            current = current.next;
            index--;
        }
        current.next = current.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.)

  • 遍历数组+头插法
/**
 * 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 reverseList(ListNode head) {
        // ListNode pummyhead = new ListNode();
        // pummyhead.next = head;
        if(head == null){
            return null;
        }
        ListNode from = head.next;

        ListNode targetPummyHead = new ListNode();
        ListNode current = targetPummyHead;
        while(head != null){
            head.next = targetPummyHead.next;
            targetPummyHead.next = head;

            head = from;
            if(from != null){
                from = from.next;
            }else{from = null;}
        }
        return targetPummyHead.next;
    }
}
  • 双指针写法
  1. 初始化:cur = head;pre=null;
  2. 遍历链表:while(cur != null)
  3. 需要一个临时指针temp = cur.next
  4. cur.next=pre;
  5. pre=cur;
  6. cur=temp
  7. return pre;
class Solution {
    public ListNode reverseList(ListNode head) {
       //双指针思路
       //初始化
       ListNode pre = null;
       ListNode cur = head;
       while( cur != null){
           ListNode temp = cur.next;
           cur.next = pre;
           pre = cur;
           cur = temp;
       }
       return pre;
    }
}
  • 递归算法
  1. reverse(cur,pre){
  2. if(cur == null)return pre;//此时终止
  3. temp = cur.next;
  4. cur.next=pre;
  5. reverse(temp,cur)}
  6. //使用:return reverse(head,null);

其实内核解法与双指针解法相同

class Solution {
    public ListNode reverseList(ListNode head) {
        return reverse(null,head);
    }
    public ListNode reverse(ListNode pre,ListNode current){
        if(current == null){
            return pre;//递归的终止条件为current为null
        }
        ListNode temp = current.next;//临时节点暂存
        current.next = pre;
        return reverse(current,temp);
    }
}

标签:力扣,head,ListNode,cur,val,current,随想录,next,链表
From: https://www.cnblogs.com/zcctxr/p/17591175.html

相关文章

  • 反转链表
    title:反转链表date:2023-07-3009:25:12tags:-c/c++categories:-算法-笔试top:反转链表题目来自acwing题目(点击跳转)定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。思考题:请同时实现迭代版本和递归版本。数据范围链表长度[0,30]......
  • go 链表栈
    packagemainimport"fmt"//链表栈typeLinkStackstruct{root*LinkNode//栈顶sizeint//栈的元素数量}//栈中的结点typeLinkNodestruct{dataintnext*LinkNode}funcNewLinkStack()*LinkStack{return&LinkStack{root:nil,size:0}}//入栈func(link......
  • [代码随想录]Day04-链表part02
    题目:24.两两交换链表中的节点思路:首先给他加一个虚拟头结点,然后思考反转的逻辑,这是每两个为一组,比如1,2是一组、3,4是一组,如果说1,2一组2,3一组就变成了链表的逆转了。那么指针的逻辑是:两个指针一个r指向要交换的二元组的第一个节点一个l指向前一个节点二元组的第二个节......
  • 力扣---77. 组合
    给定两个整数 n 和 k,返回范围 [1,n] 中所有可能的 k 个数的组合。你可以按 任何顺序 返回答案。 示例1:输入:n=4,k=2输出:[[2,4],[3,4],[2,3],[1,2],[1,3],[1,4],]示例2:输入:n=1,k=1输出:[[1]] 提示:1<=n<=201<=k<=n......
  • 力扣---141. 环形链表
    给你一个链表的头节点 head ,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从0开始)。注意:pos 不作为参数进行传递 。仅仅是为了标......
  • 力扣-设置交集大小至少为2
    1.问题描述一个整数区间[a,b] (a<b)代表着从a到b的所有连续整数,包括a和b。给你一组整数区间intervals,请找到一个最小的集合S,使得S里的元素与区间intervals中的每一个整数区间都至少有2个元素相交。输出这个最小集合S的大小。示例1:输入:intervals=[[1......
  • 双链表的插入与删除
    双链表(DoublyLinkedList)是一种链表数据结构,它与单链表相比,在每个节点上都有两个指针,一个指向前一个节点,一个指向后一个节点。这使得在双链表中的插入和删除操作更加灵活。1.双链表插入:在双链表中插入一个节点,需要先找到插入位置的前一个节点,然后通过更新指针的方式将新节点插入......
  • [代码随想录]Day03-链表part01
    题目:203.移除链表元素思路:做链表首先最好有个虚拟头指针,这样做删除添加操作的时候可以统一操作否则还得特判。那删除元素的过程,从虚拟头指针开始要做以下几步:如果当前p的next不为空,那么就可以进行判断如果p的next的值是val(↑p的next不为空↑),那么就把p的next修改为p的下......
  • 代码随想录算法训练营第三天| LeetCode 203.移除链表元素(同时也对整个单链表进行增删
    203.移除链表元素      题目链接/文章讲解/视频讲解::https://programmercarl.com/0203.%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8%E5%85%83%E7%B4%A0.html    卡哥题目建议:本题最关键是要理解虚拟头结点的使用技巧,这个对链表题目很重要。   做题思路:   ......
  • 数据结构之带头节点的单链表增删改查操作实现
     单链表的定义什么是单链表   单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。   单链表的各个数据元素在物理上可以是离散存放的,每个结点除了存放数据元素外,还要存储指向下一个节点的指针。而顺序表是连续存放的,每个结点中只......