likes
comments
collection
share

leetcode-神策数据周赛、1337-矩阵中战斗力最弱的k行 |8月更文挑战

作者站长头像
站长
· 阅读数 16

leetcode-神策数据周赛、1337-矩阵中战斗力最弱的k行

[博客链接]

菜🐔的学习之路

[题目描述]

  • 给你一个大小为 m * n 的矩阵 mat,矩阵由若干军人和平民组成,分别用 1 和 0 表示。
  • 请你返回矩阵中战斗力最弱的 k 行的索引,按从最弱到最强排序。
  • 如果第 i 行的军人数量少于第 j 行,或者两行军人数量相同但 i 小于 j,那么我们认为第 i 行的战斗力比第 j 行弱。
  • 军人 总是 排在一行中的靠前位置,也就是说 1 总是出现在 0 之前。 示例 1:
  • 输入:mat = [[1,1,0,0,0], [1,1,1,1,0], [1,0,0,0,0], [1,1,0,0,0], [1,1,1,1,1]],
  • k = 3
  • 输出:[2,0,3]
  • 解释:
  • 每行中的军人数目:
  • 行 0 -> 2
  • 行 1 -> 4
  • 行 2 -> 1
  • 行 3 -> 2
  • 行 4 -> 5
  • 从最弱到最强对这些行排序后得到 [2,0,3,1,4] 示例 2:
  • 输入:mat = [[1,0,0,0], [1,1,1,1], [1,0,0,0], [1,0,0,0]],
  • k = 2
  • 输出:[0,2]
  • 解释:
  • 每行中的军人数目:
  • 行 0 -> 1
  • 行 1 -> 4
  • 行 2 -> 1
  • 行 3 -> 1
  • 从最弱到最强对这些行排序后得到 [0,2,3,1] 提示:
  • m == mat.length
  • n == mat[i].length
  • 2 <= n, m <= 100
  • 1 <= k <= m
  • matrix[i][j] 不是 0 就是 1
  • Related Topics 数组 二分查找 矩阵 排序 堆(优先队列)
  • 👍 70 👎 0

[题目链接]

leetcode题目链接

[github地址]

代码链接

[思路介绍]

思路一:暴力法+hash+优先队列

  • 暴力法扫描所有单行数组,求战斗力和
  • 然后通过treemap做排序
  • 再通过优先队列对优先队列做弹出
  • 给固定长度K的数组进行赋值
   public int[] kWeakestRows(int[][] mat, int k) {
            Map<Integer, PriorityQueue<Integer>> map = new TreeMap<>((a, b) -> a - b);
            for (int i = 0; i < mat.length; i++) {
                int j = 0, temp = 0;
                while (j < mat[i].length && mat[i][j++] == 1) {
                    temp++;
                }
                PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(new Comparator<Integer>() {
                    @Override
                    public int compare(Integer o1, Integer o2) {
                        return o1 - o2;
                    }
                });
                priorityQueue = map.getOrDefault(temp, priorityQueue);
                priorityQueue.add(i);
                map.put(temp, priorityQueue);
            }
            int[] res = new int[k];
            int i = 0;
            for (int key : map.keySet()
            ) {
                while (i < k && !map.get(key).isEmpty()) {
                    res[i++] = map.get(key).poll();
                }
            }
            return res;
        }

时间复杂度O(m*n)​


思路二:二分查找+优先队列

  • 根据数组排列情况,可以通过二分计算战斗力值
  • 同时根据优先队列的大小控制输出数组
  • 然后返回结果
//思路二:二分+优先队列
        //根据数组排列情况,可以通过二分计算战斗力值
        //同时根据优先队列的大小控制输出数组
        //然后返回结果
        Map<Integer, Integer> map = new HashMap<>();

        public int[] kWeakestRows(int[][] mat, int k) {
            int[] res = new int[k];
            PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    if (map.getOrDefault(o2, 0).equals(map.getOrDefault(o1, 0))) {
                        return o2 - o1;
                    }
                    return map.getOrDefault(o2, 0) - map.getOrDefault(o1, 0);
                }
            });
            for (int i = 0; i < mat.length; i++) {
                int value = getValue(mat[i]);
                map.put(i, value);
                if (priorityQueue.size() < k) {
                    priorityQueue.add(i);
                } else {
                    if (map.get(priorityQueue.peek()) > value) {
                        priorityQueue.poll();
                        priorityQueue.add(i);
                    }
                }
            }
            for (int i = k - 1; i >= 0; i--) {
                res[i] = priorityQueue.poll();
            }
            return res;
        }

        private int getValue(int[] mat) {
            int l = 0, r = mat.length - 1;
            while (l < r) {
                int mid = l + r + 1 >> 1;
                if (mat[mid] >= 1) l = mid;
                else r = mid - 1;
            }
            return mat[r] > 0 ? r + 1 : r;
        }

