LeetCode 116th Weekly Contest 总结

第一题很简单easy跳过

1. 962. Maximum Width Ramp

题意

Given an array A of integers, a ramp is a tuple (i, j) for which i < j and A[
i] <= A[j]. The width of such a ramp is j - i.
Find the maximum width of a ramp in A. If one doesn't exist, return 0.

找到一个数组中A[j] > A[i],且(j - i)最大的值

这题看起来不难,但是O(n^2)超时,需要复杂度更小的,其实有很多解法

思路

  • 解法一:用TreeMap,最简单的一种思路
    找到比当前数小的第一次出现的数
    即如果存在比当前数小的数了,则不要将当前数放进去了;否则将当前数放进去,可以更新最小值
class Solution {
    public int maxWidthRamp(int[] A) {
        int res = 0;
        int n = A.length;
        TreeMap<Integer, Integer> map = new TreeMap<>();
        for (int i = 0; i < n; i++) {
            if (map.floorKey(A[i]) == null) {
                map.put(A[i], i);  
            } else {
                res = Math.max(res, i - map.get(map.floorKey(A[i])));
            }
        }
        return res;
    }
}
  • 解法二 :排序O(nlogn): 排序index,然后只要维护每个index前面最小的index就行了
public int maxWidthRamp(int[] A) {
        int n = A.length;
        Integer[] indexes = new Integer[n];
        for (int i = 0; i < n; i++) {
            indexes[i] = i;
        }
        Arrays.sort(indexes, (a, b) -> ((Integer) A[a]).compareTo(A[b]));
        
        int res = 0, minIndex = indexes[0];
        for (int i = 0; i < n; i++) {
            res = Math.max(res, indexes[i] - minIndex);
            minIndex = Math.min(minIndex, indexes[i]);
        }
        return res;
}
  • 解法三 :单调栈 O(n):
    找到左边第一个比它小的数
    那么用递增栈还是递减栈呢?=>
    如果我们从右向左遍历每个数的话,希望找到左起第一个比该数小的数,也就是希望栈顶是第一个比这个数小的数,=>
    那么如果我们能保证栈顶右边的数,都比栈顶的数大,就是对于右边的数来说,栈顶的数就是第一个小于它的数了 =>
    可以维护一个递减栈

代码:

class Solution {
    public int maxWidthRamp(int[] A) {
        Stack<Integer> stack = new Stack<>();
        int n = A.length;
        for (int i = 0; i < n; i++) {
            if (stack.isEmpty() || A[stack.peek()] > A[i]) {
                stack.push(i);
            }
        }
        int res = 0;
        for (int i = n - 1; i > 0; i--) {
            while (!stack.isEmpty() && A[i] >= A[stack.peek()]) {
                res = Math.max(res, i - stack.pop());
            }
        }
        return res;
    }
}

总结:

2. Minimum Area Rectangle II

题意

Given a set of points in the xy-plane, determine the minimum area of any rectangle formed from these points, with sides not necessarily parallel to the x and y axes.

点能组成的最小面积的矩形,边不一定要平行

思路

这道题是939. Minimum Area Rectangle 的follow up,939要求矩形两边平行坐标轴,用hash table解的。该题的话,由于边可以不平行坐标轴,构成矩形的条件需要稍作思考。

  • 由于涉及到边不会平行坐标轴,则应该考虑对角线来构成矩形
  • 初中数学:对角线相等且平分的四边形是矩形 => 可以借助hash table,key存对角线长度和中点构成的字符串,value存对角线的点
  • 知道了对角线的坐标点后,我们得到了矩形的两个对角线坐标,然后用勾股定理求出两个矩形邻边,再相乘就行了;

代码:

class Solution {
    public double minAreaFreeRect(int[][] points) {
        int len = points.length;
        double res = Double.MAX_VALUE;
        if (len < 4) return 0.0;
        Map<String, List<int[]>> map = new HashMap<>();
        for (int i = 0; i < len; i++) {
            for (int j = i + 1; j < len; j++) {
                long dis = (points[i][0] - points[j][0]) * (points[i][0] - points[j][0]) + (points[i][1] - points[j][1]) * (points[i][1] - points[j][1]);
                double cx = (double)(points[j][0] + points[i][0])/2;
                double cy = (double)(points[j][1] + points[i][1])/2;
                String key = "" + dis + "+" + cx + "+" + cy; 
                if (map.get(key) == null) map.put(key, new ArrayList<int[]>());
                map.get(key).add(new int[]{i,j});
            }
        }
        for (String key : map.keySet()) {
            if (map.get(key).size() > 1) {
                List<int[]> list = map.get(key);
                int lsize= list.size();
                for (int i = 0; i < lsize; i++) {
                    for (int j = i + 1; j < lsize; j++) {
                        int p1 = list.get(i)[0];
                        int p2 = list.get(j)[0];
                        int p3 = list.get(j)[1];
                        double temp = Math.sqrt((points[p1][0] - points[p2][0]) * (points[p1][0] - points[p2][0]) +  (points[p1][1] - points[p2][1]) * (points[p1][1] - points[p2][1]))*  Math.sqrt((points[p1][0] - points[p3][0]) * (points[p1][0] - points[p3][0]) +  (points[p1][1] - points[p3][1]) * (points[p1][1] - points[p3][1]));
                        res = Math.min(res, temp);
                    }
                }
            }
        }
        return res == Double.MAX_VALUE ?  0.0 : res;
    }
}

总结

...emmm 加油吧,周赛的历练不够哇,以后坚持周周都要做

看到了大佬的博客,每道题都有题解,量的积累到质的飞跃

原文地址:https://www.cnblogs.com/shawshawwan/p/10165952.html