百度面试题

来源:互联网 发布:皂基洗面奶知乎 编辑:程序博客网 时间:2024/06/08 18:49

1)已知二叉树的先序遍历和中序遍历字符串,编程实现输出后序遍历字符串

eg:二叉树如下所示:

                 

                   a

              ↙   ↘

            b         c

         ↙↘        ↘

       d      e         g

前序:abdecg

中序:dbeacg

由前序的第一个a,可以把树分为两个部分,左子树和右子树。

在中序序列中找到a,左边部分则是左子树的中序,右边则是右子树的中序,

同样前序a的后面紧跟着左子树的前序和右子树的前序。

则问题可分解为两个结构相同的小问题。

1,先求左子树的后序;

2,求右子树的后序;

3,再将左子树和右子树的后序串起来,最后加上本身节点即可。

代码:

package com.xiejun;public class Xulie {public static String postOrder(String preOrder,String centerOrder){if(preOrder.length()!=centerOrder.length()||preOrder.length()==1){return preOrder;}char root = preOrder.charAt(0);int index = centerOrder.indexOf(root);if(index==-1){throw new RuntimeException();}if(index==0){ //只有右子树String newPreOrder2 = preOrder.substring(1);String newCenterOrder2 = centerOrder.substring(1);return postOrder(newPreOrder2, newCenterOrder2)+root;}if(index==preOrder.length()-1){ //只有左子树String newPreOrder2 = preOrder.substring(1);String newCenterOrder2 = centerOrder.substring(0,preOrder.length()-1);return postOrder(newPreOrder2, newCenterOrder2)+root;}String newPreOrder1 = preOrder.substring(1, index+1);String newCenterOrder1 = centerOrder.substring(0, index);String newPreOrder2 = preOrder.substring(index+1, preOrder.length());String newCenterOrder2 = centerOrder.substring(index+1, preOrder.length());return postOrder(newPreOrder1, newCenterOrder1)+postOrder(newPreOrder2, newCenterOrder2)+root;}public static void main(String[] args) {String postString = postOrder("abdecg","dbeacg");System.out.println(postString);}}

2)如何终止一个线程

如何停止java的线程一直是一个困恼我们开发多线程程序的一个问题。这个问题最终在Java5的java.util.concurrent中得到了回答:使用interrupt(),让线程在run方法中停止。

在Sun公司的一篇文章《Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? 》中详细讲解了舍弃这些方法的原因。那么,我们究竟应该如何停止线程呢?

1.当线程处于运行状态,可以设置volatile标志量来循环检测,让线程退出

2.处于可中断等待线程的停止

当线程处于下面的状况时,属于非运行状态:

  • 当sleep方法被调用。

  • 当wait方法被调用

当线程处于上述的状态时,使用前面介绍的方法就不可用了。这个时候,我们可以使用interrupt()来打破阻塞的情况

3. 处于IO阻塞状态线程的停止

Java中的输入输出流并没有类似于Interrupt的机制,但是JavaInterruptableChanel接口提供了这样的机制,任何实现了InterruptableChanel接口的类的IO阻塞都是可中断的,中断时抛出ClosedByInterruptedException,也是由Thread对象调用Interrupt方法完成中断调用。IO中断后将关闭通道。

        以文件IO为例,构造一个可中断的文件输入流的代码如下:

new InputStreamReader(             Channels.newInputStream(                     (new FileInputStream(FileDescriptor.in)).getChannel()))); 

  实现InterruptableChanel接口的类包括FileChannel,ServerSocketChannel, SocketChannel, Pipe.SinkChannel andPipe.SourceChannel,也就是说,原则上可以实现文件、Socket、管道的可中断IO阻塞操作。

        虽然解除IO阻塞的方法还可以直接调用IO对象的Close方法,这也会抛出IO异常。但是InterruptableChanel机制能够使处于IO阻塞的线程能够有一个和处于中断等待的线程一致的线程停止方案。

4.处于大数据IO读写中的线程停止

处于大数据IO读写中的线程实际上处于运行状态,而不是等待或阻塞状态,因此上面的interrupt机制不适用。线程处于IO读写中可以看成是线程运行中的一种特例。停止这样的线程的办法是强行closeio输入输出流对象,使其抛出异常,进而使线程停止。

        最好的建议是将大数据的IO读写操作放在循环中进行,这样可以在每次循环中都有线程停止的时机,这也就将问题转化为如何停止正在运行中的线程的问题了。

5. 在线程运行前停止线程

有时,线程中的run方法需要足够健壮以支持在线程实际运行前终止线程的情况。即在Thread创建后,到Threadstart方法调用前这段时间,调用自定义的stop方法也要奏效。从上述的停止处于等待状态线程的代码示例中,stop方法并不能终止运行前的线程,因为在Threadstart方法被调用前,调用interrupt方法并不会将Thread对象的中断状态置位,这样当run方法执行时,currentThreadisInterrupted方法返回false,线程将继续执行下去。

         为了解决这个问题,不得不自己再额外创建一个volatile标志量,并将其加入run方法的最开头:





0 0
原创粉丝点击