求链表中的中点、上中点、下中点

提示:


文章目录

  • 求链表中的中点、上中点、下中点
    • @[TOC](文章目录)
  • 题目
  • 一、审题
  • 二、笔试代码求AC:不管空间
  • 三、面试代码求最优解:时间空间最优
    • 暴力解
    • 最优解:快慢指针行走法
  • 总结

题目

一共四个题目:
(1)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的中点;
(2)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的中点;
(3)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的中点的前一个点;
(4)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的中点的前一个点;


一、审题

(1)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的中点;

(2)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的中点;

(3)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的中点的前一个点;

(4)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的中点的前一个点;

下中点的前一个点,就是上中点


二、笔试代码求AC:不管空间

明白了案例的意思,四个题,就要有各自的解题方案

咱们有一个解题的原则:
笔试求AC,通过测试案例,就能进面试!故不在乎空间复杂度,只考虑时间复杂度。
而面试力求最优解;故优先考虑时间复杂度,然后也要考虑空间复杂度。唯有更好的最优解,方得面试官的青睐!!

如果笔试场上遇到本题:
那就用最傻的办法
将链表转化为数组,然后求中点,上中点,下中点,返回结果

这四道题,全部代码很相似,只是求中点,上中点,下中点的公式有区别:
(1)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的中点;
如果数组长度为N,则中点的位置就是:(N-1)/2

(2)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的中点;
如果数组长度为N,则中点的位置就是:(N)/2

(3)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的中点的前一个点;
如果数组长度为N,则中点的位置就是:(N-3)/2


(4)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的中点的前一个点;
如果数组长度为N,则中点的位置就是:(N-2)/2

ok:总结一波:笔试求AC,不用节约空间,直接将链表转化为数组即可,根据数组长度N,索引中点即可:
笔试就简单画个图,看一下公式就行,非常容易
(1)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的中点;
如果数组长度为N,则中点的位置就是:(N-1)/2
(2)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的中点;
如果数组长度为N,则中点的位置就是:(N)/2
(3)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的中点的前一个点;
如果数组长度为N,则中点的位置就是:(N-3)/2
(4)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的中点的前一个点;
如果数组长度为N,则中点的位置就是:(N-2)/2

手撕代码:
本题要用的节点,通用的链表节点:

//基础数据结构Nodepublic static class Node{public Node next;//自己有指针,也是连接Node的public int value;public Node(int v){value = v;}}

(1)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的中点;
如果数组长度为N,则中点的位置就是:(N-1)/2

//(1)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的**上**中点;//如果数组长度为N,则中点的位置就是:**(N-1)/2**public static Node midOrUpMidPoint(Node head){if (head == null || head.next == null) return head;ArrayList<Node> arr = new ArrayList<>();//动态数组,中点可以索引的Node cur = head;while (cur != null){arr.add(cur);cur = cur.next;}int N = arr.size();return arr.get((N - 1) >> 1);}

(2)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的中点;
如果数组长度为N,则中点的位置就是:(N)/2

//(2)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的**下**中点;//如果数组长度为N,则中点的位置就是:**(N)/2**public static Node midOrDownMidPoint(Node head){if (head == null || head.next == null) return head;ArrayList<Node> arr = new ArrayList<>();//动态数组,中点可以索引的Node cur = head;while (cur != null){arr.add(cur);cur = cur.next;}int N = arr.size();return arr.get(N >> 1);}

(3)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的中点的前一个点;
如果数组长度为N,则中点的位置就是:(N-3)/2

//(3)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的**上**中点的前一个点;//如果数组长度为N,则中点的位置就是:**(N-3)/2**public static Node midPreOrUpMidPrePoint(Node head){if (head == null || head.next == null) return head;ArrayList<Node> arr = new ArrayList<>();//动态数组,中点可以索引的Node cur = head;while (cur != null){arr.add(cur);cur = cur.next;}int N = arr.size();return arr.get((N - 3) >> 1);}

(4)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的中点的前一个点;
如果数组长度为N,则中点的位置就是:(N-2)/2

//(4)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的**下**中点的前一个点;//如果数组长度为N,则中点的位置就是:**(N-2)/2**public static Node midPreOrDownMidPrePoint(Node head){if (head == null || head.next == null) return head;ArrayList<Node> arr = new ArrayList<>();//动态数组,中点可以索引的Node cur = head;while (cur != null){arr.add(cur);cur = cur.next;}int N = arr.size();return arr.get((N - 2) >> 1);}

