【笔试强训】Week5:空调遥控, kotor和气球,走迷宫,主持人调度II,体操队形,二叉树的最大路径和,排序子序列,消减整数

文章目录

1. 空调遥控

空调遥控

题目描述

解题思路

解法一:滑动窗口

时间复杂度:O(n * lonn) + O(n)

把数组排序,维护一个窗口,保证max-min<=2p,统计窗口长度,返回最大值

解法二:二分查找

时间复杂度:O(n * lonn ) + O(n * lonn )

把数组排序,枚举每一个温度,通过二分查找,分别找到arr[i]-parr[i]+p对应的下标,计算这个区间内人数总和,返回最大值即可

代码实现

java 复制代码
import java.util.*;
import java.io.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static Read in = new Read();
    static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

    public static void main(String[] args) throws IOException{
        int n = in.nextInt();
        int p = in.nextInt();

        long[] arr = new long[n];
        for(int i= 0;i<n;i++)
            arr[i] = in.nextLong();
        Arrays.sort(arr);
        
        int left = 0;
        int right = 0;
        int ret = 0;
        
        while(right<n){
            while(left<=right && (arr[right]-arr[left])>2*p)
                left++;
            ret = Math.max(right-left+1,ret);
            right++;
        }
        System.out.println(ret);
        out.close();
    }
}



class Read{
    StringTokenizer st = new StringTokenizer("");
    BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

    String next() throws IOException{
        while(!st.hasMoreTokens()){
            st = new StringTokenizer(bf.readLine());
        }
        return st.nextToken();
    }

    int nextInt() throws IOException{
        return Integer.parseInt(next());
    }

    long nextLong() throws IOException{
        return Long.parseLong(next());
    }

}

2. kotori和气球

kotori和气球

题目描述

解题思路

排列组合

第一个位置n种选择,其余位置n-1种选择

代码实现

java 复制代码
import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        
        int n = in.nextInt();
        int m = in.nextInt();
        int ans = n;
        for(int i = 1;i<m;i++){
            ans=ans*(n-1)%109;
        }
        System.out.println(ans);
    }
}

3. 走迷宫

走迷宫

题目描述

解题思路

最短路径 --》 BFS

注意: 下标从1开始,字符串要先前置一个" " 再填写到grid中

代码实现

java 复制代码
import java.util.*;
import java.io.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static Read in = new Read();
    public static void main(String[] args) throws IOException {
        int n = in.nextInt();
        int m = in.nextInt();
        int xs = in.nextInt();
        int ys = in.nextInt();
        int xt = in.nextInt();
        int yt = in.nextInt();
        int[] dx = {0, 0, 1, -1};
        int[] dy = {1, -1, 0, 0};

        if (xs == xt && ys == yt) {
            System.out.println(0);
            return;
        }

        boolean[][] check = new boolean[n + 1][m + 1];
        char[][] grid = new char[n + 1][m + 1];

        for (int i = 1; i <= n; i++) {
            String str = in.next();
            str = " "+str;
            grid[i] = str.toCharArray();
        }

        int ans = 0;
        Queue<int[]> queue = new LinkedList<>();
        queue.add(new int[] {xs, ys});
        check[xs][ys] = true;

        while (!queue.isEmpty()) {
            ans++;
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                int[] top = queue.poll();
                for (int k = 0; k < 4; k++) {
                    int x = dx[k] + top[0];
                    int y = dy[k] + top[1];
                    if (x > 0 && x <= n && y > 0 && y <= m && !check[x][y] && grid[x][y] == '.') {
                        if (x == xt && y == yt){
                            System.out.println(ans);
                            return ;
                        }
                        queue.add(new int[] {x, y});
                        check[x][y] = true;
                    }
                }
            }
        }
        System.out.println(-1);
    }

}

class Read {
    StringTokenizer st = new StringTokenizer("");
    BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

    String next() throws IOException {
        while (!st.hasMoreTokens()) {
            st = new StringTokenizer(bf.readLine());
        }
        return st.nextToken();
    }

    int nextInt() throws IOException {
        return Integer.parseInt(next());
    }

    long nextLong() throws IOException {
        return Long.parseLong(next());
    }

}

4. 主持人调度II

主持人调度II

题目描述

解题思路

  1. 把所有数组按照第一个元素排序
  2. 创建一个列表,表示已分配的数组。
  3. 放入第一个数组,接着遍历数组,如果可以与已分配的数组时间错开,就可以继续排在后面。如果与所有已分配的数组都重合,就再添加一个子列表
  4. 结果就是列表的长度

优化:

  1. 子列表中不需要存放放已分配好的数组的右端点的最大值
  2. 每次遍历列表时间复杂度太高,可以把列表设置成小根堆,每次与堆顶元素比较即可

代码实现

java 复制代码
public int minmumNumberOfHost (int n, int[][] startEnd) {
        // write code here
        Arrays.sort(startEnd, (a, b)->Integer.compare(a[0], b[0]));
        PriorityQueue<Integer> heap = new PriorityQueue<>();
        heap.add(startEnd[0][1]);

        for (int i = 1; i < n; i++) {
            int top = heap.peek();
            if(startEnd[i][0] >= top){
                heap.poll();
                heap.add(startEnd[i][1]);
            }else
                heap.add(startEnd[i][1]);

        }
        return heap.size();

    }

5. 体操队形

体操队形

题目描述

解题思路

