当前位置: 首页 > news >正文

顺序表和链表面试题

文章目录

  • 顺序表
    • (1)原地移除数组中所有的元素val,要求时间复杂度为O(N),空间复杂度为O(1)。
    • (2)删除有序数组中的重复项
    • (3)合并两个有序数组
  • 链表
    • (1)删除链表中等于给定值 val 的所有节点
    • (2)反转一个单链表
    • (3) 合并两个有序链表
    • (4)链表的中间结点
    • (5)链表中倒数第k个结点
    • (6)分割链表
    • (7)输入两个链表,找出它们的第一个公共结点(Y型)
    • (8)给你一个链表的头节点 head ,判断链表中是否有环。
    • (9)给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
    • (10)判定链表是否是回文

顺序表

(1)原地移除数组中所有的元素val,要求时间复杂度为O(N),空间复杂度为O(1)。

oj链接
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

双指针

class Solution {public int removeElement(int[] nums, int val) {int left = 0;for (int right = 0; right < nums.length; right++) {if (nums[right] != val) {nums[left++] = nums[right];}}return left;}
}

(2)删除有序数组中的重复项

oj链接
给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
返回 k

双指针

class Solution {public int removeDuplicates(int[] nums) {if(nums == null || nums.length == 0) return 0;int front = 0;int next = 1;while(next < nums.length){if(nums[front] != nums[next]){nums[++front] = nums[next];}next++;}return front+1;}
}

优化(相邻的元素不同不进行多余的赋值操作)
像[1,2,3,4,5]就不用进行赋值操作

class Solution {public int removeDuplicates(int[] nums) {if(nums == null || nums.length == 0) return 0;int front = 0;int next = 1;while(next < nums.length){if(nums[front] != nums[next]){if(next - front > 1){nums[front + 1] = nums[next];}front++;}next++;}return front + 1;}
}

(3)合并两个有序数组

oj链接
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

从后面开始确定

class Solution {public void merge(int[] nums1, int m, int[] nums2, int n) {while(m>0&&n>0) {if(nums1[m-1]>nums2[n-1]) {nums1[m+n-1] = nums1[m-1];m--;} else {nums1[m+n-1] = nums2[n-1];n--;}}while(n>0) {nums1[n-1] = nums2[n-1];n--;}}
}

链表

(1)删除链表中等于给定值 val 的所有节点

oj链接
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

class Solution {public ListNode removeElements(ListNode head, int val) {while(head!=null&&head.val==val) {head= head.next;}if(head == null) {return null;}ListNode prev = head;while(prev.next!=null) {if(prev.next.val==val) {prev.next=prev.next.next;} else {prev=prev.next;}}return head;}
}

(2)反转一个单链表

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

class Solution {public ListNode reverseList(ListNode head) {if(head==null)  return null;ListNode prev = null;ListNode cur = head;ListNode next = head.next;while(next != null) {cur.next = prev;prev = cur;cur = next;next = next.next;}cur.next = prev;return cur;}
}

递归

class Solution {public ListNode reverseList(ListNode head) {if (head == null || head.next == null) {return head;}ListNode newHead = reverseList(head.next);head.next.next = head;head.next = null;return newHead;}
}

(3) 合并两个有序链表

oj链接
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

class Solution {public ListNode mergeTwoLists(ListNode l1, ListNode l2) {ListNode prehead = new ListNode(-1);ListNode prev = prehead;while (l1 != null && l2 != null) {if (l1.val <= l2.val) {prev.next = l1;l1 = l1.next;} else {prev.next = l2;l2 = l2.next;}prev = prev.next;}prev.next = l1 == null ? l2 : l1;return prehead.next;}
}

递归

class Solution {public ListNode mergeTwoLists(ListNode l1, ListNode l2) {if (l1 == null) {return l2;}else if (l2 == null) {return l1;}else if (l1.val < l2.val) {l1.next = mergeTwoLists(l1.next, l2);return l1;}else {l2.next = mergeTwoLists(l1, l2.next);return l2;}}
}

(4)链表的中间结点

oj链接
给你单链表的头结点 head ,请你找出并返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

快慢指针

慢指针走一步,快指针走两步

while循环条件不能换顺序

class Solution {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;}
}

(5)链表中倒数第k个结点

牛客网链接
输入一个链表,输出该链表中倒数第k个结点。