四个代码一起测试:

//造一个链表public static Node createLinkNode(boolean odd){Node head = new Node(1);Node n2 = new Node(2);Node n3 = new Node(3);Node n4 = new Node(4);head.next = n2;n2.next = n3;if (!odd) n3.next = n4;//是偶数长度N,连n4return head;}//测试一波:public static void test2(){Node head = createLinkNode(true);//N=3Node head2 = createLinkNode(false);//N=3System.out.println("链表:1-2-3或者1-2-3-4,其中点或者上中点");System.out.println(midOrUpMidPoint(head).value);System.out.println(midOrUpMidPoint(head2).value);System.out.println("链表:1-2-3或者1-2-3-4,中点或者下中点");System.out.println(midOrDownMidPoint(head).value);System.out.println(midOrDownMidPoint(head2).value);System.out.println("链表:1-2-3或者1-2-3-4,中点前一个或者上中点的前一个");System.out.println(midPreOrUpMidPrePoint(head).value);System.out.println(midPreOrUpMidPrePoint(head2).value);System.out.println("链表:1-2-3或者1-2-3-4,中点前一个或者下中点的前一个");System.out.println(midPreOrDownMidPrePoint(head).value);System.out.println(midPreOrDownMidPrePoint(head2).value);}public static void main(String[] args) {//        test1();test2();}

看结果:

链表:1-2-3或者1-2-3-4,其中点或者上中点
2
2
链表:1-2-3或者1-2-3-4,中点或者下中点
2
3
链表:1-2-3或者1-2-3-4,中点前一个或者上中点的前一个
1
1
链表:1-2-3或者1-2-3-4,中点前一个或者下中点的前一个
1
2

全部AC,easy,非常easy!!!


三、面试代码求最优解:时间空间最优

面试呢,咱就只能在这链表上操作了,绝不可以用额外的空间,否则面试官就会扣你分!!!
争取在时间复杂度高的情况下,又能节约空间

暴力解

先让cur指针,过一遍链表,统计一下链表有多少个节点N,然后
跟上面类似:
咱只需要再走这么多步:
(1)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的中点;
如果数组长度为N,则中点的位置就是:(N-1)/2
(2)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的中点;
如果数组长度为N,则中点的位置就是:(N)/2
(3)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的中点的前一个点;
如果数组长度为N,则中点的位置就是:(N-3)/2
(4)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的中点的前一个点;
如果数组长度为N,则中点的位置就是:(N-2)/2
就能找到中点返回!
这可以,但是这还不是最优解!

最优解:快慢指针行走法

啥意思呢?
什么是快慢指针?
所谓快指针:就是一个指针fast,它每次可以走2步;
所谓慢指针:就是一个指针slow,它每次可以走1步;

今后遇到这个,跟面试官聊题的时候,直接用笔画案例,找边界,然后就知道代码怎么写了!
也就知道初始化这个快慢指针该怎么办了。

(1)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的中点;
——如果head=null,或者head只有1个点,或者head有2个点,他们都只需要返回head,你画个图瞅瞅是不是?

——当N为奇数或者偶数时,初始化:先让fast走2步,slow走1步
然后快慢指针走,必然,fast先走完,一旦快指针fast走不动了,此时slow就是我们要的中点或者上中点!
【fast指针走不动:fast.next=null或者fast.next.next=null】

//复习,面试代码://(1)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的**上**中点;//——如果head=null,或者head只有1个点,或者head有2个点,他们都只需要返回head,你画个图瞅瞅是不是?//当N为奇数或者偶数时,初始化:先让fast走2步,slow走1步//然后快慢指针走,必然,fast先走完,一旦快指针fast走不动了,此时slow就是我们要的中点或者上中点!public static Node midOrUpMidPointFace(Node head){if (head == null || head.next == null || head.next.next == null) return head;Node fast = head.next.next;Node slow = head.next;while (fast.next != null && fast.next.next != null){fast = fast.next.next;//快指针slow = slow.next;//满指针}return slow;}

(2)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的中点;
——当head=null或者head只有1个点时,返回head就行

N>=2的话:
——当N时奇数或者偶数时,初始化:fast和slow都要走一步
然后快慢指针走,fast走不动了,slow必然是中点或者下中点。

