2020.6.5复习栈的内容

1.在做题的时候发现忘记了用栈模拟队列的形式和用队列模拟栈的形式打算每天复习一点之前的东西,在昨晚每日一题之后,从今天开始执行,希望能坚持到底因为做重要的不是你重新学习了哪些新的知识而是你有没有好好回顾之前学习的知识,把基础打扎实。
利用两个队列来实现栈:我们首先先建立两个队列分别是queue1和queue2他们两个的底层使用LinkedList实现的
首先入栈利用这两个队列的特点队列是先进先出的,我们首先判断这两个队列哪个是空的谁是不是空的,把数组往不是空的那个队列里面放,如果两个队列都是空的我们选择queue1作为放数组的队列。当我们把数组全部放到这两个队列中去了,想要出栈的时候,我们清楚得把不是空的哪个队列的前n-1个数组poll到另一个空的队列当中去,才能得到栈中最顶端的元素,把没有poll出去的本属于栈顶的元素用data记下来,最后pop出去,我们就相当于把栈顶的元素pop出去了,但是首先有一点我们必须清楚,就是分两个if语句判断哪个队列中不为空就poll哪个队列的前n-1个。当然我们还需要自己写一个empty()函数来以此判断两个队列都为空的情况下就结束程序;
接下来我们来top栈顶的元素但是不pop出去仅仅是得到栈顶的值而已,这个和上面的方法相同,首先你得判断那个队列不是空的就用这个队列的大小作为for循环的结束条件,当每次进入这个队列的时候并且遍历的数组长度小于此队列的长度时(注意在此时不用给size-1,因为计算的是栈顶)我们用每次弹出的元素用打他记录下来,当然也得吧弹出的所有元素放到另一个队列当中,当我们弹出队列当中的最后一个元素时data也就记录这最后一个元素的值,此时返回data就相当于找到了我们栈顶的元素。

import java.util.LinkedList;
import java.util.Queue;

public class Mystack{
private Queue queue1;
private Queue queue2;
public void Mystack(){
this.queue1 = new LinkedList<>();
this.queue2 = new LinkedList<>();
}
public void push(int x) {
if (!queue1.isEmpty()) {
queue1.offer(x);
} else if(!queue2.isEmpty()){
queue2.offer(x);
}else{
queue1.offer(x);
}
}
public int pop(){
if(empty()){
return -1;
}
int size1 = queue1.size();
int size2 = queue2.size();
int data = 0;
if(!queue1.isEmpty()){
for(int i=0;i<size1-1;i++){
queue2.offer(queue1.poll());
}
data = queue1.poll();
}else {
for(int i =0;i<size2-1;i++){
queue1.offer(queue2.poll());
}
data = queue2.poll();
}
return data;
}
public int top(){
if(empty()) {
return -1;
}
int size1 = queue1.size();
int size2 = queue2.size();
int data = 0;
if(!queue1.isEmpty()){
for(int i=0;i<size1;i++){
data = queue1.poll();
queue2.offer(data);
}

    }else{
        for( int i=0;i<size2;i++){
            data = queue2.poll();
            queue1.offer(data);
        }
    }
    return data;
}
public boolean empty(){
    if(queue1.isEmpty()&&queue2.isEmpty()){
        return true;
    }
    return false;
}

}
同理当我们想用栈来实现队列的时候需要准备两个栈,我们知道栈是先进的后出,与队列相反,利用两个栈把不为空的那个栈的元素全部pop到另一个为空的栈当中,此时再弹出这个栈,就相当于我们的队列弹出的顺序了。
还是想要入队列,此时选择stack1作为存放数据的栈,直接把数组给push进去即可,当我们想要得到队列顶端的元素时,判断stack2是为空的?为空的时候就写一个for循环,结束的条件是当stack1里面为空的时候,此时弹出stack2的顶端元素就可得知队列的顶端元素是什么。当然了得到队列顶端的元素当然了peek队列顶端的元素也相同。

import java.util.Stack;