public class Solution {public ListNode FindKthToTail(ListNode head,int k) {ListNode fast = head;ListNode slow = head;if(k<=0||head==null) return null;while(k-1>0) {if(fast.next == null) return null;fast = fast.next;k--;}while(fast.next!= null) {fast = fast.next;slow = slow.next;}return slow;}
}

(6)分割链表

oj链接
给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在大于或等于 x 的节点之前。

你不需要 保留 每个分区中各节点的初始相对位置。

class Solution {public ListNode partition(ListNode head, int x) {if(head==null) return null;ListNode less = new ListNode(-1);ListNode lessHead = less;ListNode larger = new ListNode(-1);ListNode largerHead = larger;while(head != null) {if(head.val<x) {less.next = head;less = less.next;} else {larger.next = head;larger = larger.next;}head = head.next;}larger.next = null;less.next = largerHead.next;return lessHead.next;}
}

方法二:

class Solution {public ListNode partition(ListNode head, int x) {ListNode cur = head;ListNode bs = null;ListNode be = null;ListNode as = null;ListNode ae = null;//使用cur来遍历 所有的节点while (cur != null) {if (cur.val < x) {if (bs == null) {bs = cur;be = cur;} else {be.next = cur;be = be.next;}} else {// >= xif (as == null) {as = cur;ae = cur;} else {ae.next = cur;ae = ae.next;}}cur = cur.next;}if (bs == null) {return as;}be.next = as;if (as != null) {ae.next = null;}return bs;}
}

如果bs为null,那么原链表最后一个节点(next是null)是ae,ae的next就不用置为null

(7)输入两个链表,找出它们的第一个公共结点(Y型)

oj链接
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

图示两个链表在节点 c1 开始相交:
在这里插入图片描述

public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {if (headA == null || headB == null) {return null;}ListNode pA = headA, pB = headB;while (pA != pB) {pA = pA == null ? headB : pA.next;pB = pB == null ? headA : pB.next;}return pA;}
}

(8)给你一个链表的头节点 head ,判断链表中是否有环。

oj链接
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。
思路
快慢指针,即慢指针一次走一步,快指针一次走两步,两个指针从链表起始位置开始运行,如果链表带环则一定会在环中相遇,否则快指针走到链表的末尾。

为什么快指针每次走两步,慢指针走一步可以?

假设链表带环,两个指针最后都会进入环,快指针先进环,慢指针后进环。当慢指针刚进环时,可
能就和快指针相遇了,最差情况下两个指针之间的距离刚好就是环的长度。此时,两个指针每移动
一次,之间的距离就缩小一步,不会出现每次刚好是套圈的情况,因此:在慢指针走到一圈之前,
快指针肯定是可以追上慢指针的,即相遇。

public class Solution {public boolean hasCycle(ListNode head) {ListNode fast = head;ListNode slow = head;while(fast != null &&  fast.next !=null) {fast = fast.next.next;slow = slow.next;if(fast == slow) {return true;}}return false;}
}

(9)给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

oj链接
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。
思路
设链表头部走x步到环的入口, 环有 y 个节点(包括环入口节点)
先跟上一题一样, fast走两步,slow走一步,如果有环的话在环中相遇.
设在环中走了s步(不包括环的入口节点)
那么slow走了x+s步
fast走了x+s+ny(n是圈数)
因为fast走的距离是slow的两倍
所以2(x+s) = x+s+n
y
即x=(n-1)*y+(y-s)
让fast从起始位置走,slow从相遇的位置走(n-1)*y+y-s步,他们会在环的入口相遇.

public class Solution {public ListNode detectCycle(ListNode head) {ListNode fast = head;ListNode slow = head;while(fast != null &&  fast.next !=null) {fast = fast.next.next;slow = slow.next;if(fast == slow) {fast = head;while(fast != slow) {fast = fast.next;slow = slow.next;}return fast;}}return null;}
}

(10)判定链表是否是回文

即正读和倒读一样的链表
牛客网链接
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。

给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
思路
先用快慢指针找到中间节点(奇数中间,偶数第二个中间结点),将中间节点之后的节点反转,一头从头结点,一头从末尾结点开始比较.

奇数的情况

当两个指针相遇的时候返回true

偶数的情况

当第一个节点的下一个节点是第二个节点且相等就返回true

