Nicksxs's Blog

What hurts more, the pain of hard work or the pain of regret?

0%

题目介绍

You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest version of your product fails the quality check. Since each version is developed based on the previous version, all the versions after a bad version are also bad.

Suppose you have n versions [1, 2, ..., n] and you want to find out the first bad one, which causes all the following ones to be bad.

You are given an API bool isBadVersion(version) which returns whether version is bad. Implement a function to find the first bad version. You should minimize the number of calls to the API.

示例

Example 1:

Input: n = 5, bad = 4
Output: 4
Explanation:
call isBadVersion(3) -> false
call isBadVersion(5) -> true
call isBadVersion(4) -> true
Then 4 is the first bad version.

Example 2:

Input: n = 1, bad = 1
Output: 1

简析

简单来说就是一个二分查找,但是这个问题其实处理起来还是需要搞清楚一些边界问题

代码

public int firstBadVersion(int n) {
    // 类似于双指针法
    int left = 1, right = n, mid;
    while (left < right) {
        // 取中点
        mid = left + (right - left) / 2;
        // 如果不是错误版本,就往右找
        if (!isBadVersion(mid)) {
            left = mid + 1;
        } else {
        // 如果是的话就往左查找
            right = mid;
        }
    }
    // 这里考虑交界情况是,在上面循环中如果 left 是好的,right 是坏的,那进入循环的时候 mid == left
    // 然后 left = mid + 1 就会等于 right,循环条件就跳出了,此时 left 就是那个起始的错误点了
    // 其实这两个是同一个值
    return left;
}

往右移动示例

往左移动示例

结果

题目介绍

Given an integer array nums of length n and an integer target, find three integers in nums such that the sum is closest to target.

Return the sum of the three integers.

You may assume that each input would have exactly one solution.

简单解释下就是之前是要三数之和等于目标值,现在是找到最接近的三数之和。

示例

Example 1:

Input: nums = [-1,2,1,-4], target = 1
Output: 2
Explanation: The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

Example 2:

Input: nums = [0,0,0], target = 1
Output: 0

Constraints:

  • 3 <= nums.length <= 1000
  • -1000 <= nums[i] <= 1000
  • -10^4 <= target <= 10^4

简单解析

这个题思路上来讲不难,也是用原来三数之和的方式去做,利用”双指针法”或者其它描述法,但是需要简化逻辑

code

public int threeSumClosest(int[] nums, int target) {
        Arrays.sort(nums);
        // 当前最近的和
        int closestSum = nums[0] + nums[1] + nums[nums.length - 1];
        for (int i = 0; i < nums.length - 2; i++) {
            if (i == 0 || nums[i] != nums[i - 1]) {
                // 左指针
                int left = i + 1;
                // 右指针
                int right = nums.length - 1;
                // 判断是否遍历完了
                while (left < right) {
                    // 当前的和
                    int sum = nums[i] + nums[left] + nums[right];
                    // 小优化,相等就略过了
                    while (left < right && nums[left] == nums[left + 1]) {
                        left++;
                    }
                    while (left < right && nums[right] == nums[right - 1]) {
                        right--;
                    }
                    // 这里判断,其实也还是希望趋近目标值
                    if (sum < target) {
                        left++;
                    } else {
                        right--;
                    }
                    // 判断是否需要替换
                    if (Math.abs(sum - target) < Math.abs(closestSum - target)) {
                        closestSum = sum;
                    }
                }
            }
        }
        return closestSum;
    }

结果

寻找原因

这次碰到一个比较奇怪的问题,应该统一发布脚本统一给应用启动参数传了个 -Dserver.port=xxxx,其实这个端口会作为 dubbo 的服务端口,并且应用也不提供 web 服务,但是在启动的时候会报embedded servlet container failed to start. port xxxx was already in use就觉得有点奇怪,仔细看了启动参数猜测可能是这个问题,有可能是依赖的二方三方包带了 spring-web 的包,然后基于 springboot 的 auto configuration 会把这个自己加载,就在本地复现了下这个问题,结果的确是这个问题。

解决方案

老版本 设置 spring 不带 web 功能

比较老的 springboot 版本,可以使用

SpringApplication app = new SpringApplication(XXXXXApplication.class);
app.setWebEnvironment(false);
app.run(args);

新版本

新版本的 springboot (>= 2.0.0)可以在 properties 里配置

spring.main.web-application-type=none

或者

SpringApplication app = new SpringApplication(XXXXXApplication.class);
app.setWebApplicationType(WebApplicationType.NONE);

这个枚举里还有其他两种配置

public enum WebApplicationType {

	/**
	 * The application should not run as a web application and should not start an
	 * embedded web server.
	 */
	NONE,

	/**
	 * The application should run as a servlet-based web application and should start an
	 * embedded servlet web server.
	 */
	SERVLET,

	/**
	 * The application should run as a reactive web application and should start an
	 * embedded reactive web server.
	 */
	REACTIVE

}

相当于是把none 的类型和包括 servlet 和 reactive 放进了枚举类进行控制。

