数据结构与算法(LeetCode) 第二节 链表结构、栈、队列、递归行为、哈希表和有序表
一、链表结构
1.单向链表节点结构
public class Node{
public int value;
public Node next;
public Node(int data){
value=data;
}
}
2.双向链表节点结构
public class DoubleNode{
public int value;
public DoubleNode last;
public DoubleNode next;
public DoubleNode(int data){
value=data;
}
}
3.单向链表与双向链表最简单的练习
3.1单向链表与双链表如何反转
//单向链表反转
public static Node reverseLinkedList(Node head){
Node pre =null;
Node next = null;
while(head !=null){
next=head.next;
head.next=pre;
pre=head;
head=next;
}
//返回新的头结点
return pre;
}
//双向链表反转
public static DoubleNode reverseDoubleList(DoubleNode head){
DoubleNode pre=null;
DoubleNode next=null;
while(head!=null){
next=head.next;
head.next=pre;
head.last=next;
pre=head;
head=next;
}
//返回头结点
return pre;
}
3.2把给定值删除
//删除一个单链表中值为num的节点
public static Node removeValue(Node head,int num){
//判断头部节点需要删多少个
//如在3-3-3-3-2-2-1链表中,删掉值为3的节点,则需要删掉4个头部节点
while(head !=null){
if(head.value !=num){
break;
}
head=head.next;
}
//head来到第一个不需要删除的位置
Node pre=head;
Node cur=head;
while(cur != null){
//注意:java中会自动释放无法找到的节点,不需要手动释放
if(cur.value == num){
pre.next =cur.next;
}else{
pre=cur;
}
cur= cur.next;
}
retuen pre;
}
二、栈和队列
1.逻辑概念
栈:数据先进后出
队列:数据先进先出
2.栈和队列的实际实现
双向链表实现
数组实现
1.使用双向链表实现栈和队列
(1)使用双向链表模拟栈与队列的进出操作
public static class DoubleEndsQueue<T>{
public Node<T> head;//头指针
public Node<T> tail;//尾指针
//如果从头部开始加节点采用以下方法
public void addFormHead(T value){
Node<T> cur=new Node<T>(value);
if(head==null){
head=cur;
tail=cur;
}else{
cur.next=head;
head.last=cur;
head=cur;
}
}
//如果从尾部开始加节点采用以下方式
public void addFromBottom(T value){
Node<T> cur =new Node<T>(value);
if(head ==null){
head=cur;
tail=cur;
}else{
cur.last=tail;
tail.next=cur;
tail=cur;
}
}
//从头部弹出节点
public T popFromHead(){
if(head==null){
return null;
}
Node<T> cur=head;
if(head==tail){//如果链表中只有一个节点
head=null;
tail=null;
}else{
head=head.next;
cur.next=null;
head.last=null;
}
return cur.value;
}
//从尾部弹出节点
public T popFromBottom(){
if(head==null){
return null;
}
Node<T> cur=tail;
if(head==tail){//如果链表中只有一个节点
head=null;
tail=null;
}else{
tail=tail.last;
tail.next=null;
cur.last=null;
}
return cur.value;
}
}
(2)双向链表创建栈
public static class MyStack<T{
private DoubleEndsQueue<T> queue;
public MyStack(){
queue=new DoubleEndsQueue<T>();
}
//从头部插入从头部弹出,实现先进后出
//往栈中插入数据
public void push(T value){
queue.addFromHead(value);
}
//将数据弹出栈
public T pop(){
return queue.popFromHead();
}
//判断是否为空
public boolean isEmpty(){
return queue.isEmpty();
}
}
(3)双向链表创建队列
public static class MyQueue<T{
private DoubleEndsQueue<T> queue;
public MyStack(){
queue=new DoubleEndsQueue<T>();
}
//从头部插入从尾部弹出,实现先进先出
//往栈中插入数据
public void push(T value){
queue.addFromHead(value);
}
//将数据弹出栈
public T pop(){
return queue.popFromBottom();
}
//判断是否为空
public boolean isEmpty(){
return queue.isEmpty();
}
}
2.使用数组实现栈和队列
提示:只考虑固定大小数组
(1)数组实现队列:实现环形数组
public static class MyQueue{
private int[] arr;
private int pushi;//记录插入数据的位置
private int polli;//记录弹出数据的位置
private int size;//记录队列中的数据个数
private final int limit;//数组大小
//初始化数组
publish MyQueue(int limit){
arr=new int[limit];
pushi = 0;
polli=0;
size=0;
this.limit=limit;
}
//进队列
public void push(int value){
if(size==limit){
throw new RuntimeException("队列已满,不可再入队")
}
size++;
arr[pushi]=value;
pushi=nextIndex(pushi);
}
//出队列
public int pop(){
if(size==0){
throw new RuntimeException("栈为空");
}
size--;
int ans=arr[polli];
polli=nextIndex(polli);
return ans;
}
//判断是否为空
public boolean isEmpty(){
return size==0;
}
//如果现在的下标是i,返回下一个位置,
private int nextIndex(int i){
//判断i是否到了数组的最后一个位置,如果是,从0开始
return i<limit-1 ? i+1:0;
}
}
(2)数组实现栈
public static class MyStack{
private int[] arr;
private int size;//记录栈的数据大小
private final int limit;//数组大小
//初始化数组
publish MyQueue(int limit){
arr=new int[limit];
size=0;
this.limit=limit;
}
//进栈
public void push(int value){
if(size==limit){
throw new RuntimeException("队列已满,不可再入队")
}else{
size++;
arr[size]=value;
}
}
//出栈
public int pop(){
if(size==0){
throw new RuntimeException("栈为空");
}
size--;
int ans=arr[size];
return ans;
}
//判断是否为空
public boolean isEmpty(){
return size==0;
}
}
3.栈和队列的常见面试题
(1)实现一个特殊的栈,在基本功能的基础上,再实现返回栈中最小元素的功能
1) pop、push、getMin操作的时间复杂度都是O(1)。
2)设计的栈类型可以使用现成的栈结构。实现思路:准备两个栈,一个栈为正常的数据栈Data,一个栈Min来存放最小值,每次插入一个新数据newNum,Data正常插入,插入Min中是每次要与栈顶比较大小
public static class MyStack2{
//创建两个栈
private Stack<Integer> stackData;
private Stack<Integer> stackMin;
public MyStack2(){
this.stackData=new Stack<Integer>();
this.stackMin=new Stack<Integer>();
}
public void push(int newNum){
//往stackMin中放数据时,需要将数据与Min栈顶的数据进行比较,
// 以确保Min插入的每一个数据都是最新的最小值
if(this.stackMin,isEnpty()){
this.stackMin.push(newNum);
}else if(newNum<this.getmin()){
this.stackMin.push(newNum);
}else{
int newMin =this.stackMin.peek();
this.stackMin.push(newMin);
}
this.stackData.push(newNum);
}
public int pop(){
if(this.stackData.isEmpty()){
throw new RuntimeException("栈为空");
}
this.stackMin.pop();
return this.stackData.pop();
}
public int getmin(){
if (this.stackMin.isEmpty()){
throw new RuntimeException("栈为空");
}
//返回栈栈顶数据
return this.stackMin.peek();
}
}
三、递归
判断递归的复杂度
Master公式
形如 T(N)= a * T(N/b)+O(N^d)(其中的a、b、d都是常数)的递归函数,可以直接通过Master公式来确定时间复杂度如果log(b,a)< d,复杂度为O(N^d)
如果log(b,a) > d,复杂度为O(N^log(b,a))
如果log(b,a) == d,复杂度为O(N^d * logN)
四、哈希表与有序表
1.哈希表(HashMap)
1)哈希表在使用层面上可以理解为一种集合结构
2)如果只有key,没有伴随数据value,可以使用HashSet结构
3)如果既有key,又有伴随数据value,可以使用HashMap结构
4)有无伴随数据,是HashMap和HashSet唯一的区别,实际结构是一回事
5)使用哈希表增(put)、删(remove)、改(put)和查(get)的操作,可以认为时间复杂度为o(1),但是常数时间比较大
6)放入哈希表的东西,如果是基础类型,内部按值传递,内存占用是这个东西的大小
7)放入哈希表的东西,如果不是基础类型,内部按引用传递,内存占用是8字节
2.有序表(TreeMap)
1)有序表在使用层面上可以理解为一种集合结构。
2)如果只有key,没有伴随数据value,可以使用set结构
3)如果既有key,又有伴随数据value,可以使用map结构
4)有无伴随数据是set与map的唯一区别,底层的实际结构是一回事。
5)有序表和哈希表的区别是,有序表把key按顺序组织起来,而哈希表完全不组织。
6)只要是有序表,他的常见操作的时间复杂度都是O(logN)
数据结构与算法(LeetCode) 第二节 链表结构、栈、队列、递归行为、哈希表和有序表的更多相关文章
- Java数据结构和算法(一)线性结构之单链表
Java数据结构和算法(一)线性结构之单链表 prev current next -------------- -------------- -------------- | value | next ...
- 数据结构与算法【Java】08---树结构的实际应用
前言 数据 data 结构(structure)是一门 研究组织数据方式的学科,有了编程语言也就有了数据结构.学好数据结构才可以编写出更加漂亮,更加有效率的代码. 要学习好数据结构就要多多考虑如何将生 ...
- Java数据结构和算法(一)线性结构
Java数据结构和算法(一)线性结构 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 线性表 是一种逻辑结构,相同数据类型的 ...
- 【学习总结】java数据结构和算法-第三章-稀疏数组和队列
相关链接 [学习总结]尚硅谷2019java数据结构和算法 github:javaDSA 目录 稀疏数组 队列 稀疏数组 稀疏数组介绍 图示 应用实例 代码实现 SparseArray.java:与二 ...
- JavaScript 版数据结构与算法(三)链表
今天,我们要讲的是数据结构与算法中的链表. 链表简介 链表是什么?链表是一种动态的数据结构,这意味着我们可以任意增删元素,它会按需扩容.为何要使用链表?下面列举一些链表的用途: 因为数组的存储有缺陷: ...
- Java数据结构和算法(七)——链表
前面博客我们在讲解数组中,知道数组作为数据存储结构有一定的缺陷.在无序数组中,搜索性能差,在有序数组中,插入效率又很低,而且这两种数组的删除效率都很低,并且数组在创建后,其大小是固定了,设置的过大会造 ...
- 为什么我要放弃javaScript数据结构与算法(第二章)—— 数组
第二章 数组 几乎所有的编程语言都原生支持数组类型,因为数组是最简单的内存数据结构.JavaScript里也有数组类型,虽然它的第一个版本并没有支持数组.本章将深入学习数组数据结构和它的能力. 为什么 ...
- 数据结构与算法之美 06 | 链表(上)-如何实现LRU缓存淘汰算法
常见的缓存淘汰策略: 先进先出 FIFO 最少使用LFU(Least Frequently Used) 最近最少使用 LRU(Least Recently Used) 链表定义: 链表也是线性表的一种 ...
- 为什么我要放弃javaScript数据结构与算法(第三章)—— 栈
有两种结构类似于数组,但在添加和删除元素时更加可控,它们就是栈和队列. 第三章 栈 栈数据结构 栈是一种遵循后进先出(LIFO)原则的有序集合.新添加的或待删除的元素都保存在栈的同一端,称为栈顶,另一 ...
- 剑指offer_面试题5_从尾到头打印链表(栈和递归实现)
题目:输入一个链表的头结点,从尾到头反过来打印出每一个节点的值 考察 单链表操作.栈.递归等概念. 理解:要实现单链表的输出,那么就须要遍历.遍历的顺序是从头到尾.而节点输出的顺序是从尾到头.因此,先 ...
随机推荐
- pyinstaller打包程序后提示No module named ‘xxxx‘
解决方法1 1.检查 先在venv环境中安装xxx 报错的这个包 以我的举例 查看settings>project interpreter (存在对应的包) 解决方法2 2.在xxx.spec ...
- MySQL中如何定位阻塞语句
数据库中阻塞语句的查询和分析 前言 MySQL 1.使用 show processlist 查询正在运行的进程 2.使用 INNODB_TRX 查询当前运行的事务 3.使用 INNODB_LOCKS ...
- docker部署zabbix 6.0高可用集群实验
0 实验环境 虚拟机,postgresql本地部署,zabbix server及nginx容器部署 1 postgresql 参看前作 <postgresql + timescaledb离线安装 ...
- expect: telnet2switch
#!/usr/bin/expect if {$argc != 1} { puts "usage: ./telnet2sswitch <r2|r3>" exit } if ...
- Cilium 系列-7-Cilium 的 NodePort 实现从 SNAT 改为 DSR
系列文章 Cilium 系列文章 前言 将 Kubernetes 的 CNI 从其他组件切换为 Cilium, 已经可以有效地提升网络的性能.但是通过对 Cilium 不同模式的切换/功能的启用,可以 ...
- React:styled-components有趣的用法
背景 用于记录一些styled-components的有趣的用法 绑定a标签的链接 编写伪类 在styleComponents中使用参数 传入参数
- JavaScript代码片段精选
今天,我在职坐标的微信公众号里面看到了关于 JavaScript代码片段精选 的 微信软文.在实际开发中,我们经常会使用的JS来实现某些功能.今天,就在此总结一下. 1.浮点数取整 const x ...
- 关于Tensorflow!目标检测预训练模型的迁移学习
前言 关于TF的目标检测迁移学习,我一开始是想通过Tensorflow提供的API,用JS来实现的.但是官方不但没有案例,网上也没有踩坑的博客,加之我又着急要弄水印检测. 于是就在网上看了很多人用 ...
- ES集群&kibana安装
一.elasticsearch介绍 Elasticsearch 是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful 风格接口,多数据源,自动搜索负 ...
- AI绘画Stable Diffusion实战操作: 62个咒语调教-时尚杂志封面
今天来给大家分享,如何用sd简单的咒语输出好看的图片的教程,今天做的是时尚杂志专题,话不多说直入主题. 还不会StableDiffusion的基本操作,推荐看看这篇保姆级教程: AI绘画:Stable ...