蓝桥杯备战国赛

13.dp

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

 
示例 1:

输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。
示例 2:

输入:nums = [0,1,0,3,2,3]
输出:4
示例 3:

输入:nums = [7,7,7,7,7,7,7]
输出:1

class Solution {
    public int lengthOfLIS(int[] nums) {
        int n = nums.length;
        if (n == 0) return 0;
        int[] dp = new int[n];
        dp[0] = 1;
        int res = 1;
        for (int i = 1; i < n; i++) {
            dp[i] = 1;
            for (int j = 0; j < i; j++) {
                if (nums[i] > nums[j])
                    dp[i] = Math.max(dp[i], dp[j] + 1);
            }
            res = Math.max(res, dp[i]);
        }
        return res;
    }
}

12.

给定 m 个数组,每个数组都已经按照升序排好序了。现在你需要从两个不同的数组中选择两个整数(每个数组选一个)并且计算它们的距离。两个整数 a 和 b 之间的距离定义为它们差的绝对值 |a-b| 。你的任务就是去找到最大距离

示例 1:

输入: 
[[1,2,3],
 [4,5],
 [1,2,3]]
输出: 4
解释:
一种得到答案 4 的方法是从第一个数组或者第三个数组中选择 1,同时从第二个数组中选择 5 。

class Solution {
    public int maxDistance(List<List<Integer>> list) {
        int res = 0, min = list.get(0).get(0), max = list.get(0).get(list.get(0).size() - 1);
        for (int i = 1; i < list.size(); i++) {
            res = Math.max(res, Math.max(Math.abs(list.get(i).get(list.get(i).size() - 1)- min),Math.abs(list.get(i).get(0) - max)));
            min = Math.min(min, list.get(i).get(0));
            max = Math.max(max, list.get(i).get(list.get(i).size() - 1));
        }
        return res;
    }
}

11.贪心

由范围 [1,n] 内所有整数组成的 n 个整数的排列 perm 可以表示为长度为 n - 1 的字符串 s ,其中:

如果 perm[i] < perm[i + 1] ,那么 s[i] == ' i '
如果 perm[i] > perm[i + 1] ,那么 s[i] == 'D' 。
给定一个字符串 s ,重构字典序上最小的排列 perm 并返回它。

示例 1:

输入: s = "I"
输出: [1,2]
解释: [1,2] 是唯一合法的可以生成秘密签名 "I" 的特定串,数字 1 和 2 构成递增关系。
示例 2:

输入: s = "DI"
输出: [2,1,3]
解释: [2,1,3] 和 [3,1,2] 可以生成秘密签名 "DI",
但是由于我们要找字典序最小的排列,因此你需要输出 [2,1,3]。

class Solution {
    public int[] findPermutation(String s) {
        int[] res = new int[s.length() + 1];
        for (int i = 0; i < res.length; i++) {
            res[i] = i + 1;
        }
        int i = 1;
        while (i <= s.length()) {
            int j = i;
            while (i <= s.length() && s.charAt(i - 1) == 'D')
                i++;
            change(res, j - 1,i);
            i++;
        }
        return res;
    }
    public void change(int[] a, int start, int end) {
        for (int i = 0; i < (end - start) / 2; i++) {
            int t = a[start + i];
            a[start + i] = a[end - i - 1];
            a[end - i - 1] = t;
        }
    }
}

10.优先队列

给你一个会议时间安排的数组 intervals ,每个会议时间都会包括开始和结束的时间 intervals[i] = [starti, endi] ,返回 所需会议室的最小数量 。

示例 1:

输入:intervals = [[0,30],[5,10],[15,20]]
输出:2
示例 2:

输入:intervals = [[7,10],[2,4]]
输出:1