题目介绍

Given a 2D grid of size m x n and an integer k. You need to shift the grid k times.

In one shift operation:

Element at grid[i][j] moves to grid[i][j + 1].
Element at grid[i][n - 1] moves to grid[i + 1][0].
Element at grid[m - 1][n - 1] moves to grid[0][0].
Return the 2D grid after applying shift operation k times.

示例

Example 1:

Input: grid = [[1,2,3],[4,5,6],[7,8,9]], k = 1
Output: [[9,1,2],[3,4,5],[6,7,8]]

Example 2:

Input: grid = [[3,8,1,9],[19,7,2,5],[4,6,11,10],[12,0,21,13]], k = 4
Output: [[12,0,21,13],[3,8,1,9],[19,7,2,5],[4,6,11,10]]

Example 3:

Input: grid = [[1,2,3],[4,5,6],[7,8,9]], k = 9
Output: [[1,2,3],[4,5,6],[7,8,9]]

提示

  • m == grid.length
  • n == grid[i].length
  • 1 <= m <= 50
  • 1 <= n <= 50
  • -1000 <= grid[i][j] <= 1000
  • 0 <= k <= 100

解析

这个题主要是矩阵或者说数组的操作,并且题目要返回的是个 List,所以也不用原地操作,只需要找对位置就可以了,k 是多少就相当于让这个二维数组头尾衔接移动 k 个元素

代码

public List<List<Integer>> shiftGrid(int[][] grid, int k) {
        // 行数
        int m = grid.length;
        // 列数
        int n = grid[0].length;
        // 偏移值,取下模
        k = k % (m * n);
        // 反向取下数量,因为我打算直接从头填充新的矩阵
        /*
         *    比如
         *    1 2 3
         *    4 5 6
         *    7 8 9
         *    需要变成
         *    9 1 2
         *    3 4 5
         *    6 7 8
         *    就要从 9 开始填充
         */
        int reverseK = m * n - k;
        List<List<Integer>> matrix = new ArrayList<>();
        // 这类就是两层循环
        for (int i = 0; i < m; i++) {
            List<Integer> line = new ArrayList<>();
            for (int j = 0; j < n; j++) {
                // 数量会随着循环迭代增长, 确认是第几个
                int currentNum = reverseK + i * n +  (j + 1);
                // 这里处理下到达矩阵末尾后减掉 m * n
                if (currentNum > m * n) {
                    currentNum -= m * n;
                }
                // 根据矩阵列数 n 算出在原来矩阵的位置
                int last = (currentNum - 1) % n;
                int passLine = (currentNum - 1) / n;

                line.add(grid[passLine][last]);
            }
            matrix.add(line);
        }
        return matrix;
    }

结果数据


比较慢

断断续续地看完了马伯庸老师的《长安的荔枝》,一开始是看这本书在排行榜排得很高,又是马伯庸的,之前看过他的《古董局中局》,还是很有意思的,而且正好是比较短的,不过前后也拖了蛮久才看完,看完后读了下马老师自己写的后记,就特别有感触。
整个故事是围绕一个上林署监事李善德被委任一项给贵妃送荔枝的差事展开,“长安回望绣成堆,山顶千门次第开,一骑红尘妃子笑,无人知是荔枝来”,以前没细究过这个送荔枝的过程,但是以以前的运输速度和保鲜条件,感觉也不是太现实,所以主人公一开始就以为只是像以往一样是送荔枝干这种,能比较方便运输,不容易变质的,结果发现其实是同僚在坑他,这次是要在贵妃生辰的时候给贵妃送来新鲜的岭南荔枝,用比较时兴的词来说,这就是个送命题啊,鲜荔枝一日色变,两日香变,三日味变,同僚的还有杜甫跟韩承,都觉得老李可以直接写休书了,保全家人,不然就是全家送命,李善德也觉得基本算是判刑了,而且其实是这事被转了几次,最后到老李所在的上林署,主管为了骗他接下这个活还特意在文书上把荔枝鲜的“鲜”字贴住,那会叫做“贴黄”,变成了荔枝“煎”,所以说官场险恶,大家都想把这烫手山芋丢出去,结果丢到了我们老实的老李头上,但是从接到这个通知到贵妃的生辰六月初一还有挺长的时间,其实这个活虽然送命,但是在前期这个“荔枝使”也基本就是类似带着尚方宝剑,御赐黄马褂的职位,随便申请经费,不必像常规的部门费用需要定预算,申请后再层层审批,而是特事特批特办的耍赖做法,所以在这段时间是能够潇洒挥霍一下的。其实可以好好地捞一波给妻女,然后写下和离,在自己死后能让她们过的好一些,但最后还是在杜甫的一番劝导下做出了尝试一番的决定,因为也没其他办法,既是退无可退,何不向前拼死一搏,其实说到这,我觉得看这本书感觉有所收获的第一点,有时候总觉得事情没戏了,想躺平放弃了,但是这样其实这个结果是不会变好的,尝试努力,拼尽全力搏一搏,说不定会有所改观,至少不会变更坏了。