//(2)当链表个数N为奇数时,求链表中的中点、当链表个数N为偶数时,求链表中的**下**中点;//——当head=null或者head只有1个点时,返回head就行//N>=2的话://——当N时奇数或者偶数时,初始化:fast和slow都要走一步//然后快慢指针走,fast走不动了,slow必然是中点或者下中点。public static Node midOrDownMidPointFace(Node head){if (head == null || head.next == null) return head;Node fast = head.next;//1步哦Node slow = head.next;while (fast.next != null && fast.next.next != null){fast = fast.next.next;//快指针slow = slow.next;//满指针}return slow;}

(3)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的中点的前一个点;
——当head=null或者,head就1个点,或者head有2个点时,那中点前一个点为null,上中点前一个点也是null

——当N>=3时,咱们初始化:让fast先走2步,slow就在head不动
然后快慢指针走,fast走不动,slow就是中点前一个,或者上中点前一个

//(3)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的**上**中点的前一个点;//——当head=null或者,head就1个点,或者head有2个点时,那中点前一个点为null,上中点前一个点也是null//——当N>=3时,咱们初始化:让fast先走2步,slow就在head不动//然后快慢指针走,fast走不动,slow就是中点前一个,或者上中点前一个public static Node midPreOrUpMidPrePointFace(Node head){if (head == null || head.next == null || head.next.next == null) return null;Node fast = head.next.next;//2步Node slow = head;//不动哦while (fast.next != null && fast.next.next != null){fast = fast.next.next;//快指针slow = slow.next;//满指针}return slow;}

(4)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的中点的前一个点;
——当head=null或者head就1个点时,null就是中点前一个点

——当N>=2,初始化:fast先走1步,而slow先不动
快慢指针正常走,fast走不动了,此时slow就是中点前一个点,或者下中点前一个点

//(4)当链表个数N为奇数时,求链表中的中点的前一个点、当链表个数N为偶数时,求链表中的**下**中点的前一个点;//——当head=null或者head就1个点时,null就是中点前一个点//——当N>=2,初始化:fast先走1步,而slow先不动//快慢指针正常走,fast走不动了,此时slow就是中点前一个点,或者下中点前一个点public static Node midPreOrDownMidPrePointFace(Node head){if (head == null || head.next == null) return null;Node fast = head.next;//1步Node slow = head;//不动哦while (fast.next != null && fast.next.next != null){fast = fast.next.next;//快指针slow = slow.next;//满指针}return slow;}

所以 总结一下,遇到这个题,直接动笔画一下,就知道边界,和快慢指针的初始化,该怎么办了。
搞懂了核心思想,写代码完全不是问题!!!
测试:

public static void test4(){Node head = createLinkNode(true);//N=3Node head2 = createLinkNode(false);//N=3System.out.println("链表:1-2-3或者1-2-3-4,其中点或者上中点");System.out.println(midOrUpMidPointFace(head).value);System.out.println(midOrUpMidPointFace(head2).value);System.out.println("链表:1-2-3或者1-2-3-4,中点或者下中点");System.out.println(midOrDownMidPointFace(head).value);System.out.println(midOrDownMidPointFace(head2).value);System.out.println("链表:1-2-3或者1-2-3-4,中点前一个或者上中点的前一个");System.out.println(midPreOrUpMidPrePointFace(head).value);System.out.println(midPreOrUpMidPrePointFace(head2).value);System.out.println("链表:1-2-3或者1-2-3-4,中点前一个或者下中点的前一个");System.out.println(midPreOrDownMidPrePointFace(head).value);System.out.println(midPreOrDownMidPrePointFace(head2).value);}public static void main(String[] args) {//        test1();test2();}

总结

提示:重要经验:

1)链表相关问题基础的知识要牢固,另外像本题这种涉及中点,上中点,下中点的操作,今后要敏感地想到用快慢指针解决,抠清楚边界条件和初始化快慢指针的点,画图举例,自己搞清楚,就很明白了。
2)大厂的笔试代码求AC,不管空间复杂度,面试要求最优解,既要考虑速度快,还要节约空间。

