【刷题册】2024.10.13 - 2024.10.15

目录

  • 一、2024.10.13
    • [1.1 BC153 [NOIP2010]数字统计](#1.1 BC153 [NOIP2010]数字统计)
    • [1.2 NC313 两个数组的交集](#1.2 NC313 两个数组的交集)
      • [1.2.1 思路一:暴力O(N^2)](#1.2.1 思路一:暴力O(N^2))
      • [1.2.2 思路二:hash](#1.2.2 思路二:hash)
    • [1.3 AB5 点击消除](#1.3 AB5 点击消除)
  • 二、2024.10.14
    • [2.1 BC64⽜⽜的快递](#2.1 BC64⽜⽜的快递)
    • [2.2 DP4 最⼩花费爬楼梯](#2.2 DP4 最⼩花费爬楼梯)
    • [2.3 数组中两个字符串的最⼩距离](#2.3 数组中两个字符串的最⼩距离)
  • 三、2024.10.15
    • [3.1 BC149 简写单词](#3.1 BC149 简写单词)
    • [3.2 dd爱框框](#3.2 dd爱框框)
    • [3.3 除2!](#3.3 除2!)

一、2024.10.13

1.1 BC153 [NOIP2010]数字统计

题目链接:BC153 [NOIP2010]数字统计

题目描述:

解题思路:

  • 枚举,直接循环对两数字之间的所有数拆分看每个数的含2个数。
  • 拆分方法:数字取余10,看个位数是否为2,然后让数字除10,直到数字小于0为止。

解题代码:

java 复制代码
public static void main(String[] args) {
        //输入
        Scanner in = new Scanner(System.in);
        int first = in.nextInt();
        int last = in.nextInt();

        int ret = 0;
        for(int i = first; i <= last; i++) {
            ret += count(i);
        }

        System.out.println(ret);
    }
    //记录数中2个数
    private static int count(int num) {
        int ret = 0;
        while(num > 0) {
            if(num % 10 == 2) ret++;
            num = num / 10;
        }
        return ret;
    }

1.2 NC313 两个数组的交集

题目链接:NC313 两个数组的交集

题目描述:

题目分析:就是找出两数组的相同元素,且结果数组中元素是不能重复的。

1.2.1 思路一:暴力O(N^2)

直接使用两层for循环,第一个for拿到nums1中的每一个数,与第二个中的所有元素进行比较,相同存入结果数组(注意结果数组中是否已经有了该数,如nums1 = {2,2},nums2 = {2,2})。

解题代码

java 复制代码
public ArrayList<Integer> intersection (ArrayList<Integer> nums1, ArrayList<Integer> nums2) {
        ArrayList<Integer> ret = new ArrayList<Integer>();
        for(int i = 0; i < nums1.size(); i++) {
            Integer cur = nums1.get(i);
            for( int j = 0; j < nums2.size(); j++) {
                if(cur.equals( nums2.get(j) )) {
                //注意排除已经有的值
                    if(!ret.contains(cur)) ret.add(cur);
                    break;
                }
            }
        }
        return ret;
    }

1.2.2 思路二:hash

将第一个数组存入hash表中,然后遍历第二个数组看hash表中是否有这个数。

但是由于数据范围是1000,是很小的,我们就不使用集合类HashMap,

直接使用一个布尔数组来表示,

  • 遍历nums1数组,将nums1数组中元素作为布尔数组中true值的下标,其余为false;
  • 在遍历nums2数组,看nums2数组中元素作为下标的布尔数组中只是不是true;
  • 是true就将该元素存入结果数组中,并将布尔数组置为false(防止重复数据)。
java 复制代码
public ArrayList<Integer> intersection (ArrayList<Integer> nums1, ArrayList<Integer> nums2) {
        boolean[] hash = new boolean[1010];
        ArrayList<Integer> ret = new ArrayList<Integer>();
        for(int i = 0; i < nums1.size(); i++) {
            hash[nums1.get(i)] = true;
        }
        for(int i = 0; i < nums2.size(); i++) {
            if(hash[nums2.get(i)]) {
                ret.add(nums2.get(i));
                hash[nums2.get(i)] = false;
            }
        }
        return ret;
}

1.3 AB5 点击消除

题目链接:AB5 点击消除

题目描述:

解题思路:

  • 我们使用栈来模拟操作,拿到一个字母就与栈顶元素比较,相同就出栈,不同就进栈。
  • 但是使用Stack类的话,我们最后拿到的栈顶到栈尾的,toString方法也不行。我们就使用StringBuilder来模拟实现。
java 复制代码
public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String str = in.next();
        
        StringBuilder ret = new StringBuilder("");
        for(int i = 0; i <str.length(); i++) {
            char ch = str.charAt(i);
            if(ret.length() != 0 && ch == ret.charAt(ret.length()-1) ) {
                //出栈
                ret.deleteCharAt(ret.length()-1);
            } else {
            	//进栈
                ret.append(str.charAt(i));
            }            
        }
        //注意判断栈是否为空
        System.out.println(ret.length() == 0? 0 : ret.toString());
    }

二、2024.10.14

2.1 BC64⽜⽜的快递

题目链接:BC64 ⽜⽜的快递

题目描述:

题目解析:一道小学数学题,只介绍对小数的处理:

  • 法1:直接调用Math类中的ceil()库方法向上取整;
  • 法2:使用a-(int)a与0进行比较,看是否有小数,有就结果加1。

代码:

java 复制代码
//法1:
public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        float a = in.nextFloat();
        char b = in.next().charAt(0);

        int ret = 20;
        if(b == 'y') ret += 5;

        if(a > 1.0) {
            ret = ret  - 1 + (int)Math.ceil(a);
        }

        System.out.println(ret);
}
//法二:
public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        //输入处理
        float a = in.nextFloat();
        String str = in.nextLine();
        char b = str.charAt(1);

        int ret = 20;
        //是否加急
        if(b == 'y') ret += 5;
        //是否超出1
        if(a > 1) {
            float temp = a - (int)a ;
            //是否有小数
            if(temp != 0.0) ret += 1;
            ret  = ret + (int)a - 1;
        }
        System.out.println(ret);
}

2.2 DP4 最⼩花费爬楼梯

题目链接:DP4 最⼩花费爬楼梯

题目描述:

题目分析:

这是一道简单的动态规划题目,看题目给出的实例终点是走出数组。

  • 动态方程 dp[i] = Math.min(dp[i-1] + cost[i-1] , dp[i-2] + cost[i-2]);

代码:

java 复制代码
import java.util.*;
class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] cost = new int[n];
        cost[0] = in.nextInt();
        int[] dp = new int[n+1];
        
        for(int i = 2; i <= n; i++) {
            cost[i-1] = in.nextInt();
            dp[i] = Math.min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2]);
        }
        System.out.println(dp[n]);
    }
}

2.3 数组中两个字符串的最⼩距离

链接找不到,下架了

题目描述:

题目解析:

题目给得很明确,在strs数组中找str1和str2之间的最小距离。

解题思路:

  • 法1:使用两层for循环,找到一个str1,就从当前开始找str2,如果结果ret更小,就更新。
  • 法2:对法1的优化,我们只需要使用两个变量flag0和flag1分别表示当前找到的str1和str2的位置,在找到一个str1或者str2的时候与最近的相减(也就是flag1-flag0的绝对值)再与结果ret比较,小就更新。
java 复制代码
import java.io.*;
public static void main(String[] args) throws IOException{
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
 int len = Integer.parseInt(reader.readLine());
 String[] strs = reader.readLine().split(" ");
 String str1 = strs[0], str2 = strs[1];
        String[] strs = new String[len];
        for(int i = 0; i < len; i++) strs[i] = in.next();

        int ret = 0x3f3f3f3f;

        int flag0 = 0;
        int flag1 = 0;
        for(int i = 2; i < len ; i++) {
            if(strs[i].equals(str1) ) {
                flag0 = i;
            }
            if(strs[i].equals(str2)) {
                flag1 = i;
            }
            if(ret == 0 || ret > Math.abs(flag1 - flag0)) ret =  Math.abs(flag1 - flag0);
        }
        if(flag0 == 0 || flag1 == 0) System.out.println(-1);
        else System.out.println(ret);
    }

三、2024.10.15

3.1 BC149 简写单词

题目链接:BC149 简写单词

题目描述:

简单题不用解析。

代码:

java 复制代码
import java.util.*;
class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while(in.hasNext()) {
            char ch = in.next().charAt(0);          
            System.out.print((ch <= 'z'&& ch >= 'a') ? (char)(ch - 32) : ch);
        }
    }
}

3.2 dd爱框框

题目链接:dd爱框框

题目描述:

题目解析:题目要求我们找出最小区间中的数组元素和大于等于x的左右下标值。

解题思路:

  1. 暴力解法:使用两层for循环,一层i代表左下标,第二层j循环从i下标开始去求右下标,找到最小区间长度即可,但是数组长度n的值很大,这样是会超时的。
  2. 对暴力解法优化,滑动窗口/同向双指针:
    2.1. 数组中的数据全是大于1的正数,证明当我们找到一个区间的数是大于x的时候left左指针向后走一位的时候,right--不会出现区间数组和变大的情况。
    2.2 直接使用Scannner由于数据量大,会出现超时,要使用自定义快读类

代码:

java 复制代码
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {
    public static void main(String[] args) throws IOException {
        Read in = new Read();
        int n = in.nextInt();
        int x = in.nextInt();
        int[] arr = new int[n+1];
        for(int i = 1; i <= n; i++) {
            arr[i] = in.nextInt();
        }
        
        int left = 1, right = 1,sum = 0;
        int retLeft = 0, retRight = 0, retLen = 0X3f3f3f3f;
        
        while(right <= n) {
            //进窗口
            sum += arr[right];
            
            //更新结果
            while(sum >= x) {
                if(retLen > right - left + 1) {
                    retLeft = left;
                    retRight = right;
                    retLen = retRight - retLeft + 1; 
                }
                //出窗口
                sum -= arr[left++];
            }
            
            right++;
        }
        System.out.println(retLeft + " " + retRight);
    }
}

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());
	}
}

