JAVA 蓝桥杯记录

原始文档(NOTION同步更新):https://zesty-vacation-495.notion.site/JAVA-aa608e3f7ade40bda7ee1bd6ee7da658?pvs=4

前言:

JAVA相比于C++,内置库的功能更为强大,可以有很多方便的方法,比如流式操作,大数,日期函数等。自己参加只拿了安慰奖省三,认清自己对算法没有天赋而且不感兴趣,蓝桥杯更多感觉是多刷题,多培养自己的思维,很少能见到模版题。文章记录自己的学习经历。

比赛提供的软件是Eclipse,Eclipse有自动纠错和提醒功能,补全建议改为TAB键,默认的是空格键,十分影响操作;自动提醒需要手动开。比赛最好也熟悉Eclipse的调试。

Eclipse如何设置自动提示?_eclipse提示设置-CSDN博客

文章介绍内容:

一、JAVA独特强大可使用的内置库(大数、可变字符串、日期、数组、动态数组、SET集合、TreeMap二叉树、哈希表、队列、集合、优先队列、流式操作)

仅介绍常用方法,更加深刻更加具体可以自行GPT。

二、常见算法的模板

算法是学习“董晓算法”(B站老师)的,他的视频有模拟过程,有图解,理解过程十分清晰。题主补充Java的版本。

第二部分单独开一页。

———————————————————————————————————————————

一、JAVA内置的库,逃课方法:

1.1、流式操作.stream()

1.1 :常用方面:字符串列表排序、列表寻找最值、计算列表元素个数、转换大写字母、列表求和求积、去重、二维数组快速打印、列表排序等。

常用的方法代码如下:

import java.util.*;

public class StringLengthSortExample {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("apple", "pear", "banana", "cherry", "fig");

        // 按字符串长度排序(从小到大)
        List<String> sortedWords = words.stream() //words.stream就是使用word字符串列表的流式操作
                .sorted(Comparator.comparingInt(String::length))
                .collect(Collectors.toList());

        System.out.println(sortedWords); // 输出:[fig, pear, apple, banana, cherry]

        // 找到最大值
        Optional<Integer> maxNumber = numbers.stream().max(Comparator.naturalOrder());
        maxNumber.ifPresent(max -> System.out.println("最大值: " + max)); // 输出:最大值: 9
				
				//计算元素个数
				long count = numbers.stream() // 将列表转换为流
                             .filter(n -> n > 6) // 筛选出大于6的元素
                             .count(); // 计算经过筛选的元素数量
				System.out.println(count);

				//转换大写、元素全+3
				String[] strArr = { "abcd", "bcdd", "defde", "fTr" };
				List<String> strList = Arrays.stream(strArr).map(String::toUpperCase).collect(Collectors.toList());

				List<Integer> intList = Arrays.asList(1, 3, 5, 7, 9, 11);
				List<Integer> intListNew = intList.stream().map(x -> x + 3).collect(Collectors.toList());

				System.out.println("每个元素大写:" + strList);
				System.out.println("每个元素+3:" + intListNew);
				
				//求和求积
				Optional<Integer> sum = list.stream().reduce((x, y) -> x + y);
				Optional<Integer> product = list.stream().reduce((x, y) -> x * y);
				int sum = a.stream().reduce((x, y) -> x + y).orElse(0);
    	System.out.println(sum);

				//去重
					List<String> newList = Stream.concat(stream1, stream2).distinct().collect(Collectors.toList());
					
				//二维数组打印   				
 				Arrays.stream(dis)
              .map(row -> Arrays.toString(row))
              .forEach(System.out::println);
}
}J

结果可以保存到另一个数组,具体方法咨询GPT。

流式操作进阶教程可以参考:

【java基础】吐血总结Stream流操作_java stream流操作-CSDN博客

1.2 常用库 建议统一用java.util.*导入包

1.2.1 大数 BigInteger 适用于超出INT类型的值

import java.math.Biginteger; //导入包

//最后结果中,a的值不会更新
BigInteger a = new BigInteger("123"); //新建Binginteger的对象
BigInteger b = new BigInteger(str);
System.out.println(a.add(b));

//进制转换
String string1 = new BigInteger("20", 10).toString(2);
System.out.println("十进制的20转换成二进制是:"+string1);

/* 常用方法
.add	.subtract	.multiply	.division	.remainder(求余) */

1.2.2 可变字符串 StringBuilder

StingBuilder sb = new StringBuilder(); //新建对象
String result = sb.toString(); //转成STRING类
int num = Integer.parseInt(str)  //转成整数

