黑马程序员技术交流社区

标题: 想要参加面试就要做三道题 [打印本页]

作者: psuugdufnm    时间: 2016-4-11 13:08
标题: 想要参加面试就要做三道题
昨天有个HR跟我说,有三道题,都做出来就给安排面试,但本宝宝表示不会,求大神解答。
第一题:给定一个数组,里面是一些数字,请只用一个for循环,找出其中第二大的数字。
所谓第二大的数字是:相当于这个数组逆序排序后,取下标为1的那个数字。
要求:只用1个for循环,配合if/else判断。不要对数组排序。
例如:对于数组 [2, 5, 1, 3, 2], 输出:3

第二题:2、现在有如下通信协议,请实现相关函数模块。
此协议是一个二进制协议,每个协议报文由如下数据流构成,数值都以Big-endian大端方式存储:
    { TotalSize[2], Crc32[4], Ver[1], Cmd[1], Data[len] }
方括号中是占用的字节数。具体解释:
    TotalSize: 2字节,表示整个报文的长度,这个值应该等于: 2 + 4 + 1 + 1 + len
    Crc32: 4字节,表示对 {Ver, Cmd, Data} 内容的 crc32 的校验值
    Ver: 1字节,协议版本,目前约定为 0x05
    Cmd: 1字节,用户指定的操作命令,0x00 ~ 0xff
    Data: len个字节,具体的数据内容
要求:实现一个函数 pack(cmd, data, len)
输入:cmd: 用户指定的操作命令;  data: 用户指定的数据;  len: 数据长度
输出:打包好的协议报文

第三题:有两个函数,funcA 会输出 "A" , funcB 会输出 "B"
请启动两个线程,用线程同步的机制,实现如下效果:
严格按照顺序轮流输出 A B A B A B ...

作者: 木子小四    时间: 2016-4-11 14:10
我滴乖  ,这是啥面试
作者: psuugdufnm    时间: 2016-4-11 15:48
木子小四 发表于 2016-4-11 14:10
我滴乖  ,这是啥面试

android 的面试{:2_30:}
作者: z332406259    时间: 2016-4-11 17:11
本帖最后由 z332406259 于 2016-4-13 00:39 编辑

package com.lzm;

/**
*
* 第一题:给定一个数组,里面是一些数字,请只用一个for循环,找出其中第二大的数字。
* 所谓第二大的数字是:相当于这个数组逆序排序后,取下标为1的那个数字。
* 要求:只用1个for循环,配合if/else判断。不要对数组排序。
*  例如:对于数组 [2, 5, 1, 3, 2], 输出:3
*
*/
public class NO_2 {
        public static void main(String[] args) {
                int[] arr = { 6,6,5,4,3 };         // 定义数组
                int first = arr[0];                         // 将数组第一个数字标记为NO1大的数字
                int second = arr[1];                 // 将数组第二个数字标记为NO2大的数字
                if (first < second) {                 // 如果NO1大的数字>NO2的数字,就交换它们的位置
                        int temp = first;
                        first = second;
                        second = temp;
                }
                for (int i = 2; i < arr.length; i++) {                 // 对数组遍历从第三个开始
                        if (first == second) {                         // 如果NO1数字和NO2数字相等,就判断数组遍历的数字和NO1的大小.
                                if (first < arr[ i ]) {                        // 遍历的数字若比NO1大,则把遍历的数字赋值给NO1,否则赋值给NO2.
                                        first = arr[ i ];
                                } else {
                                        second = arr[ i ];
                                }
                        } else {                                                         // 如果NO1和NO2不相等,则比较遍历的数字和NO1的大小.
                                if (first < arr[ i ]) {                 // 若该数字比NO1大,就将NO1赋值给NO2,该数字赋值给NO1.
                                        second = first;
                                        first = arr[ i ];
                                } else if (first > arr[ i ]) {         // 若该数字比NO1小,就比较该数字和NO2的大小.
                                        if (second < arr[ i ]) {         // 若该数字比NO2大,就将该数字赋值给NO2.
                                                second = arr[ i ];
                                        }
                                }
                        }
                }
                System.out.println(second);                 // 输出NO2
        }
}


作者: psuugdufnm    时间: 2016-4-11 17:17
z332406259 发表于 2016-4-11 17:11
package com.heima.lzm33;