public class PalindromeList {public boolean chkPalindrome(ListNode A) {if(A==null) {return true;}ListNode fast = A;ListNode slow = A;while(fast!=null&&fast.next!=null) {fast = fast.next.next;slow = slow.next;}ListNode prev = slow;ListNode cur =slow.next;while(cur!=null) {ListNode next = cur.next;cur.next = prev;prev = cur;cur = next;}while(A!=slow) {if(A.val!=prev.val) {return false;}//偶数的情况if(A.next==prev) {return true;}A=A.next;prev=prev.next;}return true;}
}

相关文章:

顺序表和链表面试题

文章目录 顺序表(1)原地移除数组中所有的元素val&#xff0c;要求时间复杂度为O(N)&#xff0c;空间复杂度为O(1)。(2)删除有序数组中的重复项(3)合并两个有序数组 链表(1)删除链表中等于给定值 val 的所有节点(2)反转一个单链表(3) 合并两个有序链表(4)链表的中间结点(5)链表中…...

树_二叉搜索树累加求和

//给出二叉 搜索 树的根节点&#xff0c;该树的节点值各不相同&#xff0c;请你将其转换为累加树&#xff08;Greater Sum Tree&#xff09;&#xff0c;使每个节点 node 的新值等于原树中大于或等于 // node.val 的值之和。 // // 提醒一下&#xff0c;二叉搜索树满足下列约束…...

gcc编译流程概述

前言 本篇文章介绍gcc编译器编译C文件的流程概述 比如我们创建了一个.c文件hello_gcc.c #include <stdio.h> int main() {printf("Hello gcc!!!\n");return 0; }最简单的方式就是在终端使用命令 gcc hello_gcc.c -o hello_gcc // 编译、汇编、链接 ./hello_…...

【web安全】ssrf漏洞的原理与使用

前言 菜某对ssrf漏洞的总结。 ssrf的作用 主要作用&#xff1a;访问外界无法访问的内网进行信息收集。 1.进行端口扫描&#xff0c;资源访问 2.指纹信息识别&#xff0c;访问相应的默认文件 3.利用漏洞或者和payload进一步运行其他程序 4.get类型漏洞利用&#xff0c;传参数…...

佳易王会员管理软件店铺积分以及积分兑换系统

一、佳易王会员管理软件大众版 部分功能简介&#xff1a; 1、会员信息登记 &#xff1a;可以直接使用手机号登记&#xff0c;也可以使用实体卡片&#xff0c;推荐用手机号即可。 2、会员卡类型 &#xff1a;可以自由设置卡的类型&#xff0c;比如&#xff1a;充值卡、计次卡、…...

Django回顾【二】

目录 一、Web框架 二、WSGI协议 三、 Django框架 1、MVC与MTV模型 2、Django的下载与使用 补充 3、启动django项目 补充 5、 Django请求生命周期 四、路由控制 1、路由是什么&#xff1f; 2、如何使用 3、path详细使用 4、re_path详细使用 5、反向解析 6、路由…...

[Ubuntu 18.04] RK3399搭建SSH服务实现远程访问

SSH(Secure Shell)是一种网络协议和软件,用于安全地远程登录到计算机并进行网络服务的加密通信。它提供了加密的认证和安全的数据传输,使得在不安全的网络中进行远程管理和访问变得更加安全。 以下是 SSH 服务的一些关键特点和用途: 安全认证:SSH 使用公钥/私钥加密技术…...

Linux进程间通信之共享内存

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;Linux &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要内容讲解共享内存原理和相关接口的介绍&#xff0c;以及一个…...

lv11 嵌入式开发 RTC 17

目录 1 RTC简介 ​编辑2 Exynos4412下的RTC控制器 2.1 概述 2.2 特征 2.3 功能框图 3 寄存器介绍 3.1 概述 3.2 BCD格式的年月日寄存器 3.3 INTP中断挂起寄存器 3.4 RTCCON控制寄存器 3.5 CURTICCNT 作为嘀嗒定时器使用的寄存器 4 RTC编程 5 练习 1 RTC简介 RTC(…...

c语言指针详解(上)

目录 一、指针的基本概念和用法 二、指针运算 2.1 指针的自增和自减运算 2.2 指针的自增和自减运算 三、数组和指针 四、指针和函数 4.1 在函数中使用指针作为参数和返回值 4.1.1 使用指针作为函数参数 4.1.2 使用指针作为函数返回值 4.2 指针参数的传值和传引用特性 4.2.1 指针…...

如何删除mac苹果电脑上面的流氓软件?

在使用苹果电脑的过程中&#xff0c;有时候我们也会遇到一些不需要的软件。无论是因为不再需要&#xff0c;或者是为了释放磁盘空间&#xff0c;删除这些软件是很重要的。本文将为大家介绍怎样删除苹果电脑上的软件&#xff01; CleanMyMac X全新版下载如下: https://wm.make…...

WordPress(11)给文章添加预计阅读时长

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、文件配置二、代码块1.引入库2.配置 single.php三、效果图前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了…...

周周爱学习之快速排序

快速排序&#xff0c;顾名思义&#xff0c;快速排序是一种速度非常快的一种排序算法 平均时间复杂度为O(),最坏时间复杂度为O()数据量较大时&#xff0c;优势非常明显属于不稳定排序 1.算法描述 每一轮排序选择一个基准点&#xff08;pivot&#xff09;进行分区 让小于基准点…...

国产接口测试工具APIpost

说实话&#xff0c;了解APIpost是因为&#xff0c;我的所有接口相关的文章下&#xff0c;都有该APIpost水军的评论&#xff0c;无非就是APIpost是中文版的postman&#xff0c;有多么多么好用&#xff0c;虽然咱也还不是什么啥网红&#xff0c;但是不知会一声就乱在评论区打广告…...

MySQL电商管理系统练习题及答案

一 、表结构 用户表(user)&#xff1a;id(主键)、username、password、email、phone、age商品表(product)&#xff1a;id(主键)、name、price、stock、description订单表(order)&#xff1a;id(主键)、user_id(外键&#xff0c;关联用户表)、total_price、status、create_time…...

每日3道PWN(第二天)

ciscn_2019_n_1 参考&#xff1a; [BUUCTF-pwn]——ciscn_2019_n_1-CSDN博客 [BUUCTF]PWN5——ciscn_2019_n_1_ciscn_2019_n_4-CSDN博客 BUUCTF—ciscn_2019_n_1 1-CSDN博客 checksec一下 64位栈溢出 按f5查看main函数&#xff0c;双击可疑函数 发现含有命令执行的且发现fl…...

SAP STMS传输请求

一、概述 一般SAP项目上都会有六套系统&#xff0c;分别是&#xff1a; 测试环境-DEV系统 主要由100&#xff1a;沙盘系统&#xff1a;用于业务顾问配置 200&#xff1a;开发系统&#xff1a;用于开发ABAP写代码 300&#xff1a;测试系统&#xff1a;主要是单元测试、顾问自己…...

L1-009:N个数求和

目录 ⭐题目描述⭐ ⭐分析 ⭐程序代码 运行结果 ⭐文案分享⭐ ⭐题目描述⭐ 本题的要求很简单&#xff0c;就是求N个数字的和。麻烦的是&#xff0c;这些数字是以有理数分子/分母的形式给出的&#xff0c;你输出的和也必须是有理数的形式。 输入格式&#xff1a; 输入第一行给出…...

当发送“Hello,World”时,channel发生了什么?

一、Netty概述 1.Netty是什么&#xff1f; Netty 是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于快速开发可维护、高性能的网络服务器和客户端。 2.Netty的地位怎么样&#xff1f; Netty 在 Java 网络应用框架中的地位就好比&#xff1a;Spring 框架在 JavaEE …...

服务器运行情况及线上排查问题常用命令

一、top命令 指令行&#xff1a; top返回&#xff1a; 返回分为两部分 &#xff08;一&#xff09;系统概览&#xff0c;见图知意 以下是几个需要注意的参数 1、load average&#xff1a; 系统负载&#xff0c;即任务队列的平均长度。三个数值分别为 1分钟、5分钟、15分…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

手机平板能效生态设计指令EU 2023/1670标准解读

手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读&#xff0c;综合法规核心要求、最新修正及企业合规要点&#xff1a; 一、法规背景与目标 生效与强制时间 发布于2023年8月31日&#xff08;OJ公报&…...

Ubuntu Cursor升级成v1.0

0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开&#xff0c;快捷键也不好用&#xff0c;当看到 Cursor 升级后&#xff0c;还是蛮高兴的 1. 下载 Cursor 下载地址&#xff1a;https://www.cursor.com/cn/downloads 点击下载 Linux (x64) &#xff0c;…...