本文正在参加「Java主题月 - Java 刷题打卡」,详情查看 活动链接
1.题目描述
某涉密单位下发了某种票据,并要在年终全部收回。
每张票据有唯一的ID号。全年所有票据的ID号是连续的,但ID的开始数码是随机选定的。
因为工作人员疏忽,在录入ID号的时候发生了一处错误,造成了某个ID断号,另外一个ID重号。
你的任务是通过编程,找出断号的ID和重号的ID。
假设断号不可能发生在最大和最小号。
要求程序首先输入一个整数N(N<100)表示后面数据行数。 接着读入N行数据。 每行数据长度不等,是用空格分开的若干个(不大于100个)正整数(不大于100000) 每个整数代表一个ID号。
要求程序输出1行,含两个整数m n,用空格分隔。 其中,m表示断号ID,n表示重号ID
例如: 用户输入: 2 5 6 8 11 9 10 12 9
则程序输出: 7 9
再例如: 用户输入: 6 164 178 108 109 180 155 141 159 104 182 179 118 137 184 115 124 125 129 168 196 172 189 127 107 112 192 103 131 133 169 158 128 102 110 148 139 157 140 195 197 185 152 135 106 123 173 122 136 174 191 145 116 151 143 175 120 161 134 162 190 149 138 142 146 199 126 165 156 153 193 144 166 170 121 171 132 101 194 187 188 113 130 176 154 177 120 117 150 114 183 186 181 100 163 160 167 147 198 111 119
则程序输出: 105 120
资源约定: 峰值内存消耗(含虚拟机) < 64M CPU消耗 < 2000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。 注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。 注意:主类的名字必须是:Main,否则按无效代码处理。
2.思路分析
这一题自己做的时候还是对java的集合运用不是很熟练,实际上这一题并没有很复杂,也没有涉及到算法层面的内容,只要思路清晰还是挺好做的。分析这一题,可能最先想到的都是用数组存储数据,但实际做的过程中可以发现要是用int型的数组的话数组的长度可变而且还需要多维数组,情况复杂,空间消耗大。 可以使用String型输入,再转化为集合的数据,通过集合的操作来实现排序,以及整体遍历寻找断点与重复值。
3.代码分析
刚开始借鉴别人代码然后实现这个排序同时找出相同值,通过对题目中的数据代入发现没有问题,但是再多试计几组数据后发现了问题。
排序找相同值
a.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
if (o1 - o2 == 0) {
arr[0]=o1;
return 0;
} else {
return o1-o2;
}
}
});
遍历寻找断点
int j=0;
int i=a.get(0);//获取a中下标为0的数字
for (;i<c.length+a.get(0);i++,j++){
if (i != a.get(j)) {
arr[1]=i;
break;
}
}
当输入为
2
1 2 2 3
4 5 7
发现并不能找到 6 这个断点值,找到的断点值是 3
然后通过调式(傻了,就是想不明白当时...)发现了在找到相同值2后,依然将数据加入了列表中,在后续的判断中,当标准值i加到3时,列表中原本是3的位置还是2,所以就判断成不相同,将3 存到了断点与相同值的数组中去了。
为了解决这个问题,我最开始想的是能不能在找到相同值后,不让这个数值加到列表中去,尝试了几下后就失败了,然后开始从判断条件上找方法,然后发现只要将比较是否相同的条件 if (i != a.get(j)) 中的不等于换成>=就可以了......
4.代码内容
public class Main {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
String s="";
int n=Integer.parseInt(scanner.nextLine());
int[] arr=new int[2];
ArrayList <Integer>a=new ArrayList<Integer>();
//输入字符串,以回车为一个回合结束的标志,将所有的回合输入的字符串连接到S中,
//每个回合之前已空格隔开
while (n != 0) {
String temp=scanner.nextLine();
s=s.concat(temp).concat(" ");
n--;
}
//以空格分割所有的数字字符串
String c[]=s.split(" ");
//将字符输入转化为数字列表
for(String m:c){
a.add(Integer.parseInt(m));
}
//此时的a列表中已经存入好了数字,将数字进行排序
a.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
if (o1 - o2 == 0) {
arr[0]=o1;
return 0;
} else {
return o1-o2;
}
}
});
int j=0;
int i=a.get(0);//获取a中下标为0的数字
for (;i<c.length+a.get(0);i++,j++){
if (i > a.get(j)) {
arr[1]=i;
break;
}
}
System.out.println(arr[1]+" "+arr[0]);
}
}
class Main{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
//输入行数
int n=Integer.parseInt(sc.nextLine());
//定义数组存放断点与重复值
int[] arr=new int[2];
//定义列表用于存放所有数字
ArrayList<Integer> a=new ArrayList<Integer>();
//以字符串的方式输入,方便控制空格换行等,行数的控制等
String ss="";
while (n != 0) {
String temp=sc.nextLine();
ss=ss.concat(temp).concat(" ");
//字符串的添加方法,行与行之间以空格相连,有助于将所有数字存入。
n--;
}
String[] s=ss.split(" ");//字符串方法将字符以空格为分割标志
for (String c : s) {
a.add(Integer.parseInt(c));//将数字字符串转换为数字存入列表
}
//将列表排序,同时找出相同的数字
Collections.sort(a);
//该循环用于查找断点,其中i从列表第一个数字开始,
//每次加一,j为列表下标,a.get(j)为列表的每一个值,
//当i与列表中的值不一致时,证明有断点
boolean b1=true,b2=true;
for (int i =0; i < a.size()-1; i++) {
if (a.get(i + 1) == a.get(i)&&b1) {
arr[0]=a.get(i);
b1=false;
}
if (a.get(i+1)-a.get(i)>1&&b2) {
arr[1]=a.get(i+1)-1;
b2=false;
}
if (!b1&&!b2)
break;
}
System.out.println(arr[1]+" "+arr[0]);
}
}
两个代码思路是一致,只是在最后的判断方法上有所改变。新人写博,如有不足请指出,必虚心改正...