class Solution {
    public int minMeetingRooms(int[][] intervals) {
        if (intervals == null || intervals.length == 0)
            return 0;
        int[] start = new int[intervals.length];
        int[] end = new int[intervals.length];
        for(int i=0;i<intervals.length;i++){
            start[i] = intervals[i][0];
            end[i] = intervals[i][1];
        }
        Arrays.sort(start);
        Arrays.sort(end);
        int rooms = 0, activemetting = 0, i = 0, j = 0;
        while (i < intervals.length && j < intervals.length) {
            if (start[i] < end[j]) {
                activemetting++;
                i++;
            }else {
                activemetting--;
                j++;
            }
            rooms = Math.max(rooms, activemetting);
        }
        return rooms;
    }
}

9.差分

一条街上有很多的路灯,路灯的坐标由数组 lights 的形式给出。 每个 lights[i] = [positioni, rangei] 代表坐标为 positioni 的路灯照亮的范围为 [positioni - rangei, positioni + rangei] (包括顶点)。

位置 p 的亮度由能够照到 p的路灯的数量来决定的。

给出 lights, 返回最亮的位置 。如果有很多,返回坐标最小的。

class Solution {
    public int brightestPosition(int[][] lights) {
        TreeMap<Integer,Integer> tm = new TreeMap<>();
        for(int[] x : lights) {
            int left = x[0] - x[1];
            // 因为两侧都包含,所以+1
            int right = x[0] + x[1] + 1;
            tm.put(left,tm.getOrDefault(left,0) + 1);
            tm.put(right,tm.getOrDefault(right,0) - 1);
        }
        int ans = Integer.MIN_VALUE;
        // 最大的亮度
        int max = 0;
        // 当前的亮度
        int cur = 0;
        for(Map.Entry<Integer,Integer> entry : tm.entrySet()) {
            cur += entry.getValue();
            if(cur > max) {
                max = cur;
                ans = entry.getKey();
            }
        }
        return ans;
    }
}

8.差分数组

假设你有一个长度为 n 的数组,初始情况下所有的数字均为 0,你将会被给出 k 个更新的操作。

其中,每个操作会被表示为一个三元组:[startIndex, endIndex, inc],你需要将子数组 A[startIndex ... endIndex](包括 startIndex 和 endIndex)增加 inc。

请你返回 k 次操作后的数组。

示例:

输入: length = 5, updates = [[1,3,2],[2,4,3],[0,2,-2]]
输出: [-2,0,3,5,3]
解释:

初始状态:
[0,0,0,0,0]

进行了操作 [1,3,2] 后的状态:
[0,2,2,2,0]

进行了操作 [2,4,3] 后的状态:
[0,2,5,5,3]

进行了操作 [0,2,-2] 后的状态:
[-2,0,3,5,3]

class Solution {
    public int[] getModifiedArray(int length, int[][] updates) {
        int[] res = new int[length];
        if (updates.length == 0) return res;
        for (int[] e : updates) {
            res[e[0]] += e[2];
            if (e[1] < length - 1)
                res[e[1] + 1] -= e[2];
        }
        for (int i = 1; i < length; i++) {
            res[i] += res[i - 1];
        }
        return res;
    }
}

7.dp

给定一个 m x n 的二进制矩阵 mat ,返回矩阵中最长的连续1线段。

这条线段可以是水平的、垂直的、对角线的或者反对角线的。

class Solution {
    public int longestLine(int[][] M) {
        if (M == null || M.length == 0 || M[0].length == 0)
            return 0;
        int ans = 0;
        int[][] horizontal = new int[M.length][M[0].length];
        int[][] vertical = new int[M.length][M[0].length];
        int[][] diagonal = new int[M.length][M[0].length];
        int[][] antidiagonal = new int[M.length][M[0].length];
        for (int i = 0; i != M.length; ++i) {
            for (int j = 0; j != M[0].length; ++j) {
                if (M[i][j] == 0) {
                    horizontal[i][j] = 0;
                    vertical[i][j] = 0;
                    diagonal[i][j] = 0;
                    antidiagonal[i][j] = 0;
                } else {
                    horizontal[i][j] = j > 0 ? horizontal[i][j - 1] + 1 : 1;
                    vertical[i][j] = i > 0 ? vertical[i - 1][j] + 1 : 1;
                    diagonal[i][j] = i > 0 && j > 0 ? diagonal[i - 1][j - 1] + 1 : 1;
                    antidiagonal[i][j] = i > 0 && j < M[0].length - 1 ? antidiagonal[i - 1][j + 1] + 1 : 1;
                    ans = Math.max(ans, horizontal[i][j]);
                    ans = Math.max(ans, vertical[i][j]);
                    ans = Math.max(ans, diagonal[i][j]);
                    ans = Math.max(ans, antidiagonal[i][j]);
                }
            }
        }
        return ans;
    }
}

