爱奇艺8.22Java后端笔经

1.选择题

数据结构、java、python、Spring、微服务等相关

2.SQL

题目如下:

     * 现有如下MySQL数据表,请写出合适的SQL语句,查询出女生数量最多的前三个专业名称和对应的女生人数?(gender字段说明:1为男,2为女)。要求查询结果的表头如subject_name, girl_count。
     *
     * 大学学生基本信息表Student_Info
     *
     * id    name    gender
     * 1    Kate    2
     * 2    Mary    2
     * 3    Tom    1
     * 4    Jim    1
     * 5    Lily    2
     * 6    Rose    2
     * 7    Lucy    2
     * 8    Meimei    2
     * 专业信息登记表Subject_Register
     *
     * student_id     subject_id
     * 1    1
     * 2    2
     * 3    3
     * 4    3
     * 5    2
     * 6    4
     * 7    4
     * 8    4
     * 专业基本信息表Subject_Info
     *
     * id    name
     * 1    Math
     * 2    English
     * 3    Computer
     * 4    News

我自己写的...

select Subject_Info.name as subject_name,count(gender) as girl_count
from Student_Info,Subject_Register,Subject_Info
where
Subject_Info.id=Subject_Register.subject_id
and
Subject_Register.student_id=Student_Info.id
and
gender=2
group by Subject_Info.name
order by girl_count
limit 0,3

写的时候忘了排序,卧槽!0ac(下面这个应该也许大概是对的吧)

select Subject_Info.name as subject_name,count(gender) as girl_count
from Student_Info,Subject_Register,Subject_Info
where
Subject_Info.id=Subject_Register.subject_id
and
Subject_Register.student_id=Student_Info.id
and
gender=2
group by Subject_Info.name
order by girl_count desc
limit 0,3

3. 算法题1

在监控与BI报表系统中,我们经常会采集数据指标进行分析,这里的数据往往都是时序数据,对于时序数据,我们可以用一个数组来表示,例如数组下标表示时间顺序,数组的值表示采集的指标数据大小。现在作为分析师的你,得到如下一个任务:在给定一个整数形式的时序数据,求出这个时序里最大的振幅(“落差”)(振幅 = 时序里相邻的“波峰”与“波谷”相差绝对值)

输入描述
一个数组,下标代表x轴的时间顺序,数组里的每个数值代表y轴的具体值

输出描述
整个曲线的相邻波峰与波谷的最大振幅落差

只AC了75%,剩下的不知道问题在哪...

public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String line = scanner.nextLine();
        String[] stringList = line.split(",");
        int[] arr = new int[stringList.length];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = Integer.parseInt(stringList[i]);
        }
        //这里arr就是输入源...
        process(arr);
    }

    /**
     * 输入...
     * 2,2,3,8,8,6,5,10,7,6
     * 1,2,3,8,5,3,6
     * 1,2,3,4,5,6
     *
     * @param arr
     */
    public static void process(int[] arr) {
        int left = 0, right = 1;
        int max = Integer.MIN_VALUE;
        for (; left < arr.length && right < arr.length; ) {
            //符号,是正数还是负数呢?
            int sign = (arr[right] - arr[right - 1]) >= 0 ? 1 : -1;
            for (; right < arr.length; ) {
                int sign0 = (arr[right] - arr[right - 1]) >= 0 ? 1 : -1;
                if (sign0 == sign) {
                    //更新...
                    max = Math.max(Math.abs(arr[right] - arr[left]), max);
                    right++;
                } else {
                    left = right - 1;
                    break;
                }
            }
        }
        System.out.println(max);
    }

4. 算法题2-n皇后问题

