第十届蓝桥杯 修改数组---并查集的简单应用--JAVA

第十届蓝桥杯 修改数组—并查集的简单应用–JAVA写法

题目

给定一个数组,数组中可能有重复的元素,现在要将其改为没有重复整数的数组。
修改方法:当修改第i个元素是,查看该元素之前是否出现过,如果出现过,会把第i个元素+1;如果还是重复继续+1。
输入格式:	第一行包含一个整数N
            第二行包含N个整数
  输出则把数组一次输出
  样例:5
        2 1 1 3 4
        输出:2 1 3 4 5

思路

一开始大部分人应该会想到递归,但是单纯的递归数据几百个可能就撑不住了,而这题的要求中数组元素最多会达到100000个
这题比较好的方法就是利用并查集,不过一般在考场上还是需要一定实力才能想到。没关系,编程就是慢慢积累经验的过程。

至于并查集建议大家看看csdn上其他大佬的详解(一定要看)

代码和讲解

大家捋不清楚的建议拿一组数据试一试
比如2 1 1 3 4,首先输出就是2,然后并查集使得数组元素f【2】本来的2,+1变成了3,也就是之后再碰到2会直接输出3。后面都是同理。一定要去看并查集的文章理解后再看代码。

public class Main6 {
第十届研究生组试题G 修改数组(并查集应用)
	static int[] f=new int[2000000];
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		//获取第一行数据
		int n=Integer.parseInt(sc.nextLine());
		int[] data=new int[n];
		
		//初始化f数组
		for (int i = 1; i < f.length; i++) {
			f[i]=i;
		}
		//获取第二行数据,放到数组中
		for (int i = 0; i < n; i++) {
			data[i]=sc.nextInt();
		}
		for (int i = 0; i < data.length; i++) {
			int k=find(data[i]);
			data[i]=k;
			f[data[i]]=find(data[i]+1);
		}
		for (int i = 0; i < data.length; i++) {
			System.out.print(data[i]+" ");
		}			
	}
	//(并查集)
	public static int find(int x) {
		if(x==f[x]) {
			return x;
		}else {
			f[x]=find(f[x]);
			return f[x];
		}
		
	
	}
	
	//以下是递归法,但是速度过慢,几十个数据就撑不住了
//	public static void fun(int k,ArrayList<Integer> list) {
//		for (int i=k; k < list.size(); k++) {
//			boolean boo=false;
//			for (int j = 0; j <i; j++) {		
//				if(list.get(i)==list.get(j)) {
//					list.set(i,list.get(i)+1);
//					boo=true;
//				}	
//			}
//			if(boo) {
//				fun(k, list);
//			}else {
//				k++;
//				fun(k, list);
//			}
//		}
//		
//	}
	
	
	
	
}
### 关于第十届蓝桥杯 Java A组 修改数组 类型题目 #### 解析与解答 在第十届蓝桥杯比赛中,Java A组确实存在一些涉及修改数组的题目。这类题目通常考察选手对数组操作的理解以及算法设计能力。以下是针对此类题目的分析和解决方案。 --- #### 题目描述 假设有一道典型的修改数组类型的题目如下: > 给定两个整数数组 `a` 和 `b`,其中 `a` 的长度为 `m`,`b` 的长度为 `n` (`m >= n`)。现在需要通过调整数组 `a` 中的部分元素使得对于每一个 `i` (`0 <= i < n`),满足条件 `a[i] >= b[i] + 3` 或者移除多余的元素来达到目标状态。求可以实现的目标的最大数量。 此问题可以通过双指针技术解决[^4]。 --- #### 实现代码 以下是一个基于上述逻辑的具体实现方案: ```java import java.util.ArrayList; import java.util.Collections; public class ModifyArray { public static void main(String[] args) { ArrayList<Integer> a = new ArrayList<>(); Collections.addAll(a, 7, 8, 9, 10); ArrayList<Integer> b = new ArrayList<>(); Collections.addAll(b, 2, 3); int m = a.size(); int n = b.size(); // 排序以便后续处理 Collections.sort(a); Collections.sort(b); long ans = 0; int l = -1, r = -1; for (int i = 0; i < a.size(); i++) { while (r + 1 < b.size() && a.get(i) >= b.get(r + 1) + 3) { r++; } while (l + 1 <= r && a.get(i) - (b.get(l + 1) + 3) > k) { // 假设k已定义 l++; } ans += r - l; } System.out.println(ans); } } ``` --- #### 思路详解 该程序的核心在于利用双指针技巧高效计算符合条件的数量。具体来说: -数组 `a` 和 `b` 进行排序以简化比较过程。 - 使用变量 `l` 和 `r` 来追踪当前窗口范围内的有效索引位置。 - 当前遍历到的 `a[i]` 如果能够覆盖更多的 `b[j]` 则扩展右边界;如果不再满足约束则收缩左边界。 --- #### 质数相关补充说明 虽然本题主要讨论的是修改数组的操作,但在同一赛事中也出现了质数相关的经典问题。例如,在寻找第2019个质数时采用的方法非常简洁明了[^3]。这种方法同样适用于其他类似的序列查找场景。 --- #### 字符串子串计数拓展 另外值得注意的是字符串的不同子串统计也是常见的考点之一。无论是通过嵌套循环还是集合去重的方式都可以有效地解决问题[^1][^2]。 --- ###
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值