zoukankan      html  css  js  c++  java
  • 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 加油吧,周赛的历练不够哇,以后坚持周周都要做

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

  • 相关阅读:
    操作系统——死锁相关
    Java 实现广度优先搜索和深度优先搜索
    Java 实现常见排序算法
    初次接触JQuery
    Firefox使用stylish自定义网页背景
    使用randoop自动化生成测试用例
    软件测试(五)——使用Selenium IDE进行自动化测试
    软件项目管理(二)——用jenkins持续集成、Maven、Github的使用
    云计算(一)——使用 Hadoop Mapreduce 进行数据处理
    软件测试(四)——图覆盖
  • 原文地址:https://www.cnblogs.com/shawshawwan/p/10165952.html
Copyright © 2011-2022 走看看