/*
利用栈来实现队列
/
public class MyQueue{
private Stack stack1;
private Stack stack2;
public void MyQueue(){
this.stack1 = new Stack<>();
this.stack2 = new Stack<>();
}
public void push(int x){
stack1.push(x);
}
public int pop(){
if(empty()){
return -1;
}
if(stack2.isEmpty()){
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
}
return stack2.pop();
}
public int peek(){
if(empty()){
return -1;
}
if(stack2.isEmpty()){
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
}
return stack2.peek();
}
public boolean empty(){
if(stack1.isEmpty() && stack2.isEmpty()){
return true;
}
return false;
}
}
2.当我们想要计算一串字符串当中的最长数字串时必须滤除掉那些是字母的字符串接下来我将会写三种方法:
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
Stirng str = scanner.nextLine();
String[] s = str.splite("\D+");
int max = 0;
String f = " ";
for(int i=0;i<s.length;i++){
if(s[i].length()>max){
max = s[i].length();
f = s[i];
}
}
System.out.println(f);
}
}
再用到学校给的方法时发现我忘记了substring方法,它是截取字符串的给一个参数就返回这个位置之后的字符串,给两个位置就返回这两个位置的中间字符串应该是左闭右开的,来时曾经说过大部分的都是左闭右开的。
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String str = sc.nextLine();
int count = 0;
int max = 0;
int end = 0;
for(int i = 0;i<str.length();i++){
if(str.charAt(i)>=‘0’ && str.charAt(i)<=‘9’){//一定要注意准化成字符之后要对数字加‘’这个,注意还有substring的使用。
count++;
if(count>max){
max = count;
end = i;
}
}else{
count =0;
}
}
System.out.println(str.substring(end-max+1,end+1));
}
}
}
当我在写括号匹配的时候我不知道刚开始用什么写最后看了别人的代码知道了原来括号匹配问题大部分是用栈来写的,首先给你一个字符串让你看看这个里面是不是括号匹配的,你建立一个for循环把这些字符串变成一个个字符与()进行匹配如果是(这个类型的括号就将他压入栈中,如果是这个)类型的字符就先判断一下栈是不是空的如果栈是空的那么肯定返回false,不是空的就将栈顶的元素给弹出来,到这里之后你发现你是不是没有考虑(a)这种情况,所以遍历到既不是左括号也不是有括号的时候直接返回false说明这个字符就不是括号。当然了for循环结束之后你还要进行一个栈是否为空判断,因为你如果是()括号匹配的就将战中的元素都pop出去了,加入都遍历完所有的字符了,你站中还有元素那证明要么括号不匹配要么就是你的栈中还有像a,b这种类型的字符,肯定是错的;
import java.util.
;

public class Parenthesis {
public boolean chkParenthesis(String A, int n) {
Stack stack = new Stack<>();
if(A == null || A.length() != n ){
return false;
}
for(int i = 0;i<n;i++){
if(A.charAt(i) == ‘(’){
stack.push(A.charAt(i));
}else if( A.charAt(i) == ‘)’){
if(stack.isEmpty()){
return false;
}else{
stack.pop();
}
}else{
return false;
}
}
if(! stack.isEmpty()){
return false;
}else{
return true;
}
}
}
4 面向对象开发中,引用传递意味着传递的并不是实际的对象,而是对象的引用,因此,外部对引用对 象所做的改变不会反映到所引用的对象上;
5 在这里插入图片描述可以看到遇到这个题是在每日一题中的我总结了下后面的黄色代码相当于死代码在idea中会包黄,可以说写不写都可以不影响结果:在这里插入图片描述
在以上这里插入图片描述
可以看到结果是false;

6.在考试时经常会出现关于线程的题,有很多我都已经忘记了我要好好看看这一方面的知识:

Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别?

sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保持,因此休眠时间结束后会自动恢复。wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lock pool),如果线程重新获得对象的锁就可以进入就绪状态。

线程的sleep()方法和yield()方法有什么区别?

① sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;
  yield()方法只会给相同优先级或更高优先级的线程以运行的机会;
② 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;
③ sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;
④ sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植性。
7.HashMap底层是由数组+链表/红黑树构成的,
8 String没有decode和encode方法,Spring没有fromBytes()方法。
如何实现GBK编码字节流到UTF-8编码字节流的转换下面是正确的:
dst=new String(src,“GBK”).getBytes(“UTF-8”)
用new String(src,“GBK”)解码得到字符串
用getBytes(“UTF-8”)得到UTF8编码字节数组
9 java中return在Try-Catch中的执行顺序:分为两种情况
(1)try{} catch(){}finally{} return;这种程序就按照顺序执行了
(2)try{ return; }catch(){} finally{} return;
程序执行try块中return之前(包括return语句中的表达式运算)代码;
再执行finally块,最后执行try中return;
finally块之后的语句return,因为程序在try中已经return所以不再执行。
(3)try{ } catch(){return;} finally{} return;
程序先执行try,如果遇到异常执行catch块,
有异常:则执行catch中return之前(包括return语句中的表达式运算)代码,再执行finally语句中全部代码,
最后执行catch块中return. finally之后也就是4处的代码不再执行。
无异常:执行完try再finally再return.
(4):try{ return; }catch(){} finally{return;}程序执行try块中return之前(包括return语句中的表达式运算)代码;
再执行finally块,因为finally块中有return所以提前退出。
情况5:try{} catch(){return;}finally{return;}程序执行catch块中return之前(包括return语句中的表达式运算)代码;
再执行finally块,因为finally块中有return所以提前退出。
情况6:try{ return;}catch(){return;} finally{return;} 程序执行try块中return之前(包括return语句中的表达式运算)代码;
有异常:执行catch块中return之前(包括return语句中的表达式运算)代码;
则再执行finally块,因为finally块中有return所以提前退出。
无异常:则再执行finally块,因为finally块中有return所以提前退出。
1、不管有没有出现异常,finally块中代码都会执行;
2、当try和catch中有return时,finally仍然会执行;
3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,不管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;
4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。
任何执行try 或者catch中的return语句之前,都会先执行finally语句,如果finally存在的话。
如果finally中有return语句,那么程序就return了,所以finally中的return是一定会被return的,
编译器把finally中的return实现为一个warning。
5Java编译后生成字节码文件即.class文件,然后JVM将字节码文件翻译成机器码文件由CPU执行。
6 CopyOnWriteArrayList适用于写少读多的并发场景
ReadWriteLock即为读写锁,他要求写与写之间互斥,读与写之间互斥,读与读之间可以并发执行。在读多写少的情况下可以提高效率 .
ConcurrentHashMap采用分段锁技术,写操作加锁,读操作一般不加锁
volatile只保证多线程操作的可见性,不保证原子性 java并发编程的艺术P39面:volatile变量自身具有以下特性:1。可见性2.原子性:对任意单个volatile变量的读写具有原子性,但类似volatile++这种复合操作不具有原子性
volatite只保证线程在“加载数据阶段”加载的数据是最新的,并不能保证线程安全。

一个线程执行的过程有三个阶段:
加载(复制)主存数据到操作栈 --> 对操作栈数据进行修改 --> 将操作栈数据写回主存
volatite关键字,让编译器不去优化代码使用缓存等,以保证线程在“加载数据阶段”加载的数据都是最新的

比如:
某一时刻i=6是最新的值,volatile保证线程A,B都同时加载了这个最新的值,
然后A执行i(A)+1=7,然后将7写回主存,
B也执行i(B)+1=7,然后也将7写回内存,
这样,执行两次加法,i却只增加了1
7
A、Semaphore:类,控制某个资源可被同时访问的个数;
B、ReentrantLock:类,具有与使用synchronized方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大;
C、 Future:接口,表示异步计算的结果;
D、 CountDownLatch: 类,可以用来在一个线程中等待多个线程完成任务的类。
8.当我们想要截取用空格隔开的数字时例如4 5 6 7;我们可以使用hasNextInt()方法这个方法只读取数字当然了我们用nextInt 接受的时候不会读取到空格所以会截取出你想要的数字 4,5,6,7,这个样单独隔开你可以用int a = scanner.nextInt()接受。
今天我学习了动态规划算法,其实还不是很会应用,就知道不选和选两种方式会存在什么样的影响,要多 坐一坐动态规划的题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值