/**

给力!!谢谢。
作者: z332406259    时间: 2016-4-11 18:07
本帖最后由 z332406259 于 2016-4-11 18:29 编辑

package com.heima.lzm33;

public class Test_3 {

        /**
         * 第三题:有两个函数,funcA 会输出 "A" , funcB 会输出 "B" 请启动两个线程,用线程同步的机制,实现如下效果:
         * 严格按照顺序轮流输出 A B A B A B ...
         */
        public static void main(String[] args) {
                final Hello h = new Hello();                                        //创建Hello对象

                new Thread() {                                                                                //匿名线程1
                        public void run() {
                                while (true) {                                                                //不停调用funcA()方法输出A
                                        try {                                                                                        //异常判断
                                                h.funcA();
                                        } catch (InterruptedException e1) {
                                                e1.printStackTrace();
                                        }
                                }
                        }
                }.start();                                                                                                        //线程开启

                new Thread() {                                               //匿名线程2
                        public void run() {
                                while (true) {                                                                //不停调用funcB()方法输出B
                                        try {                                                                                        //异常判断
                                                h.funcB();
                                        } catch (InterruptedException e1) {
                                                e1.printStackTrace();
                                        }
                                }
                        }
                }.start();                                                                                                        //线程开启
        }
}

class Hello {
        private int flag = 1;                                                                        //标记 默认为1

        public void funcA() throws InterruptedException {
                synchronized (this) {   //锁对象this                                                               
                        if (flag != 1) {                                                                        //当标记不为1时,该线程1等待
                                this.wait();
                        }
                        System.out.println("A");
                        flag = 2;                                                                                        //标记赋值为2
                        this.notify();                                                                                //唤醒线程2(其他线程)
                }
        }

        public void funcB() throws InterruptedException {
                synchronized (this) {   //锁对象this  
                        if (flag != 2) {                                                                        //当标记不为2时,该线程2等待
                                this.wait();
                        }
                        System.out.println("B");
                        flag = 1;                                                                                        //标记赋值为2
                        this.notify();                                                                                //唤醒线程1(其他线程)
                }
        }
}

作者: z332406259    时间: 2016-4-11 18:09
等待进城唤醒机制.由于控制台不能横着输出A B A B A B.....我就换成
A
B
A
B
A
B
.
.
.


作者: z332406259    时间: 2016-4-11 18:16
本帖最后由 z332406259 于 2016-4-11 18:54 编辑

根据楼上改了一下.JDK1.5的新特性,互斥锁,个人感觉没什么区别.就是锁对象的问题.
package com.heima.lzm33;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Test_3 {

        /**
         * 第三题:有两个函数,funcA 会输出 "A" , funcB 会输出 "B" 请启动两个线程,用线程同步的机制,实现如下效果:
         * 严格按照顺序轮流输出 A B A B A B ...
         */
        public static void main(String[] args) {
                final Hello h = new Hello(); // 创建Hello对象

                new Thread() { // 匿名线程1
                        public void run() {
                                while (true) { // 不停调用funcA()方法输出A
                                        try { // 异常判断
                                                h.funcA();
                                        } catch (InterruptedException e1) {
                                                e1.printStackTrace();
                                        }
                                }
                        }
                }.start(); // 线程开启

                new Thread() { // 匿名线程2
                        public void run() {
                                while (true) { // 不停调用funcB()方法输出B
                                        try { // 异常判断
                                                h.funcB();
                                        } catch (InterruptedException e1) {
                                                e1.printStackTrace();
                                        }
                                }
                        }
                }.start(); // 线程开启
        }
}

class Hello {
        private int flag = 1;                                                                                                // 标记 默认为1
        private ReentrantLock r = new ReentrantLock();        //互斥锁
        private Condition c1 = r.newCondition();                               
        private Condition c2 = r.newCondition();

        public void funcA() throws InterruptedException {
                r.lock();                        //获取锁
                if (flag != 1) { // 当标记不为1时,该线程1等待
                        c1.await();                        //c1等待
                }
                System.out.println("A");
                flag = 2; // 标记赋值为2
                c2.signal();                //唤醒c2线程
                r.unlock();                        //释放锁
        }

        public void funcB() throws InterruptedException {
                r.lock();                        //获取锁
                if (flag != 2) { // 当标记不为1时,该线程1等待
                        c2.await();                //c2等待
                }
                System.out.println("B");
                flag = 1; // 标记赋值为2
                c1.signal();                //唤醒c1线程
                r.unlock();                        //释放锁
        }
}