时间复杂度O(m(lgn+lgk)


神策数据周赛

Q1 是否是三除数

给你一个整数 n 。如果 n 恰好有三个正除数 ,返回 true ;否则,返回 false 。

如果存在整数 k ,满足 n = k * m ,那么整数 m 就是 n 的一个 除数 。

 

示例 1:

输入:n = 2
输出:false
解释:2 只有两个除数:1 和 2 。
示例 2:

输入:n = 4
输出:true
解释:4 有三个除数:1、2 和 4 。
 

提示:

1 <= n <= 104

思路一:数学分析

  • 也就是说他只能包含一个因数,因为1 和 n本身是一定满足的
class Solution {
        public boolean isThree(int n) {
            if(n <= 2){
                return false;
            }
            boolean flag =false;
            for(int i = 2; i <n ; i++){
                if(n%i==0){
                    if(flag){return false;}
                    flag = true;
                }
            }
            return flag;
        }
    }

时间复杂度O(n)


Q2 最长连续工作周数

给你 n 个项目,编号从 0 到 n - 1 。同时给你一个整数数组 milestones ,其中每个 milestones[i] 表示第 i 个项目中的阶段任务数量。

你可以按下面两个规则参与项目中的工作:

每周,你将会完成 某一个 项目中的 恰好一个 阶段任务。你每周都 必须 工作。
在 连续的 两周中,你 不能 参与并完成同一个项目中的两个阶段任务。
一旦所有项目中的全部阶段任务都完成,或者仅剩余一个阶段任务都会导致你违反上面的规则,那么你将 停止工作 。注意,由于这些条件的限制,你可能无法完成所有阶段任务。

返回在不违反上面规则的情况下你 最多 能工作多少周。

 

示例 1:

输入:milestones = [1,2,3]
输出:6
解释:一种可能的情形是:
••••- 第 1 周,你参与并完成项目 0 中的一个阶段任务。
- 第 2 周,你参与并完成项目 2 中的一个阶段任务。
- 第 3 周,你参与并完成项目 1 中的一个阶段任务。
- 第 4 周,你参与并完成项目 2 中的一个阶段任务。
- 第 5 周,你参与并完成项目 1 中的一个阶段任务。
- 第 6 周,你参与并完成项目 2 中的一个阶段任务。
总周数是 6 。
示例 2:

输入:milestones = [5,2,1]
输出:7
解释:一种可能的情形是:
- 第 1 周,你参与并完成项目 0 中的一个阶段任务。
- 第 2 周,你参与并完成项目 1 中的一个阶段任务。
- 第 3 周,你参与并完成项目 0 中的一个阶段任务。
- 第 4 周,你参与并完成项目 1 中的一个阶段任务。
- 第 5 周,你参与并完成项目 0 中的一个阶段任务。
- 第 6 周,你参与并完成项目 2 中的一个阶段任务。
- 第 7 周,你参与并完成项目 0 中的一个阶段任务。
总周数是 7 。
注意,你不能在第 8 周参与完成项目 0 中的最后一个阶段任务,因为这会违反规则。
因此,项目 0 中会有一个阶段任务维持未完成状态。
 

提示:

n == milestones.length
1 <= n <= 105
1 <= milestones[i] <= 109

思路一:贪心法

  • 最大解如果可以满足情况,那么其余任务一定都可以满足

  • 如果最大解不满足情况,则是总和-最大解*2+1

  • 这道题的贪心我没想到怎么证明

     public long numberOfWeeks(int[] milestones) {
                int max = milestones[0];
                long sum = 0L;
                for (int i = 0; i < milestones.length; i++) {
                    sum += milestones[i];
                    max = Math.max(max, milestones[i]);
                }
                long remain = sum - max;
                return Math.min(sum, 2 * remain + 1);
            }

时间复杂度O(n)

Q3 满足所需苹果的最小周长

    给你一个用无限二维网格表示的花园,每一个 整数坐标处都有一棵苹果树。整数坐标 (i, j) 处的苹果树有 |i| + |j| 个苹果。

    你将会买下正中心坐标是 (0, 0) 的一块 正方形土地 ,且每条边都与两条坐标轴之一平行。

    给你一个整数 neededApples ,请你返回土地的 最小周长 ,使得 至少 有 neededApples 个苹果在土地 里面或者边缘上。

    |x| 的值定义为:

    如果 x >= 0 ,那么值为 x
    如果 x < 0 ,那么值为 -x
     

    示例 1:


    输入:neededApples = 1
    输出:8
    解释:边长长度为 1 的正方形不包含任何苹果。
    但是边长为 2 的正方形包含 12 个苹果(如上图所示)。
    周长为 2 * 4 = 8
    示例 2:

    输入:neededApples = 13
    输出:16
    示例 3:

    输入:neededApples = 1000000000
    输出:5040
     

    提示:



    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/minimum-garden-perimeter-to-collect-enough-apples
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

leetcode-神策数据周赛、1337-矩阵中战斗力最弱的k行 |8月更文挑战

思路一:数学公式+二分

  • 可以很容易的求得总苹果树的数量公示
  • apples = 2 * i * (i + 1) * (2 * i + 1);
    //思路一:二分等会儿写吧 先写暴力
            /*public long minimumPerimeter(long neededApples) {
                for (long i = 0; i < Integer.MAX_VALUE; i++) {
                    long apples = 2 * i * (i + 1) * (2 * i + 1);
                    if (apples >= neededApples) {
                        return i * 8L;
                    }
                }
                return 0;
            }*/
            //思路二:二分
            public long minimumPerimeter(long neededApples) {
                int l = 0, r = Integer.MAX_VALUE;
                while (l < r) {
                    int mid = (l + r )/2;
                    long apples = 2 * mid * (mid + 1) * (2 * mid + 1);
                    if (apples > neededApples) {
                        r = mid - 1;
                    } else {
                        l = mid;
                    }
                }
                return r;
            }

时间复杂度暴力O(n), 二分O(lgn)

转载自:https://juejin.cn/post/6991321271120166948
评论
请登录