/* 常用方法
.append(””) 追加	.insert(5,””) 插入	.replace(5,11,””) 替换	.delete(5,9) 删除没有改变a没有改变a	.reverse(); 反转
.indexOf(String str) 返回子串位置	.length();	.charAt(int index)	.equals(str2)==只是比较内存地址	.substring(1,3)截断从1到3(不包括3) */

1.2.3 日期 LocalDateTime

import java.time //导入包
import java.time.format.DateTimeFormatter; //导入日期格式的包,需要单独导入,time.*并不能导入format包

LocalDateTime date = LocalDateTime.of(2000,1,1,0,0,0); 
//新建对象


DateTimeFormatter formats = DateTimeFormatter.ofPattern(”yyyy-MMdd-HHmmss”);
String str = date.format(formats)
//按格式导出为字符串
//注意:MM为月份,mm为分钟,HH为24小时制,hh为12小时制


String dateString = "20230123102030";(20230102因为没有保存小时那些,导致抛出异常)
DateTimeFormatter input = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
LocalDate date = LocalDate.parse(dateString, formatter);

//获取几号、星期几
int dayOfMonth = localDateTime.getDayOfMonth(); // 当月的日期,1 到 31
DayOfWeek dayOfWeek = localDateTime.getDayOfWeek(); // 星期几

//字符串转成日期

/*常用方法
获取时间日期:
int year = currentDateTime.getYear();	
.getDayOfMonth() / .getMonth / .getYear  
.getHour() / .getMinute / . getSecond();

加上减去特定时间:负数减去时间
LocalDateTime futureDateTime = currentDateTime.plusDays(1);	
.plusYears() / .plusMonths / .plusDays
.plusHours() / .plusMinutes / . plusSeconds()

判断是否在日期前:
boolean isAfter = currentDateTime.isAfter(targetDateTime);	
.isAfter / .isBefore
*/

相关题目代码:

//输入毫秒,输出从1970年1月1日的时间相加后的日期
import java.util.*;
import java.time.*;
import java.time.format.*;

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        long add = scan.nextLong();
        LocalDateTime date = LocalDateTime.of(1970, 1, 1, 0, 0, 0);
        LocalDateTime res = date.plusSeconds(add / 1000); // 将毫秒转换为秒并添加到日期时间中
        DateTimeFormatter formats = DateTimeFormatter.ofPattern("HH:mm:ss");
        String str = res.format(formats);
        System.out.println(str);
    }
}

1.2.4 数组 Array

import java.util.Arrays; //导入包

// 数组排序(升序)
Arrays.sort(numbers);
// 使用 Collections.reverseOrder() 获取降序排序的比较器
import java.util.Collections; // 导入 Collections 类
Arrays.sort(numbers, Collections.reverseOrder());

// 数组复制
int[] copy = Arrays.copyOf(numbers, numbers.length);

// 数组填充
Arrays.fill(numbers, 0);  // 将整个数组填充为0

// 检查数组相等性
boolean isEqual = Arrays.equals(numbers, copy);

// 数组转换为字符串输出
String arrayAsString = Arrays.toString(numbers);
System.out.println("Array: " + arrayAsString);

// .binarySearch() 二分查找,需有序

1.2.5 动态数组 ArrayList        

import java.util.ArrayList; //导入包

 // 创建一个整数型的二维 ArrayList
        ArrayList<ArrayList<Integer>> twoDArrayList = new ArrayList<>();
        
        // 创建第一行并添加元素
        ArrayList<Integer> row1 = new ArrayList<>();
        row1.add(10);
        row1.add(20);
        row1.add(30);

        // 将第一行添加到二维 ArrayList
        twoDArrayList.add(row1);
				// 获取二维 ArrayList 中的元素
        int element = twoDArrayList.get(1).get(2);
        System.out.println("二维 ArrayList 中的元素是:" + element);

/* 
.add(E element) 末尾添加	        .get(int index) 获取	
.set(int index,E element) 替换	.remove 删除
.clear() 清空	                .contains(E) 是否包含【返回true false】	
.isEmpty() 是否为空	            .indexOf(E) 返回出现的第一个位置 */

//注意如果是用自定义的数据类型来构建二维数组,例如图论中,一定要先初始化,否则容易报错

//构建二维列表,Edge包含w和v整数变量
static ArrayList<ArrayList<Edge>> e = new ArrayList<>();

//初始化edge结构体,避免空指针异常
for (int i = 0; i <= n; i++) {
     e.add(new ArrayList<>());
}

//添加元素
e.get(a).add(new Edge(b, c));
e.get(b).add(new Edge(a, c));

//二维数组打印   				
Arrays.stream(dis)
      .map(row -> Arrays.toString(row))
      .forEach(System.out::println);

