一、链表结构

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) 第二节 链表结构、栈、队列、递归行为、哈希表和有序表的更多相关文章

  1. Java数据结构和算法(一)线性结构之单链表

    Java数据结构和算法(一)线性结构之单链表 prev current next -------------- -------------- -------------- | value | next ...

  2. 数据结构与算法【Java】08---树结构的实际应用

    前言 数据 data 结构(structure)是一门 研究组织数据方式的学科,有了编程语言也就有了数据结构.学好数据结构才可以编写出更加漂亮,更加有效率的代码. 要学习好数据结构就要多多考虑如何将生 ...

  3. Java数据结构和算法(一)线性结构

    Java数据结构和算法(一)线性结构 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 线性表 是一种逻辑结构,相同数据类型的 ...

  4. 【学习总结】java数据结构和算法-第三章-稀疏数组和队列

    相关链接 [学习总结]尚硅谷2019java数据结构和算法 github:javaDSA 目录 稀疏数组 队列 稀疏数组 稀疏数组介绍 图示 应用实例 代码实现 SparseArray.java:与二 ...

  5. JavaScript 版数据结构与算法(三)链表

    今天,我们要讲的是数据结构与算法中的链表. 链表简介 链表是什么?链表是一种动态的数据结构,这意味着我们可以任意增删元素,它会按需扩容.为何要使用链表?下面列举一些链表的用途: 因为数组的存储有缺陷: ...

  6. Java数据结构和算法(七)——链表

    前面博客我们在讲解数组中,知道数组作为数据存储结构有一定的缺陷.在无序数组中,搜索性能差,在有序数组中,插入效率又很低,而且这两种数组的删除效率都很低,并且数组在创建后,其大小是固定了,设置的过大会造 ...

  7. 为什么我要放弃javaScript数据结构与算法(第二章)—— 数组

    第二章 数组 几乎所有的编程语言都原生支持数组类型,因为数组是最简单的内存数据结构.JavaScript里也有数组类型,虽然它的第一个版本并没有支持数组.本章将深入学习数组数据结构和它的能力. 为什么 ...

  8. 数据结构与算法之美 06 | 链表(上)-如何实现LRU缓存淘汰算法

    常见的缓存淘汰策略: 先进先出 FIFO 最少使用LFU(Least Frequently Used) 最近最少使用 LRU(Least Recently Used) 链表定义: 链表也是线性表的一种 ...

  9. 为什么我要放弃javaScript数据结构与算法(第三章)—— 栈

    有两种结构类似于数组,但在添加和删除元素时更加可控,它们就是栈和队列. 第三章 栈 栈数据结构 栈是一种遵循后进先出(LIFO)原则的有序集合.新添加的或待删除的元素都保存在栈的同一端,称为栈顶,另一 ...

  10. 剑指offer_面试题5_从尾到头打印链表(栈和递归实现)

    题目:输入一个链表的头结点,从尾到头反过来打印出每一个节点的值 考察 单链表操作.栈.递归等概念. 理解:要实现单链表的输出,那么就须要遍历.遍历的顺序是从头到尾.而节点输出的顺序是从尾到头.因此,先 ...

随机推荐

  1. pyinstaller打包程序后提示No module named ‘xxxx‘

    解决方法1 1.检查 先在venv环境中安装xxx 报错的这个包 以我的举例 查看settings>project interpreter  (存在对应的包) 解决方法2 2.在xxx.spec ...

  2. MySQL中如何定位阻塞语句

    数据库中阻塞语句的查询和分析 前言 MySQL 1.使用 show processlist 查询正在运行的进程 2.使用 INNODB_TRX 查询当前运行的事务 3.使用 INNODB_LOCKS ...

  3. docker部署zabbix 6.0高可用集群实验

    0 实验环境 虚拟机,postgresql本地部署,zabbix server及nginx容器部署 1 postgresql 参看前作 <postgresql + timescaledb离线安装 ...

  4. expect: telnet2switch

    #!/usr/bin/expect if {$argc != 1} { puts "usage: ./telnet2sswitch <r2|r3>" exit } if ...

  5. Cilium 系列-7-Cilium 的 NodePort 实现从 SNAT 改为 DSR

    系列文章 Cilium 系列文章 前言 将 Kubernetes 的 CNI 从其他组件切换为 Cilium, 已经可以有效地提升网络的性能.但是通过对 Cilium 不同模式的切换/功能的启用,可以 ...

  6. React:styled-components有趣的用法

    背景 用于记录一些styled-components的有趣的用法 绑定a标签的链接 编写伪类 在styleComponents中使用参数 传入参数

  7. JavaScript代码片段精选

    今天,我在职坐标的微信公众号里面看到了关于  JavaScript代码片段精选 的 微信软文.在实际开发中,我们经常会使用的JS来实现某些功能.今天,就在此总结一下. 1.浮点数取整 const x ...

  8. 关于Tensorflow!目标检测预训练模型的迁移学习

    ​ 前言 关于TF的目标检测迁移学习,我一开始是想通过Tensorflow提供的API,用JS来实现的.但是官方不但没有案例,网上也没有踩坑的博客,加之我又着急要弄水印检测. 于是就在网上看了很多人用 ...

  9. ES集群&kibana安装

    一.elasticsearch介绍 Elasticsearch 是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful 风格接口,多数据源,自动搜索负 ...

  10. AI绘画Stable Diffusion实战操作: 62个咒语调教-时尚杂志封面

    今天来给大家分享,如何用sd简单的咒语输出好看的图片的教程,今天做的是时尚杂志专题,话不多说直入主题. 还不会StableDiffusion的基本操作,推荐看看这篇保姆级教程: AI绘画:Stable ...