萌新算法水平很弱,这题只得了30分(超时),请大佬们帮优化一下代码
,或者指点萌新一个高效的算法。谢谢
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner inputer = new Scanner(System.in);
//读数据
int diskCount = inputer.nextInt();//有的硬盘总数
int stripSize = inputer.nextInt();//一条中有几块
int avaliableDiskCount = inputer.nextInt();//可用的硬盘数量
//读取因盘中的信息
String[] datas = new String[avaliableDiskCount];
inputer.nextLine();//提前做处理
for( int x = 0 ; x < avaliableDiskCount ; x++) datas[x] = inputer.nextLine();//读入硬盘的数据
int outputCount = inputer.nextInt(); //输出的数量
int[] outputNum = new int[outputCount];
for(int x = 0 ; x < outputCount ; x ++)outputNum[x] = inputer.nextInt();//输出的序号
/*
输入信息检测 ok
for(int x = 0 ; x < avaliableDiskCount ; x++) System.out.println(datas[x]);//硬盘信息
for(int x = 0 ; x < outputCount ; x ++)System.out.println(outputNum[x]);//输出的个数
*/
//创建硬盘阵列
int pieceCountInOneDisk = (datas[0].length() - (datas[0].indexOf(" ") + 1) ) / 8 ; //一个硬盘中的最大的分条数
String[][] diskDatas = new String[pieceCountInOneDisk][diskCount];//阵列数据
int cutIndex ;//截取硬盘号用的暂时数据计数
String diskNumInString = "";//用暂存硬盘编号
int nowDiskNum ; // 当前的硬盘编号
String everyPieceData = "";//每块中的8位数据
int nowPieceNum ; //填充硬盘数据是用 的计数器
boolean[] diskSign = new boolean[diskCount];//硬盘是否可用记号
for(String s : datas) {
//截取硬盘号
cutIndex = 0 ;
diskNumInString = "";
while(s.charAt(cutIndex) != ' ') {
diskNumInString += s.charAt(cutIndex);//拼接数字
cutIndex ++ ;//结束后是空格所在位置
}
nowDiskNum = Integer.parseInt(diskNumInString);//把硬盘编号转换成数值
diskSign[nowDiskNum] = true ;//该硬盘即可用
cutIndex ++ ; //移到数据的地方
nowPieceNum = 0 ;
//向该盘中填充数据
while(true) {//结束条件内部控制
everyPieceData = "";
for(int x = 0 ; x < 8 ; x ++ , cutIndex++)everyPieceData += s.charAt(cutIndex);//截取8位
diskDatas[nowPieceNum][nowDiskNum] = everyPieceData ;//填入对应的盘和对应的块
if(cutIndex == s.length())break ;
nowPieceNum ++ ;//结束时候是有效的最大块
}
}//for(s) end
/*
*测试硬盘阵列的建立
for(int x = 0 ; x < pieceCountInOneDisk ; x ++) {
for(int y = 0 ; y < diskCount ; y ++) {
if(diskSign[y])System.out.print(diskDatas[x][y] + " ");
else System.out.print("- ");
}
System.out.println();
}
*/
//修复与输出
int[] nowLocation ;//转换出来的标准位置0:硬盘中的第几块、1:哪个硬盘
String[] otherData ;
for(int x = 0 ; x < outputCount ; x ++) {//遍历输出序列
nowLocation = location(outputNum[x] , stripSize , diskCount);//定位
if(diskSign[nowLocation[1]] == true) {//当前的硬盘存在,
//判断是否超越界限
if(nowLocation[0] >= pieceCountInOneDisk)System.out.println("-");//输出错误
else System.out.println(diskDatas[nowLocation[0]][nowLocation[1]]);//输出
}else if(diskCount - avaliableDiskCount >= 2) {
//不可修复
System.out.println("-");
}else {//可修复进行修复
otherData = new String[diskCount-1];//其他盘中的数据
for(int y = 0 , y2 = 0 ; y < diskCount ; y ++) {
if(y != nowLocation[1]) {//取得其他恢复用数据
otherData[y2] = diskDatas[nowLocation[0]][y];
y2++;
}
}//for(y) end
//进行恢复输出
System.out.println(fixUp(otherData));
}
}
}
public static int[] location(int thePieceNum , int stripSize , int diskCount) {
int stripLineNum = thePieceNum /( (diskCount - 1) * stripSize);//在第几排条
int numInThisStriopLine =( thePieceNum %( (diskCount - 1) * stripSize)) / stripSize ;//在当前排条的第几条
int thisStripLineCickNum = (diskCount - 1) - (stripLineNum % diskCount) ; //当前排条的校验位
int nowDiskNum = thisStripLineCickNum + 1 == diskCount ? 0 : thisStripLineCickNum + 1 ; //初始化该排第一个数据位
for(int x = 0 ; x < numInThisStriopLine ; x++)nowDiskNum = nowDiskNum + 1 == diskCount ? 0 : nowDiskNum + 1 ;//定位到硬盘号
int thisStripNumInDisk = (stripLineNum * stripSize) + (thePieceNum % stripSize) ;//定位到当前硬盘第几块
int[] solve = {thisStripNumInDisk , nowDiskNum};
return solve ;
}
public static String fixUp(String[] otherData) {
String[][] stemp1 = new String[4][otherData.length];//转成分4位的二进制串
int index ; //截取起始位置
String nowTempH ;//截取的16进制串
String nowTempB ;//街截取的2进制串
for(int x = 0 ; x < 4 ; x++) {
for(int y = 0 ; y < otherData.length ; y ++ ) {
nowTempH = "";
nowTempB = "";
index = x * 2 ;//延这个位置截取2个
nowTempH += otherData[y].charAt(index);//第一个
index ++ ;
nowTempH += otherData[y].charAt(index);//第二个
//转成二进制串
nowTempB = Integer.toBinaryString(Integer.parseInt(nowTempH , 16));
//补齐8位
for(int z = nowTempB.length() ; z < 8 ; z++)nowTempB = "0" + nowTempB ;
stemp1[x][y] = nowTempB ;//记录
}
}//for(x) end
/*
* 测试
*
System.out.println("测试stemp1:");
for(int y = 0 ; y < otherData.length ; y ++ ) {
for(int x = 0 ; x < 4 ; x ++) {
System.out.print(stemp1[x][y] + " ");
}
System.out.print(" ");
}
System.out.println();
*/
String[] solveInB = new String[4];
String solve ;//每8位的异或结果
int oneCount ; // 1 的个数
for(int x = 0 ; x < 4 ; x ++) {
solve = "" ;
for(int z = 0 ; z < 8 ; z ++) {
oneCount = 0 ;
for(int y = 0 ; y < otherData.length ; y ++){
if(stemp1[x][y].charAt(z)=='1')oneCount ++ ;
}
solve += oneCount % 2 == 1 ? "1" : "0";
}
solveInB[x] = solve ;
}
/*
* 测试
for(int x = 0 ; x < 4 ; x ++)System.out.print(solveInB[x] + " ");
System.out.println();
*/
//最后拼串
String end = "";
int endTemp ; //转成10进制
String endTempString ;
for(int x = 0 ; x < 4 ; x ++) {
endTemp = Integer.parseInt(solveInB[x] , 2);
endTempString = Integer.toHexString(endTemp);
for(int y = endTempString.length() ; y < 2 ; y++)endTempString = "0" + endTempString ;
end += endTempString.toUpperCase();
}
return end ;
}
}
题主,这个问题我来替你解决,若有帮助,还望采纳,点击回答右侧采纳即可。
避免使用循环嵌套,尽量减少循环次数,提高代码效率。
减少数组的使用,可以使用变量代替数组,以减小内存占用。
在定位硬盘位置时,可以直接使用数学公式计算出来,而不是使用循环来定位。
在修复数据时,可以避免使用多重循环,直接使用二进制位运算来进行异或操作。
注意代码的命名规范,尽量使用有意义的变量名、函数名和类名来提高代码的可读性。
下面是一个修改后的代码示例:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner inputer = new Scanner(System.in);
//读数据
int diskCount = inputer.nextInt();//有的硬盘总数
int stripSize = inputer.nextInt();//一条中有几块
int avaliableDiskCount = inputer.nextInt();//可用的硬盘数量
//读取因盘中的信息
String[] datas = new String[avaliableDiskCount];
inputer.nextLine();//提前做处理
for (int x = 0; x < avaliableDiskCount; x++)
datas[x] = inputer.nextLine();//读入硬盘的数据
int outputCount = inputer.nextInt(); //输出的数量
int[] outputNum = new int[outputCount];
for (int x = 0; x < outputCount; x++)
outputNum[x] = inputer.nextInt();//输出的序号
//创建硬盘阵列
int pieceCountInOneDisk = (datas[0].length() - (datas[0].indexOf(" ") + 1)) / 8; //一个硬盘中的最大的分条数
String[][] diskDatas = new String[pieceCountInOneDisk][diskCount];//阵列数据
boolean[] diskSign = new boolean[diskCount];//硬盘是否可用记号
for (String s : datas) {
//截取硬盘号
int cutIndex = 0;
String diskNumInString = "";
while (s.charAt(cutIndex) != ' ') {
diskNumInString += s.charAt(cutIndex);//拼接数字
cutIndex++;//结束后是空格所在位置
}
int nowDiskNum = Integer.parseInt(diskNumInString);//把硬盘编号转换成数值
diskSign[nowDiskNum] = true;//该硬盘即可用
cutIndex++;//移到数据的地方
int nowPieceNum = 0;
//向该盘中填充数据
while (true) {//结束条件内部控制
String everyPieceData = s.substring(cutIndex, cutIndex + 8);//截取8位
diskDatas[nowPieceNum][nowDiskNum] = everyPieceData;//填入对应的盘和对应的块
if (cutIndex + 8 >= s.length()) break;//到数据末尾
nowPieceNum++;//结束时候是有效的最大块
cutIndex += 8;
}
}//for(s) end
//定位和修复
for (int i = 0; i < outputCount; i++) {
int pieceIndex = outputNum[i] % stripSize;//定位在条内的第几块
int stripIndex = outputNum[i] / stripSize;//定位在条内的第几个条带
int checkIndex = (diskCount - 1) - stripIndex % diskCount;//定位奇偶校验所在的硬盘
boolean flag = true;
String[] otherData = new String[diskCount - 1];
for (int j = 0, k = 0; j < diskCount; j++) {
if (j != checkIndex && diskSign[j]) {//取得其他恢复用数据
if (diskDatas[pieceIndex][j] == null) {//数据块不存在
flag = false;
break;
}
otherData[k++] = diskDatas[pieceIndex][j];
}
}
if (flag) {//数据可修复
String repairedData = fixUp(otherData);
diskDatas[pieceIndex][checkIndex] = repairedData;
System.out.println(repairedData);
} else {//不可修复
System.out.println("-");
}
}
}
public static String fixUp(String[] otherData) {
String result = "";
for (int i = 0; i < 8; i++) {
int count = 0;
for (int j = 0; j < otherData.length; j++) {
if (otherData[j].charAt(i) == '1') {
count++;
}
}
result += count % 2 == 0 ? "0" : "1";
}
return Integer.toHexString(Integer.parseInt(result, 2)).toUpperCase();
}
}