• acwing每日一题(8.12 ~ 8.14)


    2022.8.12

    Leetcode 128  用户分组

    1282. 用户分组 - 力扣(LeetCode)

    思路:我们用哈希表存储  键:不同大小的组     值:组内元素 (用一个链表或者ArrayList)

    如果一个哈希表的组内元素个数  ==  它的组的大小   则说明我们当前组加满了,可以塞进答案中了

    遍历所有的点,重复操作即可 (时间复杂度 O(N))

    1. class Solution {
    2. public List> groupThePeople(int[] groupSizes) {
    3. Map> map = new HashMap<>();
    4. List> res = new ArrayList<>();
    5. for (int i = 0; i < groupSizes.length; i ++) {
    6. int j = groupSizes[i];
    7. if (map.get(j) == null) { // 说明还没有ArrayList
    8. map.put(j,new ArrayList());
    9. }
    10. map.get(j).add(i); // 把元素加入到组内
    11. if (map.get(j).size() == j) { // 如果组满了就重开组
    12. res.add(map.get(j));
    13. map.remove(j);
    14. }
    15. }
    16. return res;
    17. }
    18. }

    2022.8.13

    Leetcode 768    最多能完成排序的块

    768. 最多能完成排序的块 II - 力扣(LeetCode) 

    思路1:假设我们有一个排序后的组,如果对一段从0开始的区间 它的元素种类和 我们未排序的块一样,那我们可以排序的次数就要加1,因此我们可以用一个hash表来存储,未排序复杂对应元素++,排序复杂元素-- ,如果一段区间元素的个数都是0,则res++(时间复杂度 O(N * logN))

    思路二:单调栈的利用,假设我们当前元素i的前边元素都已经分好块了,如果我们 i 小于 上一个块的最大值,则说明上一个块其实没有完全分好(它必须加上我们的i)如果我们的 i 大于上一个元素,则我们的 i 可以成为一个新的块(时间复杂度 O(N))

    思路三:很巧妙的利用前缀和的思想,我们可以发现 可以分块的区间它的前缀和都是和排完序之后的区间前缀和相等的(元素一样,和肯定相等)所以我们可以统计有多少次前缀和相等即可(时间复杂度 O(N * Log N))

    单调栈代码:

    1. class Solution {
    2. public int maxChunksToSorted(int[] arr) {
    3. Deque stk = new LinkedList<>();
    4. for (int x: arr) {
    5. int t = x;
    6. while (!stk.isEmpty() && stk.peek() > x) { // 把不合法的区间合成一段
    7. t = Math.max(t,stk.peek());
    8. stk.pop();
    9. }
    10. stk.push(t);
    11. }
    12. return stk.size();
    13. }
    14. }

    前缀和代码:

    1. class Solution {
    2. public int maxChunksToSorted(int[] arr) {
    3. int[] sum = Arrays.copyOf(arr,arr.length); // 复制加排序
    4. Arrays.sort(sum);
    5. for (int i = 0; i < arr.length; i ++) {
    6. if (i != 0) { // 前缀和的处理
    7. sum[i] += sum[i - 1];
    8. arr[i] += arr[i - 1];
    9. }
    10. }
    11. int res = 0;
    12. for (int i = 0; i < arr.length; i ++) {
    13. if (sum[i] == arr[i]) res ++;
    14. }
    15. return res;
    16. }
    17. }

    Hash表代码:

    1. class Solution {
    2. public int maxChunksToSorted(int[] arr) {
    3. int[] a = Arrays.copyOf(arr,arr.length);
    4. Arrays.sort(a);
    5. Map map = new HashMap<>();
    6. int res = 0;
    7. for (int i = 0,cnt = 0; i < arr.length; i ++) {
    8. map.put(arr[i],map.getOrDefault(arr[i],0) + 1);
    9. if (map.getOrDefault(arr[i],0) == 0) cnt --;
    10. else if (map.getOrDefault(arr[i],0) == 1)cnt ++;
    11. map.put(a[i],map.getOrDefault(a[i],0) - 1);
    12. if (map.getOrDefault(a[i],0) == 0) cnt --;
    13. else if (map.getOrDefault(a[i],0) == -1) cnt ++;
    14. if (cnt == 0) res ++;
    15. }
    16. return res;
    17. }
    18. }

    2022.8.14

    acwing 4405  统计子矩阵个数

    c++ 蓝桥杯省赛

    4405. 统计子矩阵 - AcWing题库

     

    思路:n,m 都是 500 级别 暴力枚举矩阵四个边界时间复杂度是 O(N^4) 肯定超时了

    因此考虑双指针优化,固定 一个有边界 r , 左边界 l 定义为最靠左的矩阵之和不超过 k 的边,当 r往右, l 也只能往右 因此得到对于 l 和 r 的单调函数 ,可以采用双指针优化

     预处理前缀和的复杂度是O(N) 的,由于我们固定上下边界,我们只需要处理每一列的前缀和

    代码:

    1. import java.util.*;
    2. public class Main{
    3. static int N = 510;
    4. static int[][] s = new int[N][N];
    5. public static void main(String[] args) {
    6. Scanner sc = new Scanner(System.in);
    7. int n = sc.nextInt(), m = sc.nextInt(), k = sc.nextInt();
    8. for (int i = 1; i <= n; i ++) {
    9. for (int j = 1; j <= m; j ++) {
    10. s[i][j] = sc.nextInt();
    11. s[i][j] += s[i - 1][j];
    12. }
    13. }
    14. long res = 0;
    15. for (int i = 1; i <= n; i ++) {
    16. for (int j = i; j <= n; j ++) {
    17. for (int l = 1,r = 1,sum = 0; r <= m; r ++) {
    18. sum += s[j][r] - s[i - 1][r]; // 加上最右边的一列
    19. while (sum > k) {
    20. sum -= s[j][l] - s[i - 1][l]; // 总和超过 k 了 需要把最左边的一列剔除
    21. l ++;
    22. }
    23. res += r - l + 1; // 总和没有超过k 此时l就是对于r 最靠左的一条边界 ,r 可以++
    24. }
    25. }
    26. }
    27. System.out.print(res);
    28. }
    29. }

  • 相关阅读:
    【MySQL基本查询(下)】
    DC电源模块的使用寿命问题
    刷题记录:牛客NC14701取数游戏2
    大型企业是否有必要进行数字化转型?
    android11.0 Launcher3 高端定制之新应用图标自动添加主屏幕
    DQL(数据库查询)
    创建无序列表
    差分(一维+二维超详细)
    QT发送Get请求并返回内容
    mysql 原生语句点滴学习记录
  • 原文地址:https://blog.csdn.net/qq_59539549/article/details/126339786