求链表中的中点、上中点、下中点相关推荐

  1. 链表题目--2 求链表的中间结点 和 求链表中倒数第k个结点

    求链表的中间结点 思路 一个走两步,一个走一步.一个走到尾,另外一个就走到了中间 /*** Definition for singly-linked list.* struct ListNode {* ...

  2. 使用AndriodStudio制作音乐播放器之音乐播放界面(进度条正常播放、上、下曲切换)

    效果图: 思路整理: 1.要实现上.下曲切换,进度条正常播放前提首先要把音乐资源导入播放器中: 2.获取音乐的时间长度get.length 3.用seekbar获取进度条,使用线程的方法配置进度条 4 ...

  3. 已知一个带有表头的单链表,结点结构为data-link,假设该链表只给出了头指针list。在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第k个位置上的结点(k为正整数)。

    今天和大家分享一道2009年代码为408的一道真题: 已知一个带有表头的单链表,结点结构为data-link,假设该链表只给出了头指针list.在不改变链表的前提下,请设计一个尽可能高效的算法,查找链 ...

  4. Leetcode 129求根节点到叶节点数字之和、104二叉树的最大深度、8字符串转换整数(atoi)、82删除排序链表中的重复元素II、204二分查找、94二叉树的中序遍历、144二叉树的前序遍历

    Top1:Leetcode 129求根节点到叶节点数字之和 官方题解:https://leetcode.cn/problems/sum-root-to-leaf-numbers/solution/qi ...

  5. 懒羊羊吃青草:懒羊羊是一只非常能吃的羊,它在青青草原上发现一块巨大的正方形草地,但灰太狼已经抢先一步在草地上布下了若干陷阱。正方形草地位于直角坐标系中...

    题面描述 懒羊羊是一只非常能吃的羊,它在青青草原上发现一块巨大的正方形草地,但灰太狼已经抢先一步在草地上布下了若干陷阱.正方形草地位于直角坐标系中,左下角坐标为 (1, 1) ,右上角坐标为 (m, ...

  6. C++ 单链表基本操作分析与实现 链表   链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结

    C++ 单链表基本操作分析与实现 链表 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每一个元素称为结点)组成,结点可以 ...

  7. 求二叉树中的第一条最长路径长度,并输出最长路径上的节点

    #include <stdio.h> #define MaxSize 1000typedef struct BiTNode {int data;struct BiTNode *lchild ...

  8. 链表相关操作:创建链表、遍历链表、求链表长度、链表中删除一个节点、链表中插入一个节点、反转单链表...

    1 #include<iostream> 2 #include<stdlib.h> 3 4 typedef struct node 5 { 6 int data; 7 stru ...

  9. 【编程题目】输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印...

    第 16 题(树): 题目(微软): 输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印. 例如输入 8 / \ 6 10 / \ / \ 5 7 9 11 输出 8 6 1 ...

最新文章

  1. python模块-random
  2. 机器学习笔记(一)绪论
  3. 前端参数无法转为后端实体内部类_Spring Boot返回前端Long型丢失精度
  4. Vue + Element UI + Spring Boot——易班优课YOOC课群在线测试自动答题解决方案(十)问题管理页面
  5. mysql-5.7.11-winx64.zip 安装配置
  6. NUS 联合 Sea AI Lab 发表 Multi-view Pose Transformer,完全端到端学习,超强可扩展性...
  7. 第六章 图像识别与卷积神经网络
  8. hdu 1085 Holding Bin-Laden Captive! (母函数)
  9. ext4文件系统制作 - make_ext4fs 参数介绍【转】
  10. 震惊!!【微信拼图红包】继微信语音红包后又一新技能
  11. c语言10的10万次方,在c语言编程中 10的n次方应该怎么表达
  12. win10家庭版将中文用户名修改为英文
  13. [木野狐]ViewState 剖析(翻译兼笔记)
  14. System.Globalization.CultureInfo.InvariantCulture失效
  15. Validation工具类
  16. python计算多边形面积
  17. mybatis-plus存数组对象,并从数据库查出这个数组
  18. unity PC端 调用FFmpeg生成视频 unity序列帧合成视频
  19. 【Unity3D】关于 InputManager 以及改键功能的制作
  20. 蓝桥杯单片机CT107D_13_工厂灯光控制系统

热门文章

  1. 数字身份的万亿市场之争才刚开始
  2. 网易微专业web前端开发课程视频教程分享
  3. 记录一次线上Mysql数据库迁移方案制定与实施
  4. 最佳运动类APP-Keep原型设计与欣赏
  5. 视频转gif如何做?三步教你视频转gif制作
  6. iOS屏幕旋转及其基本适配方法
  7. 【第五课】UAV倾斜摄影测量三维建模之空三计算问题
  8. windows文件服务器高可用,通过 Windows Server 2012 构建高可用性的文件服务器
  9. python math模块
  10. 小米全系列手机 刷机总贴