6.bfs

你被给定一个 m × n 的二维网格 rooms ,网格中有以下三种可能的初始化值:

-1 表示墙或是障碍物
0 表示一扇门
INF 无限表示一个空的房间。然后,我们用 231 - 1 = 2147483647 代表 INF。你可以认为通往门的距离总是小于 2147483647 的。
你要给每个空房间位上填上该房间到 最近门的距离 ,如果无法到达门,则填 INF 即可。

class Solution {
        int EMPTY = Integer.MAX_VALUE;
        List<int[]> DIRECTIONS = Arrays.asList(
                new int[] { 1,  0},
                new int[] {-1,  0},
                new int[] { 0,  1},
                new int[] { 0, -1}
        );

        public void wallsAndGates(int[][] rooms) {
            int m = rooms.length;
            if (m == 0) return;
            int n = rooms[0].length;
            Queue<int[]> q = new LinkedList<>();
            for (int row = 0; row < m; row++) {
                for (int col = 0; col < n; col++) {
                    if (rooms[row][col] == 0) {
                        q.add(new int[] { row, col });
                    }
                }
            }
            while (!q.isEmpty()) {
                int[] point = q.poll();
                int row = point[0];
                int col = point[1];
                for (int[] direction : DIRECTIONS) {
                    int r = row + direction[0];
                    int c = col + direction[1];
                    if (r < 0 || c < 0 || r >= m || c >= n || rooms[r][c] != EMPTY) {
                        continue;
                    }
                    rooms[r][c] = rooms[row][col] + 1;
                    q.add(new int[] { r, c });
                }
            }
        }
}

5.

由空地(用 0 表示)和墙(用 1 表示)组成的迷宫 maze 中有一个球。球可以途经空地向 上、下、左、右 四个方向滚动,且在遇到墙壁前不会停止滚动。当球停下时,可以选择向下一个方向滚动。
给你一个大小为 m x n 的迷宫 maze ,以及球的初始位置 start 和目的地 destination ,其中 start = [startrow, startcol] 且 destination = [destinationrow, destinationcol] 。请你判断球能否在目的地停下:如果可以,返回 true ;否则,返回 false 。

你可以 假定迷宫的边缘都是墙壁(参考示例)。

class Solution {
    public boolean hasPath(int[][] maze, int[] start, int[] destination) {
        boolean[][] is = new boolean[maze.length][maze[0].length];
        return dfs(is,start,destination,maze);
    }
    public boolean dfs(boolean[][] is,int[] start, int[] destination,int[][] maze) {
        if (is[start[0]][start[1]])
            return false;
        if (destination[0] == start[0] && destination[1] == start[1])
            return true;
        is[start[0]][start[1]] = true;
        int right = start[1] + 1, left = start[1] - 1, up = start[0] - 1, down = start[0] + 1;
        //向右
        while (right < maze[0].length && maze[start[0]][right] == 0)
            right++;
        if (dfs(is,new int[]{start[0],right - 1},destination,maze))
            return true;
        //向左
        while (left >= 0 && maze[start[0]][left] == 0)
            left--;
        if (dfs(is,new int[]{start[0],left + 1},destination,maze))
            return true;
        //向上
        while (up >= 0 && maze[up][start[1]] == 0)
            up--;
        if (dfs(is,new int[]{up + 1,start[1]},destination,maze))
            return true;
        
        while (down < maze.length && maze[down][start[1]] == 0)
            down++;
        if (dfs(is,new int[]{down - 1,start[1]},destination,maze))
            return true;
        return false;
    }

}