AC100%,DFS搜索就行...

    /**
     * n皇后问题...
     */
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String str = scanner.next();
        int n = Integer.parseInt(str.substring(2));
        List<List<String>> list = new ArrayList<>();
        List<char[]> charsList = new ArrayList<>();
        //初始化Chars列表为.
        for (int i = 0; i < n; i++) {
            char[] rowVal = new char[n];
            Arrays.fill(rowVal, '.');
            charsList.add(rowVal);
        }
        process(0, charsList, list, n);
        System.out.println(list);
    }

    public static void process(int row, List<char[]> charList, List<List<String>> res, int n) {
        if (row == n) {
            List<String> strings = new ArrayList<>();
            for (char[] chars : charList) {
                String str = new String(chars);
                strings.add(str);
            }
            res.add(strings);
            return;
        }

        //对应行的...遍历每一列...
        for (int col = 0; col < n; col++) {
            //如果row,col位置不合法,那么continue...
            if (!isValid(charList, row, col, n)) {
                continue;
            }
            //做选择...
            (charList.get(row))[col] = 'Q';
            process(row + 1, charList, res, n);
            //取消选择...
            (charList.get(row))[col] = '.';
        }

    }

    public static boolean isValid(List<char[]> charsList, int row, int col, int n) {
        for (int i = col; i >= 0; i--) {
            //如果当前这一行已经出现了Q,那么return false
            if ((charsList.get(row))[i] == 'Q') {
                return false;
            }
        }
        for (int i = row; i >= 0; i--) {
            //如果当前列出现了Q,return false
            if ((charsList.get(i))[col] == 'Q') {
                return false;
            }
        }
        //检验左上角
        int i = row, j = col;
        for (; i >= 0 && j >= 0; i--, j--) {
            if ((charsList.get(i))[j] == 'Q') {
                return false;
            }
        }

        //检验右上角...
        i = row;
        j = col;
        for (; i >= 0 && j < n; i--, j++) {
            if ((charsList.get(i))[j] == 'Q') {
                return false;
            }
        }
        return true;
    }

5.多线程

/**
 * 假设有这么一个类:
 * <p>
 * class ZeroAndEvenOdd {
 * public ZeroAndEvenOdd(int n) { ... }      // 构造函数
 * public void printZero(printNumber) { ... }  // 仅打印出 0
 * public void printEven(printNumber) { ... }  // 仅打印出 偶数
 * public void printOdd(printNumber) { ... }   // 仅打印出 奇数
 * }
 * 相同的一个 ZeroAndEvenOdd类实例将会传递给三个不同的线程:
 * <p>
 * 线程 A 将调用 printZero(),它只输出 0 。
 * <p>
 * 线程 B 将调用 printEven(),它只输出偶数。
 * <p>
 * 线程 C 将调用 printOdd(),它只输出奇数。
 * <p>
 * 每个线程都有一个 printNumber 方法来输出一个整数。请修改给出的代码以输出整数序列 010203040506... ,其中序列的长度必须为 2n。
 * <p>
 * 输入描述
 * 整数n
 * <p>
 * 输出描述
 * 输出整数序列 010203040506... ,输出整数序列 010203040506... ,其中序列的长度必须为 2n
 * <p>
 * <p>
 * 样例输入
 * 5
 * 样例输出
 * 0102030405
 *
 * @author wanna
 * @version v1.0
 */

用一个volatile变量current标识当前的到达的数字,用一个volatile变量who表示去唤醒别的线程去打印奇数/偶数,who=1打印0,who=2打印偶数,who=3打印奇数,who=1时打印0并且根据current是奇数还是偶数去唤醒who=2或者who=3的线程。(其实不是唤醒,for循环等着current到达n,有点耗费CPU,应该也可以使用ReentrantLock.Condition去解决)

AC100%...