1.2.6 队列 LinkedList

import java.util.LinkedList;
import java.util.Queue;

public class QueueExample {
    public static void main(String[] args) {
        Queue<String> queue = new LinkedList<>();

        // 添加元素到队列
        queue.offer("Apple");
        queue.offer("Banana");
        queue.offer("Orange");

        // 从队列移除并返回头部元素
        String head = queue.poll();
        System.out.println("Removed element: " + head);

        // 获取但不移除头部元素
        String peekedElement = queue.peek();
        System.out.println("Peeked element: " + peekedElement);

        // 遍历队列并输出所有元素
        System.out.println("All elements in the queue:");
        for (String element : queue) {
            System.out.println(element);
        }
    }
}

/* 
.addFirst(E) 开头添加	
.addLast(E) / .offer() 末端添加
.add(int index,E)指定添加
.removeFirst() 删除第一个
.removeLast()
.remove(int index)
.poll() .pollFirst() .pollLast 弹出元素 */

1.2.7 SET集合(即不包含重复元素)

import java.util;

Set<String> hashSet = new HashSet<>();

/*
1. **`HashSet`**:基于哈希表实现,是最常用的`Set`实现类。它不保证集合的迭代顺序;尤其是它不保证该顺序恒久不变。此实现为基本操作(添加、删除、包含和大小确定)提供了稳定的性能,时间复杂度大致为O(1)。
2. **`LinkedHashSet`**:是`HashSet`的一个子类,内部使用链表维护元素的插入顺序。因此,迭代访问`Set`时,结果是按照元素插入的顺序进行的。性能略低于`HashSet`,但在迭代访问整个集合时有更好的性能。
3. **`TreeSet`**:基于红黑树(一种自平衡的二叉查找树)实现。元素会按照自然顺序进行排序,或者根据创建`TreeSet`时提供的`Comparator`进行排序。`TreeSet`支持有序集合相关的操作,如`first`、`last`、`headSet`、`tailSet`等。

.add(E e)	.remove(O)	.contains(o)	.size()	.isEmpty() */

1.2.8 哈希表 HashMap

import java.util.HashMap;

public class HashMapExample {
    public static void main(String[] args) {
        // 创建一个 HashMap 对象
        HashMap<String, Integer> hashMap = new HashMap<>();

        // 插入元素.put也可以替换元素
        hashMap.put("apple", 3);
        hashMap.put("banana", 2);
        hashMap.put("orange", 5);

        // 查找元素
        System.out.println("Value for key 'apple': " + hashMap.get("apple")); // 输出:Value for key 'apple': 3

        // 删除元素
        int removedValue = hashMap.remove("banana");
        System.out.println("Removed value for key 'banana': " + removedValue); // 输出:Removed value for key 'banana': 2

        // 遍历输出所有键值对
        System.out.println("All key-value pairs:");
        for (String key : hashMap.keySet()) {
            System.out.println(key + ": " + hashMap.get(key));
        }
    }
}

/* .keySet() 返回键集合	.values()	.put(key,value) 添加	
.remove(key) 	.containsKey	.containsValue */

1.3 进阶模板

1.3.1 线段树

董晓老师的讲解:C02【模板】线段树+懒标记 Luogu P3372 线段树 1_哔哩哔哩_bilibilij

1.3.1.1 区间和+懒标记模板
package main;

import java.util.*;

public class Main {
    static Node[] tr = new Node[1<<20];
    static int[] w = new int[1<<20];
    
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int m = scan.nextInt();
        for (int i=1;i<=n;i++){
            w[i] = scan.nextInt();
        }
        build(1,1,n);
        
