上岸 I LeetCode Weekly Contest 195解题报告 刷题解法

卖大米 2020-6-28 638


No.1 判断路径是否相交

★解题思路

使用一个 Set 记录已经走过的点即可.

代码展示


class Solution { 
   public boolean isPathCrossing(String path) { 
       // 一个点 (x, y), 使用 x * 100000 + y 即可唯一表示这个点 
       // 因为题目说明操作不超过 10^4, 即 x, y 的绝对值不会超过 10^4 
       Set<Long> set = new HashSet<>(); 
       char[] str = path.toCharArray(); 
       long x = 0, y = 0; 
       set.add(x * 100000 + y); 
       for (char c : str) { 
           switch (c) { 
               case 'N' -> x++; 
               case 'S' -> x--; 
               case 'W' -> y--; 
               case 'E' -> y++; 
           } 
           if (set.contains(x * 100000 + y)) { 
               return true; 
           } 
           set.add(x * 100000 + y); 
       } 
       return false; 
   } 
}

No.2 检查数组对是否可以被k整除

解题思路

详情见注释.

代码展示


class Solution { 
   public boolean canArrange(int[] arr, int k) { 
       int n = arr.length; 
       for (int i = 0; i < n; i++) { 
           // 将数组的元素转换成 [0, k) 范围内的值 
           // % 运算不影响两个数相加后是否可以被 k 整除  
           arr[i] = ((arr[i] % k) + k) % k; 
       } 
       // 排序 
       Arrays.sort(arr); 
       // 统计 0 的个数 
       int zero = 0; 
       while (zero < n && arr[zero] == 0) zero++; 
       if (zero % 2 != 0) return false; // 奇数个 0, 非法 
       // 非 0 的必须两两成对, 相加等于 k (即原本的两个数相加可以被 k 整除) 
       for (int left = zero, right = n - 1; left < right; ) { 
           if (arr[left] + arr[right] == k) { 
               left++; 
               right--; 
           } else { 
               return false; 
           } 
       } 
       return true; 
   } 
}

No.3 满足条件的子序列数目

★解题思路

详情见注释.

代码展示


class Solution { 
   public int numSubseq(int[] nums, int target) { 
       Arrays.sort(nums); 
       long res = 0; 
       // 依次计算以每个元素为最小值时的序列个数 
       for (int left = 0, right = nums.length - 1; left <= right; left++) { 
           while (left <= right && nums[left] + nums[right] > target) right--; 
           if (left <= right && nums[left] + nums[right] <= target) { 
               // 以 left 为最小值时, [left, right] 之间的任意元素可以做最大值 
               // 以 r 为最大值时, 子序列有 2 ^ (r - left - 1) 个, 特殊地, left == r 时有 1 个子序列 
               // 即 1 + 1 + 2 + 4 + ... + 2^(right-left-1) = 2^(right-left) 
               // 不能直接用 1 << x 来求 2 ^ x, 可能会溢出 
               res += mypow(2L, right - left, 1000000007L); 
               res %= 1000000007L; 
           } 
       } 
       return (int)res; 
   } 
   // 递归式的快速幂 
   long mypow(long x, int y, long mod) { 
       if (y == 0) return 1L; 
       if (y == 1) return x % mod; 
       long t = mypow(x, y / 2, mod); 
       if (y % 2 == 0) return t * t % mod; 
       else return (t * x % mod) * t % mod; 
   } 
}

No.4 满足不等式的最大值

★解题思路

单调队列.

队列中保存 x 坐标比当前点小的点, 同时越靠前的点越优秀 (与当前点计算得到的答案越大).

代码展示


class Solution { 
   public int findMaxValueOfEquation(int[][] points, int k) { 
       LinkedList<int[]> queue = new LinkedList<>(); 
       int n = points.length; 
       int res = Integer.MIN_VALUE; 
       queue.add(points[0]); 
       for (int i = 1; i < n; i++) { 
           // 将 x 坐标超出范围的点出队 
           while (!queue.isEmpty() && points[i][0] - queue.getFirst()[0] > k) queue.pollFirst(); 
           // 队不为空, 则用队首与当前点计算答案 
           if (!queue.isEmpty()) { 
               int[] p = queue.getFirst(); 
               res = Math.max(res, points[i][1] + p[1] + Math.abs(points[i][0] - p[0])); 
           } 
           // 当前点入队前, 判断是否比队尾优秀 
           // 若比队尾优秀, 那么将队尾出队, 以维持单调性 
           // 因为计算方式为 y1+y2+|x1-x2|, 所以只要 y 的增长超过了 x 的增长, 那么当前点就比队尾更优秀 
           while (!queue.isEmpty() && points[i][1] - queue.getLast()[1] > points[i][0] - queue.getLast()[0]) queue.pollLast(); 
           queue.add(points[i]); 
       } 
       return res; 
   } 
}

杭州上岸算法网络科技有限公司

上岸科技,一家位于西雅图致力于帮助北美小伙伴们上岸的团体。

团队主要由一群怀揣情怀于美国高校毕业的一线IT公司工程师构成。我们坚持采用小班课形式,并结合大量”面试式“和”白板“的教学和交流形式,最终帮助大家提升求职成功概率同时大大减少刷题的痛苦。

正如我们的信仰:我们教的是如何上岸而不仅是算法。

最新回复 (0)
返回