4.深度优先搜索

给定一个非空 01 二维数组表示的网格,一个岛屿由四连通(上、下、左、右四个方向)的 1 组成,你可以认为网格的四周被海水包围。

请你计算这个网格中共有多少个形状不同的岛屿。两个岛屿被认为是相同的,当且仅当一个岛屿可以通过平移变换(不可以旋转、翻转)和另一个岛屿重合。

示例 1:

11000
11000
00011
00011
给定上图,返回结果 1 。

示例 2:

11011
10000
00001
11011

class Solution {
    int path = 0;
    public int numDistinctIslands(int[][] grid) {
        Set<Integer> set = new HashSet<>();
        for (int g = 0; g < grid.length; g++) {
            for (int i = 0; i < grid[0].length; i++) {
                if (grid[g][i] == 1) {
                    path = 0;
                    dfs(grid,g,i,path);
                    set.add(path);
                }
            }
        }
        return set.size();
    }
    public void dfs(int[][] grid, int i, int j, int pre) {
        if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] == 0)
            return;
        grid[i][j] = 0;
        path = path * 10 + pre;
        dfs(grid, i + 1, j,1);
        dfs(grid,i - 1, j, 2);
        dfs(grid, i ,j + 1, 3);
        dfs(grid,i,j - 1, 4);
        path = path * 10 + 5;
    }
}

3.深度优先搜索+二分

给定一个 m x n 的整数矩阵 grid,返回从 (0,0) 开始到 (m - 1, n - 1) 在四个基本方向上移动的路径的最大 分数 。

一条路径的 分数 是该路径上的最小值。

例如,路径 8 → 4 → 5 → 9 的得分为 4 。

class Solution {
    int n, m;
    int[][] dir = new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    public int maximumMinimumPath(int[][] grid) {
        n = grid.length;
        m = grid[0].length;
        int left = 0, right = Math.min(grid[0][0], grid[n - 1][m - 1]), res = -1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (dfs(mid, 0, 0, new boolean[n][m], grid)) {
                res = Math.max(res, mid);
                left = mid + 1;
            }else 
                right = mid - 1;
        }
        return res;
    }
    public boolean dfs(int min, int i, int j, boolean[][] is, int[][] grid) {
        if (i == n - 1 && j == m - 1)
            return true;
        is[i][j] = true;
        for (int k = 0; k < 4; k++) {
            int x = i + dir[k][0];
            int y = j + dir[k][1];
            if (x >= 0 && y >= 0 && x < n && y < m && !is[x][y] && grid[x][y] >= min) {
                if (dfs(min, x, y, is, grid))
                    return true;
            }
        }
        return false;
    }
}

2.dp

假如有一排房子,共 n 个,每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。

当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。每个房子粉刷成不同颜色的花费是以一个 n x 3 的正整数矩阵 costs 来表示的。

例如,costs[0][0] 表示第 0 号房子粉刷成红色的成本花费;costs[1][2] 表示第 1 号房子粉刷成绿色的花费,以此类推。

请计算出粉刷完所有房子最少的花费成本。

示例 1:

输入: costs = [[17,2,17],[16,16,5],[14,3,19]]
输出: 10
解释: 将 0 号房子粉刷成蓝色,1 号房子粉刷成绿色,2 号房子粉刷成蓝色。
     最少花费: 2 + 5 + 3 = 10。
示例 2:

输入: costs = [[7,6,2]]
输出: 2