3.3 除2!

题目链接:除2!

题目描述:

题目解析:这道题目就是给你最多k次让偶数除2操作,使最后数组元素和最小。

解题思路:

  • 因为是对偶数除2,并且要让最后数组和尽可能小,那么我们就可以使用大根堆来存储偶数
  • 注意k只是最多可以操作的次数,有可能最后数组中已经没有偶数,而k的次数还没执行完;
  • 我们先将给的数据和加起来,每出一次大根堆就减去,在判断除2后是不是还是偶数,是就进堆。

代码:

java 复制代码
import java.util.Scanner;
import java.util.PriorityQueue;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        long n = in.nextLong();
        int k = in.nextInt();
        
        PriorityQueue<Long> heap = new PriorityQueue<>((a,b) -> {
           return (int)(b - a); 
        });
        
        long sum = 0;
        while(in.hasNextLong()) {
            long temp = in.nextInt();
            sum += temp;
            if(temp % 2 == 0) {
                heap.add(temp);
            }
        }
        
        while(!heap.isEmpty() && k > 0) {
            long temp = heap.poll() / 2;
            sum -= temp;
            if(temp % 2 == 0) {
                heap.add(temp);
            }
            k--;
        }
        System.out.println(sum);
    }
}
相关推荐
Daniel 大东26 分钟前
BugJson因为json格式问题OOM怎么办
java·安全
不去幼儿园29 分钟前
【MARL】深入理解多智能体近端策略优化(MAPPO)算法与调参
人工智能·python·算法·机器学习·强化学习
Mr_Xuhhh31 分钟前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
盼海2 小时前
排序算法(五)--归并排序
数据结构·算法·排序算法
Theodore_10225 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
网易独家音乐人Mike Zhou5 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
冰帝海岸6 小时前
01-spring security认证笔记
java·笔记·spring
世间万物皆对象6 小时前
Spring Boot核心概念:日志管理
java·spring boot·单元测试
没书读了6 小时前
ssm框架-spring-spring声明式事务
java·数据库·spring
小二·7 小时前
java基础面试题笔记(基础篇)
java·笔记·python