IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 链表(2)------数据结构 -> 正文阅读

[数据结构与算法]链表(2)------数据结构

1)进行反转单链表:节点的值不发生改变,只需要进行修改节点的指向

进行测试的时候要给方法传入一个头结点

输入:1,2,3,4,5;

输出:5,4,3,2,1;

1)我们先写两个变量,front=head,current=front.next;我们设想一下只用这两个变量是否可以进行反转单链表的操作呢;

我让current.next=front,再让front=current;这是我们就发现current已经无法走到下一个节点了,因为此时current.next已经被修改了,所以我们可以让curNext来进行保存每一次反转操作的current.next的值(这个操作再循环中的第一条语句)

2)循环条件为current.next!=null;

public Node resverse()
{
    if(head==null)
    {
        throw new RuntimeException("链表长度为空");
    }
    Node front=null;
    Node current=head;
    Node currentNext=head.next;
    while(current!=null)
    {  currentNext=current.next;
        current.next=front;
        front=current;
        current=currentNext;
    }
    return front;
}

2.只遍历单链表一遍,找出链表的中间节点,如果有两个中间节点,那么返回第二个中间节点

输入:1,2,3,4,5,返回:3

输入:1,2,3,4,5,6,返回:4,如果一个链表有两个中间节点,那么我们返回第二个节点

先求出链表的长度,再走count/2步

class Solution {
    public ListNode middleNode(ListNode head) {
        ListNode current=head;
        int count=0;
        while(current!=null){
            current=current.next;
            count++;
        }
         current=head;
        for(int i=0;i<count/2;i++){//当我们的current走到count/2的位置的时候
       //恰好已经走到了链表的中间节点
            current=current.next;
        }
        return current;
    }
}

思路:快指针速度是慢指针速度的2倍,一个到结尾了,那么另一个就是中间位置:

1)进行快慢指针,我们可以定义一个快慢指针,一开始让fast节点和slow节点都指向head,然后我们指向循环,让fast一次走两步,让slow一次走一步;

奇数节点fast走到最后一步的时候fast.next为空

偶树节点fast走到最后一步的时候fast为空

2)最终slow就是中间节点

我们可以自己画图演示一下,链表长度为奇数或者链表长度是偶数的截至条件是不一样的

   public ListNode middleNode(ListNode head) {
       ListNode fast=head;
       ListNode slow=head;
       while(fast!=null&&fast.next!=null)
       {
           fast=fast.next.next;
           slow=slow.next;
       }
       return slow;
public ListNode middleNode(ListNode head) {
        if(head==null){
            return null;
        }
     ListNode fast=head;
     ListNode slow=head;
         while(true){
          if(fast==null||fast.next==null){
                 return slow;
             }
             fast=fast.next.next;
             slow=slow.next;
         }
    }

此时那一个判断条件if(fast==null||fast.next==null)必须写在让指针进行移动的前面,因为此时如果连表中只有一个元素的时候,否则会发生空指针异常

第三题:找出链表中的倒数第K个节点,能不能遍历单链表一遍

要找到倒数第K个,要从前向后走len-k步(至少要遍历两遍,因为首先要知道链表的长度);?

1)我们进行定义两个快慢指针,fast为快指针,slow是慢指针,我们先让fast走k-1步

2)然后再让fast和slow同时走;等到fast.next为空的时候(或者说fast走到最后一个节点)

3)并返回slow节点,这时的slow才为倒数第K个节点;

从倒数第三个到倒数第一个 走几步?需要走两步

从倒数第四个到倒数第一个 走几步?需要走三步

从倒数第K个到倒数第一个? 走几步?需要走k-1步

2)更简单的方法是先求出链表的长度,让current走len-k步,但是需要进行遍历单链表现要求出但是链表长度

class Solution {
    public ListNode getKthFromEnd(ListNode head, int k) {
          if(k<=0||k>size()){
//必须加上,否则下面的循环会出现空指针异常,再循环走k-1步的时候会发生空指针异常
            return null;
            }
        int count=0;
        ListNode current=head;
        while(current!=null){
            count++;
            current=current.next;
        }
        current=head;
        for(int i=0;i<count-k;i++){//当走到count-k的位置的时候,循环退出
              current=current.next;
        }
     return current;
    }
}

public Node returnLastK(int index)
{
    if(index<0)
    {
        throw new UnsupportedOperationException("此时的链表的倒数第K个节点位置不正确");
    }
    if(head==null)
    {
        throw new UnsupportedOperationException("此时链表长度是空");
    }
    Node fast=head;
    Node slow=head;
    for(int i=0;i<index-1;i++)
    {  fast=fast.next;
        if(fast==null)
        {
            throw new UnsupportedOperationException("当前你输入的index的值已经超过了链表的长度");
        }
    }
    while(fast.next!=null)
    {
        fast=fast.next;
        slow=slow.next;
    }
    return slow;
}

4.合并两个有序链表

思路:

1)我们首先定义一个虚拟节点是newHead作为要合并在一起的总链表的新节点,注意它是一个虚拟节点,里面的值是任意的

2)我们再合并headA和headB这两个链表的时候,保存两个链表的右节点是没有什么用处的,如果发现headA.data>headB.data,我们就把HeadA指向的这个头结点放到先开辟的链表后面,同时让headA进行向后移动

? ?if(headA.data>headB.data)

? ? ? {

? ? ? ?}else if(HeadA.data<HeadB.data){

? ?}else{

? ?}

3)再进行合并的过程中,两个链表所走的过程中都不可以是空的,所以循环条件是HeadA!=null&&HeadB!=null

4)在循环出来之后,会出现一种情况,HeadA过长或者HeadB过长,此时我们还要进行特殊处理

 public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode HeadA=list1;
        ListNode HeadB=list2;
        ListNode newHead=new ListNode(-1);
       ListNode temp=newHead;
        while(HeadA!=null&&HeadB!=null)
        {
            if(HeadA.val<HeadB.val)
            {
                temp.next=HeadA;
                HeadA=HeadA.next;
                temp=temp.next;
            }else
            {
                temp.next=HeadB;
                HeadB=HeadB.next;
                temp=temp.next;
            }
        }
        if(HeadA!=null)
        {
            temp.next=HeadA;
        }
        if(HeadB!=null)
        {
            temp.next=HeadB;
        }
        return newHead.next;
class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
       ListNode head1=list1;
       ListNode head2=list2;
       ListNode newHead=new ListNode(-1);
       ListNode current=newHead;
       while(head1!=null&&head2!=null){
           if(head1.val>head2.val){
               current.next=head2;
               head2=head2.next;
               current=current.next;
           }else{
               current.next=head1;
               head1=head1.next;
               current=current.next;
           }
       }
       while(head1!=null){
             current.next=head1;
             head1=head1.next;
             current=current.next;
       }
       while(head2!=null){
              current.next=head2;
              head2=head2.next;
              current=current.next;
       }
       current.next=null;
       return newHead.next;
    }
}

下一种写法更推荐

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-12-25 11:33:24  更:2022-12-25 11:36:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 14:19:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码