作者: 追梦de蜗牛2016    时间: 2016-4-11 18:21
第三个题直接用互斥锁,
作者: 木丶子李    时间: 2016-4-11 19:16
第一题不是只用一个for/if吗?
作者: yy0328    时间: 2016-4-11 20:40
不明觉厉   楼主加油
作者: Yoyoqiu    时间: 2016-4-11 21:05
只会第一题
class Test_002 {
        public static void main(String[] args) {
                int [] arr = {2, 2, 3, 43, 32, 8, 23, 35};
                int first = arr[0];
                int second = arr[1];
                if (first<second) {
                        int temp = second;
                        second = first;
                        first= temp;      //获取max和max2
                }
                for (int i = 2;i<arr.length ;i++ ) {  //数组第三个开始遍历比较
                        if (first<=arr[i]) {        //比max还大的  
                                second = first;   // 先把max记录给 max2
                                first = arr[i];      // 再把遍历出的最大赋给max
                    }else if (arr[i]>second) {  //如果遍历出来都比max小
                                 second = arr[i];  // 那就只需要和max2 比较即可
                         }       
                }
                System.out.println(second);       
        }
}
作者: 李亚东_JAVAEE    时间: 2016-4-11 21:11
感觉好难啊
作者: z332406259    时间: 2016-4-11 21:31
本帖最后由 z332406259 于 2016-4-12 00:24 编辑

package com.heima.lzm33;

import java.util.zip.CRC32;

public class Test_4 {

        /**
         * 第二题:2、现在有如下通信协议,请实现相关函数模块。
         * 此协议是一个二进制协议,每个协议报文由如下数据流构成,数值都以Big-endian大端方式存储:
         * { TotalSize[2],Crc32[4], Ver[1], Cmd[1], Data[len] } 方括号中是占用的字节数。具体解释:
         * TotalSize:2字节,表示整个报文的长度,这个值应该等于: 2 + 4 + 1 + 1 + len
         * Crc32: 4字节,表示对 {Ver, Cmd,Data} 内容的 crc32 的校验值
         * Ver: 1字节,协议版本,目前约定为 0x05
         * Cmd: 1字节,用户指定的操作命令,0x00 ~0xff
         * Data: len个字节,具体的数据内容
         * 要求:实现一个函数 pack(cmd, data, len) 输入:cmd:
         * 用户指定的操作命令; data: 用户指定的数据; len: 数据长度 输出:打包好的协议报文
         */
        public static void main(String[] args) {
                pack(0x0A, "35566",5 );
                //报文打包方法(这边也可以不自己输入数值,设置键盘录入)
        }

        public static void pack(int cmd, String data, int len) {//方法:参数:int String int(用键盘录入可以全定义为String,然后转换)
                CRC32 crc32 = new CRC32();                                    //建立CRC32对象
                short TotalSize = (short) (2 + 4 + 1 + 1 + len);//定义变量TotalSize
                byte Ver = 0x05;                                                   //定义Ver
                byte Cmd = (byte) cmd;                                          //定义Cmd
                byte[] Data = new byte[len];                                 //建立字节数组来接收数据,因为数据是一个一个接收的.
                Data = data.getBytes();                                        //将字符串转换为字节数组
                byte[] b = new byte[len + 2];                               //新建一个比数据长度+2的字节数组
                for (int i = 0; i < Data.length - 1; i++) {              //遍历该数组将数据数组放入新数组中
                        b = Data;
                }
                b[len - 1] = Ver;                                             //将Ver和Cmd也放入新数组中
                b[len - 2] = Cmd;

                crc32.update(b);                                           //调用CRC32的方法传入字节数组更新校检值
                int Crc32 = (int) crc32.getValue();                 //取出校检值赋给Crc32
                System.out.print("{" + Integer.toHexString(TotalSize) + ","+ Integer.toHexString(Crc32) + ","
                + Integer.toHexString(Ver)+ "," + Integer.toHexString(Cmd) + ",");
               //输出{ TotalSize[2],Crc32[4], Ver[1], Cmd[1], Data[len] } 的十六进制表示
               //因为Big-endian大端方式是低地址存储最高有效字节,和正常习惯一样,直接打印十六进制.
                for (byte c : Data) {
                        System.out.print(Integer.toHexString(c));
                }
                System.out.println("}");
        }
}