class Solution {
    public int minCost(int[][] costs) {
        int[][] dp = new int[costs.length][3];
        dp[0][0] = costs[0][0];
        dp[0][1] = costs[0][1];
        dp[0][2] = costs[0][2];
        for (int i = 1; i < costs.length; i++) {
            dp[i][0] = Math.min(dp[i - 1][1], dp[i - 1][2]) + costs[i][0];
            dp[i][1] = Math.min(dp[i - 1][0], dp[i - 1][2]) + costs[i][1];
            dp[i][2] = Math.min(dp[i - 1][0], dp[i - 1][1]) + costs[i][2];
        }
        return Math.min(Math.min(dp[costs.length - 1][0], dp[costs.length - 1][1]), dp[costs.length - 1][2]);
    }
}

1.dp

有 k 种颜色的涂料和一个包含 n 个栅栏柱的栅栏,请你按下述规则为栅栏设计涂色方案:

每个栅栏柱可以用其中 一种 颜色进行上色。
相邻的栅栏柱 最多连续两个 颜色相同。
给你两个整数 k 和 n ,返回所有有效的涂色 方案数 。

class Solution {
    public int numWays(int n, int k) {
        int[][] dp = new int[n][2];
        dp[0][0] = 0;
        dp[0][1] = k;
        for (int i = 1; i < n; i++) {
            dp[i][0] = dp[i - 1][1];
            dp[i][1] = dp[i - 1][0] * (k - 1) + dp[i - 1][1] * (k - 1);
        }
        return dp[n - 1][0] + dp[n - 1][1];
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 历届蓝桥杯单片机国赛题目的pdf文件包含了多年来比赛的题目,对于参赛者来说非常有价值。这些题目主要涉及单片机的应用,包括各种实际问题的解决方案设计和实现。 蓝桥杯单片机国赛的题目非常好,具有一定的难度和挑战性。在这些题目中,可以看出组织者对参赛者的考察点,如编程基础、算法设计、电路原理和PCB设计等方面的能力要求。 这些题目的难度和要求因年份而异。一些题目可能要求参赛者按照给定的要求,设计和实现具体的功能,比如控制器的编程和接口的设计。还有一些题目则更注重算法的设计和优化,要求参赛者解决一些实际问题,如传感器数据采集和处理、自动控制系统设计等。 参赛者可以通过阅读历届蓝桥杯单片机国赛题目的pdf,了解以往比赛的题目类型和要求。同时,可以从中学习其他选手的优秀作品,借鉴他们的思路和方法,不断提高自己的编程水平和解决问题的能力。 总的来说,历届蓝桥杯单片机国赛题目pdf是参赛者备战比赛的重要资料,通过认真研读和思考这些题目,可以帮助参赛者更好地了解比赛的要求和考察点,为自己的比赛表现做好准备。同时,也可以通过学习其他选手的优秀作品,借鉴他们的经验和方法,提升自己的编程和设计能力。 ### 回答2: 历届蓝桥杯单片机国赛题目pdf经过多年的发展和举办,已经形成了一套完整的题库。这些pdf文件收录了每年蓝桥杯单片机国赛的题目,包括初赛和决赛的所有题目。通过这些pdf文件,参赛选手可以了解到历年比赛中的难度和类型,为他们的备战提供了很好的参考。 每年的比赛题目都由蓝桥杯组委会精心设计,力求在知识点的全面性和难度上有所考量。题目内容通常包括单片机基础知识、电路设计、编程能力等方面的要求。比赛题目除了要求选手具备一定的硬件和软件实验能力外,还要求选手具备良好的分析和解决问题的能力。 通过历届蓝桥杯单片机国赛题目pdf的学习,可以帮助选手更好地了解比赛要求,熟悉比赛形式和题型,提高应对复杂问题的能力。同时,这些题目也对教育者具有一定的参考价值,可以作为培训学生的教材和示例。 总之,历届蓝桥杯单片机国赛题目pdf对于参赛选手和教育者来说都是非常有价值的资源。通过对这些题目的学习和分析,可以更好地为比赛做好准备,并提高自身的技能水平。希望未来蓝桥杯单片机国赛题目pdf会进一步完善,为单片机爱好者提供更好更全面的支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海边的彩虹与你

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值