        int op,x,y,k;
        while(m-->0){
            op = scan.nextInt();
            x = scan.nextInt();
            y = scan.nextInt();
            if (op == 2)
                System.out.println(query(1,x,y));
            else{
                k = scan.nextInt(); 
                change(1,x,y,k);
            }
        }
    }
    
    //建立函数 p节点 l、r左右边界
    
    public static void build(int p, int l, int r){
        tr[p] = new Node(l, r, w[l], 0); //w[l]一般无所谓,在后续更新中会替换掉
        if (l == r) return; //到达叶节点返回(即[5,5]这种,此时[5,5]=w[l]=5;
        int m = (l + r) >> 1;
        build(p << 1, l, m); //裂左裂右
        build(p << 1 | 1, m + 1, r);
        pushup(p);
    }
    
    //向上更新
    public static void pushup(int p){
    	//父节点的区间和 = 两个儿子的区间和 的和
        tr[p].sum = tr[p << 1].sum + tr[p << 1 | 1].sum;
    }
    
    //向下更新
    public static void pushdown(int p){
        if (tr[p].add != 0) { //有懒标记
            tr[p << 1].sum += tr[p].add * (tr[p << 1].r - tr[p << 1].l + 1); 
            tr[p << 1 | 1].sum += tr[p].add * (tr[p << 1 | 1].r - tr[p << 1 | 1].l + 1);
          //左儿子节点更新后的区间和 = 懒标记 * 左儿子节点的区间长度
            tr[p << 1].add += tr[p].add;
            tr[p << 1 | 1].add += tr[p].add;
            //把 父节点的蓝标记 累加到 左儿子的节点懒标记上
            tr[p].add = 0;
        }
    }
    
    //点修改 根节点p进入
    public static void update(int p, int x, int y, int k){
        if (x <= tr[p].l && tr[p].r <= y){
            tr[p].sum += (tr[p].r - tr[p].l + 1) * k;
            tr[p].add += k;
            return;
        }
        //完全覆盖区间则直接 该节点的区间和 = 区间长度 * 单个元素增加值 
        //对应懒标记 = 单个元素增加值
        //否则裂开递归到儿子节点中
        int m = tr[p].l + tr[p].r >> 1;
        pushdown(p);
        if (x <= m) update(p << 1, x, y, k);
        if (y > m) update(p << 1 | 1, x, y, k);
        pushup(p);
    }
    
    //区间查询,
    public static int query(int q, int x, int y){
        if (x <= tr[q].l && tr[q].r <= y)
            return tr[q].sum;
        //完全覆盖直接返回区间和
        //否则裂开左右两边求和
        int m = tr[q].l + tr[q].r >> 1;
        pushdown(q);
        int sum = 0;
        if (x <= m) sum += query(q << 1, x, y);
        if (y > m) sum += query(q << 1 | 1, x, y);
        return sum;
    }
    
    
    public static void change(int u, int l, int r, int k){
        if (tr[u] == null || l > tr[u].r || r < tr[u].l) {
            return;
        } //边界判断,查询区间超出线段树区间,避免空指针异常
        if (l <= tr[u].l && tr[u].r <= r){ //覆盖区间则直接修改
            tr[u].sum += (tr[u].r - tr[u].l + 1) * k;
            tr[u].add += k;
            return;
        }
        pushdown(u);
        change(u << 1, l, r, k);
        change(u << 1 | 1, l, r, k);
        pushup(u);
    }

    
    static class Node{
        int l, r, sum, add;
        public Node(int l, int r, int sum, int add){
            this.l = l;
            this.r = r;
            this.sum = sum;
            this.add = add;
        }
    }
}

1.3.1.2 区间GCD + 二分

import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Scanner;

public class Main {
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
static int N = 100010;
static Node[] tr = new Node[N * 4];
static int[] a = new int[N];

public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    int f = 0;
    for (int i = 1; i <= n; ++i) {
        a[i] = sc.nextInt();
        if (a[i] == 1) f++;
    }
    if (f != 0) {
        out.println(n - f);
        out.flush();
        return;
    }
    build(1, 1, n);
    if (query(1, 1, n) != 1) {
        out.println(-1);
        out.flush();
        return;
    }
    int ans = 0x3f3f3f3f;
    for (int i = 1; i <= n; ++i) {
        int l = i + 1, r = n + 1;
        while (l < r) {
            int mid = l + r >> 1;
            if (query(1, i, mid) == 1) r = mid;
            else l = mid + 1;
        }
        if (query(1, i, r) == 1) ans = Math.min(ans, r - i);
    }
    out.println(n - 1 + ans);
    out.flush();
}

static int gcd(int a,int b){
    return b == 0 ? a:gcd(b,a%b);
}

static void pushup(int u) {
    tr[u].g = gcd(tr[u << 1].g, tr[u << 1 | 1].g);
}

static void build(int u, int l, int r) {
    if (l == r) tr[u] = new Node(l, r, a[r]);	TR1:1 3 0	TR2 :
l=1 mid=2 u
    else {
        tr[u] = new Node(l, r, 0);
        int mid = l + r >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }
}

static int query(int u, int l, int r) {
    if (tr[u].l >= l && tr[u].r <= r) return tr[u].g;
    int mid = tr[u].l + tr[u].r >> 1;
    if (r <= mid) return query(u << 1, l, r);
    else if (l > mid) return query(u << 1 | 1, l, r);
    else return gcd(query(u << 1, l, r), query(u << 1 | 1, l, r));
}

static class Node {
    int l, r, g;

    public Node(int l, int r, int g) {
        this.l = l;
        this.r = r;
        this.g = g;
    }
}
}

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值