作者: z332406259    时间: 2016-4-11 21:43
本帖最后由 z332406259 于 2016-4-12 00:12 编辑
Yoyoqiu 发表于 2016-4-11 21:05
只会第一题
class Test_002 {
        public static void main(String[] args) {

赞一个.你的程序还是有bug的,当第一个数字和第二个数字都是一样的并且接下来的数字全部小于这2个数字,最后会输出最大的数字的.
作者: z332406259    时间: 2016-4-11 21:44
本帖最后由 z332406259 于 2016-4-12 00:11 编辑

12楼的程序还是存在问题,我看看程序能不能再优化一下.
作者: 莫慌莫慌    时间: 2016-4-11 21:45
多看看多学,没准自己以后会用到.谢谢分享
作者: fanlelong    时间: 2016-4-11 21:52
感觉有点难
作者: CX898855195    时间: 2016-4-11 22:51
才学到数组,第一题还是有点意思的,学到了
作者: zixiyang    时间: 2016-4-11 23:32
只会写第一题 看看这样写可以不        public static void main(String[] args) {
                //定义数组
                int[] arr = {40,12,23,35,45,60,45,15,76};
                //定义变量max记住数组中最大数字为arr[0];
                int max = arr[0];
                //定义变量max2记住数组中第二大的数字为arr[1];
                int max2 = arr[1];
               
                //如果max2 大于max,就进行交换
                if(max<max2) {
                        int temp = max;
                        max = max2;
                        max2 = temp;
                }
               
                //从第三个元素开始遍历
                for (int i = 2; i < arr.length; i++) {
               
                        //用最大的数字max与遍历出的其他元素arr[i]一一比较,如果max <arr[i],
                        //就把arr[i]赋值给max,得出最大值;然后把原来max的值赋值给max2;
                        if (max < arr[i]) {     
                                max2= max;
                                max = arr[i];
                        //再用赋值后的max2与数组中除了最大元素进行比较,如果max小于其他元素arr[i],就把arr[i]赋值给max2;       
                        }else if(max2 < arr[i]){
                                max2 = arr[i];
                        }
                }
                //输出第二大的值
                System.out.println(max2);
        }

}
作者: zixiyang    时间: 2016-4-11 23:37
额 没看12楼 没想到差不多 啊 感觉不用等于也可以的吧
作者: 落星追恒    时间: 2016-4-12 09:44
z332406259 发表于 2016-4-11 21:43
赞一个.你的程序还是有bug的,当第一个数字和第二个数字都是一样的并且接下来的数字全部小于这2个数字,最后 ...

你这么强也是来考黑马的?感觉压力很大
作者: psuugdufnm    时间: 2016-4-12 12:34
z332406259 发表于 2016-4-11 18:07
package com.heima.lzm33;

public class Test_3 {

{:2_45:}  大神!!太厉害了
作者: psuugdufnm    时间: 2016-4-12 12:35
木丶子李 发表于 2016-4-11 19:16
第一题不是只用一个for/if吗?

只用一个for, 配合if/else.  貌似可以用多个if/else 呢
作者: psuugdufnm    时间: 2016-4-12 12:36
yy0328 发表于 2016-4-11 20:40
不明觉厉   楼主加油

也是不会才来请教大家的。要学习的还是太多太多
作者: 梧桐望穹    时间: 2016-4-12 12:38
好厉害的样子,学习了
作者: psuugdufnm    时间: 2016-4-12 12:38
Yoyoqiu 发表于 2016-4-11 21:05
只会第一题
class Test_002 {
        public static void main(String[] args) {

谢谢 悠悠球。 。{:2_45:}
作者: psuugdufnm    时间: 2016-4-12 12:41
z332406259 发表于 2016-4-11 21:31
package com.heima.lzm33;

import java.util.zip.CRC32;

这个 ,,你告诉我答案  ,我也是看不懂了,慢慢学习吧,谢谢您的回答。 等我学到这里,我再回来看这个。
作者: psuugdufnm    时间: 2016-4-12 12:44
各位大神,真是太牛了!莫名的感到压力山大。。
作者: htyjshty    时间: 2016-4-12 14:23
先马再看
作者: 哦哈哟    时间: 2016-4-12 15:57
z332406259 发表于 2016-4-11 17:11
package com.heima.lzm33;

/**

//
第一题:给定一个数组,里面是一些数字,请只用一个for循环,找出其中第二大的数字。
所谓第二大的数字是:相当于这个数组逆序排序后,取下标为1的那个数字。
要求:只用1个for循环,配合if/else判断。不要对数组排序。
例如:对于数组 [2, 5, 1, 3, 2], 输出:3
//
大哥,看清楚题目。。。。你犯了三个大错误。1.题目没审清楚,2.需求也没审清楚,3.一楼的代码有错误(13行开始arr少了下标)。
第二大的数字,已经定义了是逆序排序后的下标为1的数字。
还有要求,//不要对数组排序。
其实题目很简单就是求,数组下标为arr.length-2的数字。
代码如下
/*
第一题:给定一个数组,里面是一些数字,请只用一个for循环,找出其中第二大的数字。
所谓第二大的数字是:相当于这个数组逆序排序后,取下标为1的那个数字。
要求:只用1个for循环,配合if/else判断。不要对数组排序。
例如:对于数组 [2, 5, 1, 3, 2], 输出:3 。

需求:
1.定义求数组“第二大“的函数。
2.只用一个for循环,配合if/else判断。
3.不能对数组排序。
思路:  其实就是求arr.length-2的数字
1.定义数组arr
2.逆向遍历数组
3.判断下标是否等于arr.length-2.并输出结果。

*/
class Test6{
        public static void main(String[] args){
                int[] arr1 ={9,5,1,6,7,8,1};   //测试数组1
                int[] arr2 ={2,5,1,3,2};                //测试数组2
                Dierda(arr1);                        //结果:输出8
                Dierda(arr2);                        //结果:输出3
        }
        public static void Dierda(int[] arr){
                 for(int i=arr.length-1;i >= 0 ;i--){        //逆向遍历数组
                         if(i == arr.length-2){                                //判断是否等于arr.length-2
                                 System.out.println(arr);        //输出第二大数字
                                 break;                                                        //结束循环
                         }
                         else{
                                 continue;
                         }
                 }
        }
}
作者: Yoyoqiu    时间: 2016-4-12 17:01
psuugdufnm 发表于 2016-4-12 12:38
谢谢 悠悠球。 。

努力加油 未来是我们的
作者: Yoyoqiu    时间: 2016-4-12 17:02
psuugdufnm 发表于 2016-4-12 12:38
谢谢 悠悠球。 。

努力加油 未来是我们的
作者: Yoyoqiu    时间: 2016-4-12 17:04
psuugdufnm 发表于 2016-4-12 12:38
谢谢 悠悠球。 。

努力加油 未来是我们的
作者: z332406259    时间: 2016-4-12 17:38
本帖最后由 z332406259 于 2016-4-12 17:39 编辑
哦哈哟 发表于 2016-4-12 15:57
//
第一题:给定一个数组,里面是一些数字,请只用一个for循环,找出其中第二大的数字。
所谓第二大的数 ...

谢谢这位学友提出质疑.
首先说一下.arr角标的问题是这个回复的编辑器的问题,刚刚查看已改.请看一下你自己的代码.arr的角标也没有了.
第二,题目要求的是数组逆序排序后下标为1,
不是数组逆序,请自己百度排序的含义.见名知意,该题要求的是第二大的数,按照正常的理解就是这堆数字中第二大的数字,当然它所谓第二大的数字的定义存在瑕疵,当超过两个数字是一样的最大数字时候,显然逆序排序后下标为1的数字是最大的数字,因此忽略这个bug.
第三,需求没审清楚?是指的不要对数组排序这句话么?我并没有对数组进行排序.

这道题如果只是求arr.length-2的数字的话.完全不需要定义这个条件:    不要对数组排序
所以还是需要好好审一下题意.

作者: Q灬先生    时间: 2016-4-12 22:52
谢谢分享,以后能用到!
作者: 哦哈哟    时间: 2016-4-12 23:47
z332406259 发表于 2016-4-12 17:38
谢谢这位学友提出质疑.
首先说一下.arr角标的问题是这个回复的编辑器的问题,刚刚查看已改.请看一下你自己 ...

看来是我一直误解题意......大哥你是对的!
作者: NB的笨小孩    时间: 2016-4-13 07:02
不错,跟着学习




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2