跳房子——动态规划 存在n+1个房间,每个房间依次为房间1 2 3…i,每个房间都存在一个传送门,i房间的传送门可以把人传送到房间pi(1<=pi<=i),现在路人甲从房间1开始出发(当前房间1即第一次访问),每次移动他有两种移动策略:A. 如果访问过当前房间 i 偶数次,那么下一次移动到房间i+1;B. 如果访问过当前房间 i 奇数次,那么移动到房间pi;现在路人甲想知道移动到房间n+1一共需要多少次移动;输入描述:第一行包括一个数字n(30%数据1<=n<=100,100%数据 1<
错排问题(装错信封) NowCoder每天要给很多人发邮件。有一天他发现发错了邮件,把发给A的邮件发给了B,把发给B的邮件发给了A。于是他就思考,要给n个人发邮件,在每个人仅收到1封邮件的情况下,有多少种情况是所有人都收到了错误的邮件?即没有人收到属于自己的邮件。输入描述:输入包含多组数据,每组数据包含一个正整数n(2≤n≤20)。输出描述:对应每一组数据,输出一个正整数,表示无人收到自己邮件的种数。思路: 用A、B、C……表示写着n位友人名字的信封,a、b、c……表示n份相应的写好的信纸。把错装的总数为记作D(n)。
最长上升子串——动态规划 广场上站着一支队伍,她们是来自全国各地的扭秧歌代表队,现在有她们的身高数据,请你帮忙找出身高依次递增的子序列。 例如队伍的身高数据是(1、7、3、5、9、4、8),其中依次递增的子序列有(1、7),(1、3、5、9),(1、3、4、8)等,其中最长的长度为4。思路:定义一个dp[n]数组,dp[i]表示以0-i为下标字符串中的最长子序列长度。定义j的范围为0到i-1,如果原数组的arr[j]的值小于arr[i];则比较dp[i]和dp[j]+1值得大小替代dp[i].代码如下:import java.
最长公共子序列——动态规划 我们有两个字符串m和n,如果它们的子串a和b内容相同,则称a和b是m和n的公共子序列。子串中的字符不一定在原字符串中连续。例如字符串“abcfbc”和“abfcab”,其中“abc”同时出现在两个字符串中,因此“abc”是它们的公共子序列。此外,“ab”、“af”等都是它们的字串。现在给你两个任意字符串(不包含空格),请帮忙计算它们的最长公共子序列的长度。输入包含多组数据。每组数据包含两个字符串m和n,它们仅包含字母,并且长度不超过1024。对应每组输入,输出最长公共子序列的长度。思路:建立一个dp
自定义实现优先级队列(堆) 基于数组自定义实现一个最大堆,包括入堆,出堆,弹出堆顶元素,打印整个堆功能。public class MyHeap { private int[] elem; private int usedSize=0; // 初始化一个k大小的数组 public MyHeap(int k){ this.elem = new int[k]; } //入堆 public boolean offer(int val){ if(isF
红与黑——BFS 有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。你站在其中一块黑色的瓷砖上,只能向相邻的(上下左右四个方向)黑色瓷砖移动。请写一个程序,计算你总共能够到达多少块黑色的瓷砖。输入描述:输入包含多组数据。每组数据第一行是两个整数 m 和 n(1≤m, n≤20)。紧接着 m 行,每行包括 n 个字符。每个字符表示一块瓷砖的颜色,规则如下:“.”:黑色的瓷砖;“#”:白色的瓷砖;“@”:黑色的瓷砖,并且你站在这块瓷砖上。该字符在每个数据集合中唯一出现一次。输出描述:对应每组数据,输
蘑菇阵——动态规划 现在有两个好友A和B,住在一片长有蘑菇的由n*m个方格组成的草地,A在(1,1),B在(n,m)。现在A想要拜访B,由于她只想去B的家,所以每次她只会走(i,j+1)或(i+1,j)这样的路线,在草地上有k个蘑菇种在格子里(多个蘑菇可能在同一方格),问:A如果每一步随机选择的话(若她在边界上,则只有一种选择),那么她不碰到蘑菇走到B的家的概率是多少?输入描述:第一行N,M,K(1 ≤ N,M ≤ 20, k ≤ 100),N,M为草地大小,接下来K行,每行两个整数x,y,代表(x,y)处有一个蘑菇。输
JVM(Java虚拟机) JVM内存布局(HotSpot)JDK1.81、堆:(线程共享)所以的对象都是存在此区域的,此区域也是JVM最大的一块区域。JVM的垃圾回收就是针对此区域的。2、JVM 栈(Java虚拟机栈):(线程私有的)a) 局部变量表:八大基本数据类型,对象的引用。b) 操作栈:每个方法都会对应一个操作栈。c) 动态连接:指向常量池的方法引用。d) 方法返回地址:PC 寄存器的地址。3、本地方法栈:(线程私有的)它与JVM栈比较类似,只不过JVM栈是给Java和JVM使用,而本地方法栈他是为
java.util.concurrent 包下的常见类(JUC) 1、ReentrantLock可重入互斥锁注意事项:a) lock() 写在try之前。防止没有枷锁成功,影响正常逻辑调试。b)一定要记得在finally里面进行unLock()。2、信号量一个计数信号量,主要用于控制多线程对共同资源库访问的限制。着重说两个方法:acquire()void:尝试获取锁,如果可以正常获取到,则执行后面的业务逻辑,如果获取失败,则阻塞等待。release() void:释放锁这里用停车场的思想来演示一下:import java.util.Random;i
栈和队列的互相转换 用两个栈实现一个队列,包括入队,出队,弹出队首元素,判断队列是否为空功能。import java.util.Stack;public class StackToQueue<T> { private Stack<T> s1 = new Stack<>(); private Stack<T> s2 = new Stack<>(); //入队 public void offer(T val){ thi
自定义队列和自定义循环队列 用链表自定义实现一个队列,包括入队,出队,弹出队首元素,队列是否为空功能class Node<T>{ public T val; public Node<T> next; public Node(T val){ this.val = val; }}public class MyQueue<T>{ public Node<T> first;//队头 public Node<T> l
自定义一个栈 基于数组创建一个栈,有入栈,出栈,弹出栈顶元素,判断栈是否为空,是否为满功能。public class MyStack<T> { private T[] elem; private int top=0; //top表示当前可以存放元素的下标 //构造方法,初始化一个长度为5的数组 public MyStack(){ this.elem = (T[])new Object[5]; } //入栈 public T push(T
锁策略总结 乐观锁乐观锁:它认为一般情况下不会发生并发冲突,所以只有在进行数据更新的时候,才会检测并发冲突,如果没有冲突,则直接修改,如果有冲突,则返回失败。CAS(Compare And Swap 比较并且交换):V(内存值)A(旧值)B(新值)具体流程:V==A?true(没有并发冲突)->V=B; : false(并发冲突)线程的解决方案:加锁、ThreadLocal、Atomic*乐观锁 Atomic*我们先来看一个示例:public class ThreadDemoGJ1 {
单例模式与自定义阻塞队列 提升程序性能的方法1、多线程2、单例模式:整个程序的运行中,只存在一个对象。饿汉方式:上来不管啥先创建一个对象再说。(不用加锁也是线程安全的)懒汉方式:当程序启动之后并不会初始化,而是在什么时候调用,什么时候再初始化。设计模式:1、单例模式(手写)2、工厂模式(简单工厂、抽象工厂)3、模板模式…饿汉方式public class ThreadDemoEH1 { static class Singleton{ //1、创建私有的构造函数(为了防止其他类直接创建)
ThreadLocal 线程解决方案1、 加锁加锁⽅案虽然可以正确的解决线程不安全的问题,但同时也引⼊了新的问题,加锁会让程序进⼊排 队执⾏的流程,从⽽⼀定程度的降低了程序的执⾏效率,那有没有⼀种⽅案既能解决线程不安全的 问题,同时还可以避免排队执⾏呢?2、ThreadLocal(ThreadLocal 线程本地变量 :线程级别的私有变量,与任务级别的私有变量完全不同)ThreadLocal经典实用场景:1、解决线程安全问题2、实现线程级别的数据传递ThreadLocal使用1、set(T):将私有变量存放到线程
二叉树四种遍历方式总结——非递归 实现二叉树先序,中序,后序以及层序遍历1、先序遍历具体步骤:1、创建一个栈和一个ArrayList。2、先让根节点入栈。3、当栈不为空时,栈顶出栈,并将出栈节点值保存到ArrayList中,然后再依次将出栈节点的右子节点,左子节点入栈。ps:因为前序遍历要左子节点在右子节点前面,所以先入栈右子节点,后入栈左子节点(栈是先进后出)代码展示:public void preorder(TreeNode root,ArrayList<Integer> list){ if(
线程池的创建 线程的缺点1.线程的创建需要开辟内存资源:本地方法栈、虚拟机栈、程序计数器等线程私有变量的内存。频繁的创建和销毁,会带来一定的性能的开销。2、使用线程不能很好的管理任务和友好的拒绝任务。所有就引入了线程池这一技术。线程池线程池定义:使用池化技术来管理和使用线程的技术。这种技术就叫线程池。线程池里面的重要内容:1、线程2、任务队列线程池的执行流程:当拿到一个任务之后,会判断当前线程池里面的数量是否达到了最大值,如果没有达到创建新的线程执行任务;当任务来了之后,线程池的线程数量已经是最大值,并
对于一个字符串,请设计一个高效算法,计算其中最长回文子串的长度。 题目对于一个字符串,请设计一个高效算法,计算其中最长回文子串的长度。给定字符串A以及它的长度n,请返回最长回文子串的长度。在这里,我自己用了两个方法去完成这个题。分享给大家。1、中心扩散法中心扩散法很好理解,就是遍历字符串中的每一个字符,以这个字符为中心去向两边扩散,然后依次更替最长的回文字符子串的长度。举个列子:但是现在有一个问题,就是如果下一个字符跟现在的字符相同,我们就得向右移动右边的指针,因为不管是奇数还是偶数,相同字符组成的字符串它总是回文的。代码展示:public clas
排序算法总结 为了统一起见,我先给出一个主函数,条例比较清晰public static void main(String[] args) { int[] array = {34,2,67,88,54,33,78,22,4,90,86,45,6,12,99}; System.out.println(Arrays.toString(array)); insertSort(array); System.out.println("直接插入排序:"+Arrays.t
多线程之死锁、休眠 死锁问题定义:在多线程编程中(两个或两个以上的线程),因为资源抢占而造成线程无限等待的问题。线程和锁的关系:一对多 一个线程可以拥有多把锁,而一把锁只能被一个线程所拥有。检测死锁工具 jconsole jmc jvisualvm排查死锁死锁的关键代码synchronized (lockA){ System.out.println("线程1得到了锁A"); try { //休眠1秒 让线程2先得到锁B Thread.sleep(1000);