DFS + 枚举

通过决策树来枚举所有情况,剪枝不合法的情况:

  1. 通过vis数组记录每个数字是否被使用过
  2. 以下面为例,2要求排在1前面,当1已经排队,2还没排队,所有情况都不可能成立,所以1先排队的情况都要剪枝。

代码实现

java 复制代码
import java.util.*;

public class Main{
    static boolean[] vis;
    static int[] arr;
    static int n = 0;
    static int ret = 0;
    
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        n = in.nextInt();
        arr = new int[n+1];
        vis = new boolean[n+1];
        for(int i = 1;i<=n;i++){
            arr[i] = in.nextInt();
        }        
        
        dfs(1);
        System.out.println(ret);
    }
    
    static void dfs(int pos){
        if(pos==n+1){
            ret++;
            return;
        }
        
        for(int i = 1;i<=n;i++){
            if(!vis[i] && (arr[i]==i || !vis[arr[i]])){
                vis[i] = true;
                dfs(pos+1);
                vis[i] = false;
            }
        }
    }
}

6. 二叉树的最大路径和

二叉树的最大路径和

题目描述

解题思路

树形dp + DFS

  • 在某个子树上整合的信息:经过根节点的最大路径和
  • 左子树:返回以左孩子为根节点的最大单链路径和,如果最大和是负数,可以直接舍弃
    • left = Math.max(0,dfs(root.left))
  • 右子树:返回以右孩子为根节点的最大单链路径和

因为最终的统计如果要包含根节点,所以左右子树的路径必须是单链,再拼接上根节点,才能得到以经过根节点的最大路径和。

每次得到的路径和中取最大值,是最终的结果.

代码实现

java 复制代码
import java.util.*;
public class Solution {
     int ret = -1010;
    public int maxPathSum (TreeNode root) {
        // write code here
        dfs(root);
        return ret;
    }

    int dfs(TreeNode root){
        if(root==null)
            return 0;

        int left = Math.max(0,dfs(root.left));
        int right = Math.max(0,dfs(root.right));

        ret = Math.max(ret,left+right+root.val);
        return Math.max(left,right)+root.val;
    }
}

7. 排序子序列

排序子序列

题目描述

解题思路

贪心+模拟

定义一个指针,先判断当前是上升或者下降,如果是上升,就让指针一直向后移动到波峰,下降同理,指针不再移动时统计结果。

如果当前阶段是水平,只移动指针,不统计结果,让这段水平区域与后面上升或下降的部分连到一起

代码实现

java 复制代码
import java.util.*;
import java.io.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) throws IOException {
        Read in = new Read();
        int n = in.nextInt();
        int[] arr = new int[n];
        for(int i= 0;i<n;i++){
            arr[i] = in.nextInt();
        }

        int ret = 0;
        int i = 0;
        while(i<n){
            if(i==n-1){
                ret++;
                break;
            }
            if(arr[i]<arr[i+1]){
                while(i<n-1 && arr[i]<=arr[i+1])
                    i++;
                ret++;
            }else if(arr[i]>arr[i+1]){
                while(i<n-1 && arr[i]>=arr[i+1])
                    i++;
                ret++;
            }else{
                 while(i<n-1 && arr[i]==arr[i+1])
                    i++;
            }
            i++;
        }
        System.out.println(ret);
    }
}
class Read {
    StringTokenizer st = new StringTokenizer("");
    BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

    String next() throws IOException {
        while (!st.hasMoreTokens()) {
            st = new StringTokenizer(bf.readLine());
        }
        return st.nextToken();
    }

    int nextInt() throws IOException {
        return Integer.parseInt(next());
    }

    long nextLong() throws IOException {
        return Long.parseLong(next());
    }

}

8. 消减整数

消减整数

题目描述

解题思路

贪心

每次尽可能减去之前数的两倍:假设x-a得到y,如果y%2a==0,说明y可以一直-2a得到0;否则就-a

代码实现

java 复制代码
import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        int t = in.nextInt();
        while(t>0){
            int h = in.nextInt();
            h-=1;
            int a = 1;
            int ans = 1;
            while(h>0){
                if(h%(2*a)==0){
                    h-=2*a;
                    a*=2;
                }else
                    h-=a;
                ans++;
            }
            System.out.println(ans);
            t--;
        }
    }
}
相关推荐
郑重其事,鹏程万里1 小时前
表达式计算器(mvel2)
java
其实防守也摸鱼1 小时前
软件安全与漏洞--软件安全编码
java·前端·网络·安全·网络安全·web·工具
888CC++2 小时前
栈上分配 VS 堆分配 核心区别
java·开发语言·jvm
艾利克斯冰2 小时前
Java面试题汇总
java
我是一颗柠檬2 小时前
【JavaSE全面教学】Java集合框架下Day13(2026年)
java·开发语言·intellij-idea
吃好睡好便好2 小时前
用if…end…语句计算分段函数
开发语言·人工智能·学习·算法·matlab
vx-程序开发2 小时前
基于机器学习的动漫可视化系统的设计与实现-计算机毕业设计源码08339
java·c++·spring boot·python·spring·django·php
灰灰勇闯IT2 小时前
ops-memory:CANN Runtime 的 Tensor 内存管理
算法
叶子Talk3 小时前
OpenAI破解80年数学猜想,AI首次做出原创证明
人工智能·数学·算法·机器学习·ai·openai·ai推理