【面试现场】如何编程获得最多的年终红包奖?

小史是一个应届生,虽然学的是电子专业,但是自己业余时间看了很多互联网与编程方面的书,一心想进BAT互联网公司。

今天小史又去了一家互联网小巨头公司面试了。

【面试现场】

扫描二维码关注公众号,回复: 3768340 查看本文章

小史眉头一皱,发现事情并不简单。

题目:在数字矩阵中,从左上角到右下角,每次只能向右或向下,如何规划路径,能获得最大数字总和?

小史开始仔细分析问题,一时间竟想不到很好的方法。

给大家推荐一个程序员学习交流群:854818273。群里有分享的视频,还有思维导图

群公告有视频,都是干货的,你可以下载来看。主要分享分布式架构、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战学习架构师视频。

小史心中反复默念题目,进行思考。

小史仔细回忆起了吕老师教他的华容道搜索算法。

【请教大神】

给大家推荐一个程序员学习交流群:854818273。群里有分享的视频,还有思维导图

群公告有视频,都是干货的,你可以下载来看。主要分享分布式架构、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战学习架构师视频。

回到学校,小史把面试情况和吕老师说了一下。

吕老师:红色和蓝色两条路都能到达中间的100这个点,但是很明显,红色的路拿到的奖金更多。所以蓝色的路,后面不管再怎么走,都不可能拿到最大的奖金数了。

吕老师:假设蓝色路径再往后走出一条绿色路径是最大奖金,那么我把蓝色路径替换成红色路径,红色加绿色得到的奖金就比蓝色加绿色得到的多呀。

【记忆化搜索】

小史:哦,我明白了,这样我每搜到一个点,都可以和这个数比较,如果比它大,就更新这个数,继续搜,如果比它小,就不搜了,直接剪枝。

理解了算法之后,小史的代码写起来也是非常快,不一会儿就写好了:

给大家推荐一个程序员学习交流群:854818273。群里有分享的视频,还有思维导图

群公告有视频,都是干货的,你可以下载来看。主要分享分布式架构、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战学习架构师视频。

DeepFirstSearch.java

Main.java

运行结果

【记忆广搜】

给大家推荐一个程序员学习交流群:854818273。群里有分享的视频,还有思维导图

群公告有视频,都是干货的,你可以下载来看。主要分享分布式架构、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战学习架构师视频。

吕老师:记忆深搜确实可以剪枝,但是假如有人刻意安排数字,把较小的数都安排在你先搜的路径上,那么你的计算量还是不会减少太多。

小史:还有这么坏的人呢?不过你这样一说我到想起来,深搜确实缺少一种“全局观”,可能第一条路搜完了,再来看第二条路,发现更好,结果第一条路全白搜了。

理解了算法之后,小史的代码写起来也是非常快,不一会儿就写好了:

BreadthFirstSearch.java

Main.java

【动态规划】

给大家推荐一个程序员学习交流群:854818273。群里有分享的视频,还有思维导图

群公告有视频,都是干货的,你可以下载来看。主要分享分布式架构、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战学习架构师视频。

吕老师:小史,代码写得不错,咱们再来看看广搜的过程,其实就是在搜索的过程中从左上到右下计算出了best(i,j),所以为啥我们不能直接算出best(i,j)呢?

理解了算法之后,小史的代码写起来也是非常快,不一会儿就写好了:

Main.java

【动态规划解析】

吕老师:状态的定义要满足几个点,第一,问题的答案是某种状态,或者可由状态进行推导。第二,当前状态可以由之前的状态推导而来。

【状态压缩】

小史:哦,我知道了,这道题,如果按照斜线方向来计算,只需要保留一条斜线的状态,就能计算出下一条斜线。所以之前的状态就不需要保留了。

理解了算法之后,小史的代码写起来也是非常快,不一会儿就写好了:

DpCompressed.java

/**

* @author xiaoshi on 2018/10/20.

*/

public class DpCompressed {

    // 定义best(i) 和 M N

    private int[][] best = null;

    private int M = 0;

    private int N = 0;

    // 计算best(i)

    privatevoidcalcDp(int[][] matrix){

        // 初始化

        M = matrix.length;

        N = matrix[0].length;

        int minMN = Math.min(M, N);

        int maxMN = Math.max(M, N);

        // best只需要M和N的最小值长度就行

        best = new int[2][minMN];

        // 需要计算 M+N-1 条斜线

        for(int i = 0; i < M + N - 1; i++) {

            // 第 i 条斜线的起始x坐标

            int startX = 0;

            // 第 i 条斜线的起始y坐标

            int startY = i;

            // 第 i 条斜线的数字个数

            int number = i + 1;

            if(i >= N) {

                startX = i + 1 - N;

                startY = N - 1;

            }

            if(i >= minMN) {

                number = minMN;

            }

            if(i >= maxMN) {

                number = M + N - i - 1;

            }

            // 第 i 条斜线上的 number 个数

            for(int j = 0; j < number; j++) {

                // 起始点

                if(i == 0 && j == 0) {

                    best[1][j] = matrix[startX + j][startY - j];

                } else {

                    if (i < N) {

                        // 前半部分

                        if (j == 0) {

                            // 上边界

                            best[1][j] = best[0][j] + matrix[startX + j][startY - j];

                        } else if (j == number - 1) {

                            // 左边界

                            best[1][j] = best[0][j-1] + matrix[startX + j][startY - j];

                        } else {

                            // 状态转移

                            best[1][j] = Math.max(best[0][j], best[0][j-1]) + matrix[startX + j][startY - j];

                        }

                    } else {

                        // 后半部分

                        if(i < M && j == number - 1) {

                            // 左边界

                            best[1][j] = best[0][j] + matrix[startX + j][startY - j];

                        } else {

                            // 状态转移

                            best[1][j] = Math.max(best[0][j], best[0][j+1]) + matrix[startX + j][startY - j];

                        }

                    }

                }

            }

            // 将best[1]上的状态拷贝到best[0]

            for(int j = 0; j < number; j++) {

                best[0][j] = best[1][j];

            }

        }

    }

    // 获取最大值

    publicintgetMaxAward(int[][] matrix){

        calcDp(matrix);

        return best[0][0];

    }

}

Main.java

PS:这次这篇花费了两周时间。如果你看到了这里,并且有所收获的话,可以动动手指转发一下哦,非常感谢!

给大家推荐一个程序员学习交流群:854818273。群里有分享的视频,还有思维导图

群公告有视频,都是干货的,你可以下载来看。主要分享分布式架构、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战学习架构师视频。

猜你喜欢

转载自blog.csdn.net/hjycjy132477/article/details/83541137
今日推荐