public class Main {
    public static void main(String[] args) {
        final Scanner reader = new Scanner(System.in);
        int n = reader.nextInt();
        ZeroEvenOdd zeroEvenOdd = new ZeroEvenOdd(n);
        new Thread(() -> {
            try {
                zeroEvenOdd.printZero(System.out::print);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(() -> {
            try {
                zeroEvenOdd.printEven(System.out::print);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(() -> {
            try {
                zeroEvenOdd.printOdd(System.out::print);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

class ZeroEvenOdd {
    private int n;

    private volatile int current = 1;

    private volatile int who = 1;

    public ZeroEvenOdd(int n) {
        this.n = n;
    }

    // printNumber.accept(x) outputs "x", where x is an integer.
    //打印0,accept(x)输出x...x是个int类型...
    public void printZero(IntConsumer printNumber) throws InterruptedException {
        for (; current <= n; ) {
            if (who == 1) {
                printNumber.accept(0);
                //如果是奇数,那么唤醒...condition3
                if ((current & 1) == 0) {
                    who = 3;
                } else {
                    who = 2;
                }
            }
        }
    }

    //打印偶数
    public void printEven(IntConsumer printNumber) throws InterruptedException {
        for (; current <= n; ) {
            if (who == 2) {
                printNumber.accept(current++);
                who = 1;
            }
        }
    }

    //打印奇数
    public void printOdd(IntConsumer printNumber) throws InterruptedException {

        for (; current <= n; ) {
            if (who == 3) {
                printNumber.accept(current++);
                who = 1;
            }
        }
    }
}

下面补充使用Condition去解决

public class Main {
    public static void main(String[] args) {
        final Scanner reader = new Scanner(System.in);
        int n = reader.nextInt();
        ZeroEvenOdd zeroEvenOdd = new ZeroEvenOdd(n);
        Thread t1 = new Thread(() -> {
            try {
                zeroEvenOdd.printZero(System.out::print);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        new Thread(() -> {
            try {
                zeroEvenOdd.printEven(System.out::print);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(() -> {
            try {
                zeroEvenOdd.printOdd(System.out::print);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        //需要等待t2和t3已经被挂起了才启动t1...
        try {
            TimeUnit.MILLISECONDS.sleep(10);
            t1.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class ZeroEvenOdd {
    private final int n;

    private volatile int current = 1;

    ReentrantLock lock = new ReentrantLock();
    Condition condition1 = lock.newCondition(); //控制打印0的线程
    Condition condition2 = lock.newCondition();  //控制打印2的线程
    Condition condition3 = lock.newCondition();  //控制打印1的线程

    public ZeroEvenOdd(int n) {
        this.n = n;
    }

    // printNumber.accept(x) outputs "x", where x is an integer.
    //打印0,accept(x)输出x...x是个int类型...
    public void printZero(IntConsumer printNumber) throws InterruptedException {
        lock.lock();
        try {
            //current即使到达了n,也得唤醒,因为即将打印的就是n,必须得唤醒啊...
            for (; current <= n; ) {
                printNumber.accept(0);
                //如果是偶数,唤醒condition2,如果是奇数,唤醒condition3
                ((current & 1) == 0 ? condition2 : condition3).signal();
                condition1.await();
            }
        } finally {
            lock.unlock();
        }
    }

    //打印偶数
    public void printEven(IntConsumer printNumber) throws InterruptedException {
        lock.lock();
        try {
            //current到达n就得break掉,已经结束了...
            for (; current < n; ) {
                //等着...
                condition2.await();
                //如果当前是偶数,打印并且唤醒condition1
                printNumber.accept(current++);
                condition1.signal();
            }
        } finally {
            lock.unlock();
        }
    }

    //打印奇数
    public void printOdd(IntConsumer printNumber) throws InterruptedException {
        lock.lock();
        try {
            //current到达n就得break掉,已经结束了...
            for (; current < n; ) {
                //等着...
                condition3.await();
                //如果当前是奇数,那么打印并唤醒condition1
                printNumber.accept(current++);
                condition1.signal();
            }
        } finally {
            lock.unlock();
        }
    }
}

需要注意的是,需要保证线程t1要等线程t2和t3都启动了才去唤醒,不然t2和t3出现后先唤醒后阻塞可唤醒不了...

总结:我是fw,得多刷题呀。

#爱奇艺笔试##笔经##秋招##爱奇艺#
全部评论
这个不叫面经吧,这是笔经
点赞
送花
回复
分享
发布于 2021-08-22 18:06

相关推荐

3 13 评论
分享
牛客网
牛客企业服务