Java 需要帮助解决黑客银行的挑战吗
我正试图解决hackerrank中的一个“几乎分类”难题问题是: 给定一个包含元素的数组,能否仅使用以下操作之一按升序对该数组进行排序 交换两个元素。 反转一个子段 输入格式 第一行包含一个整数,表示数组的大小 下一行包含由空格分隔的整数 样本输入#1 2Java 需要帮助解决黑客银行的挑战吗,java,arrays,algorithm,reverse,swap,Java,Arrays,Algorithm,Reverse,Swap,我正试图解决hackerrank中的一个“几乎分类”难题问题是: 给定一个包含元素的数组,能否仅使用以下操作之一按升序对该数组进行排序 交换两个元素。 反转一个子段 输入格式 第一行包含一个整数,表示数组的大小 下一行包含由空格分隔的整数 样本输入#1 2 4.2 样本输出#1 是 互换1 2 样本输入#2 三, 3 1 2 样本输出#2 没有 样本输入#3 六, 1 5 4 3 2 6 样本输出#3 对 反向25 我试图解决这个难题,我的代码也在运行,但对于大型阵列来说,速度似乎很慢 恳请您帮
4.2 样本输出#1 是
互换1 2 样本输入#2 三, 3 1 2 样本输出#2 没有 样本输入#3 六, 1 5 4 3 2 6 样本输出#3 对 反向25 我试图解决这个难题,我的代码也在运行,但对于大型阵列来说,速度似乎很慢 恳请您帮助我找到一个更好的解决上述问题的办法 下面是我的代码:
import java.util.*;
public class Solution
{
private static int[] arr;
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int N = in.nextInt();
arr = new int[N];
for (int i = 0; i < N; i++)
{
arr[i] = in.nextInt();
}
if (IsSorted(arr))
{
System.out.println("yes");
return;
}
if(CheckSingleSwap(arr))
return;
if(CheckSingleReverse(arr))
return;
System.out.println("no");
}
private static boolean CheckSingleReverse(int[] arr)
{
int length = arr.length;
int limit = length - 2;
int current = 1;
List<Integer> indexes = new ArrayList<Integer>();
while (current < limit)
{
for (int i = 0; i < length; i++)
{
int temp = current + i;
for (int j = i; j <= temp && temp < length; j++)
{
indexes.add(j);
}
if (IsSorted(ReverseArrayPart(arr, indexes)))
{
System.out.println("yes");
System.out.println("reverse " + (indexes.get(0) + 1) + " " + (indexes.get(indexes.size() - 1) + 1));
return true;
}
indexes.clear();
}
current++;
}
return false;
}
private static int[] ReverseArrayPart(int[] arr, List<Integer> indexes)
{
int[] result = new int[arr.length];
int[] arrayPart = new int[indexes.size()];
int j = 0;
for (int i = 0; i < arr.length; i++)
{
if (indexes.contains(i))
{
arrayPart[j] = arr[i];
j++;
}
result[i] = arr[i];
}
for(int i = 0; i < arrayPart.length / 2; i++)
{
int temp = arrayPart[i];
arrayPart[i] = arrayPart[arrayPart.length - i - 1];
arrayPart[arrayPart.length - i - 1] = temp;
}
j = 0;
for (int i = 0; i < result.length; i++)
{
if (indexes.contains(i))
{
result[i] = arrayPart[j];
j++;
}
}
return result;
}
private static boolean CheckSingleSwap(int[] arr)
{
int count = 0;
int[] B = Arrays.copyOf(arr, arr.length);
Arrays.sort(B);
List<Integer> indexes = new ArrayList<Integer>();
for(int i = 0; i < arr.length; i++)
{
if(arr[i] != B[i])
{
count++;
indexes.add(i+1);
}
}
if(count > 2)
return false;
System.out.println("yes");
System.out.println("swap " + indexes.get(0) + " " + indexes.get(1));
return true;
}
private static boolean IsSorted(int[] arr)
{
int length = arr.length;
for (int i = 0; i < length - 1; i++)
{
if (arr[i] > arr[i + 1])
{
return false;
}
}
return true;
}
}
import java.util.*;
公共类解决方案
{
私有静态int[]arr;
公共静态void main(字符串[]args)
{
扫描仪输入=新扫描仪(系统输入);
int N=in.nextInt();
arr=新整数[N];
对于(int i=0;iarr[i+1])
{
返回false;
}
}
返回true;
}
}
对于以下代码,传入A
作为原始数组,传入B
作为排序数组
CheckSingleSwap
:
与其将索引添加到另一个列表中,不如存储遇到的第一次交换,然后继续;如果找到对应的其他交换,则存储它并记录查找结果;如果找到其他交换,则以false退出。最后,如果已记录查找,则打印对应的索引
private static boolean CheckSingleSwap(int[] A, int[] B)
{
int L = A.length;
int firstSwap = -1, secondSwap = -1;
for(int i = 0; i < L; i++)
{
if(A[i] != B[i])
{
if (firstSwap == -1)
firstSwap = i;
else if (secondSwap == -1 && A[i] == B[firstSwap] && A[firstSwap] == B[i])
secondSwap = i;
else
return false;
}
}
if (firstSwap != -1 && secondSwap != -1)
{
System.out.println("yes");
System.out.println("swap " + (firstSwap + 1) + " " + (secondSwap + 1));
return true;
}
System.out.println("array is already sorted!");
return false; // or whatever you decide to do; maybe even an exception or enumerated type
}
为了让您了解性能提升的情况,在
ideone.com
上,数组长度为150的CheckSingleReverse
最初的实现耗时1.83秒,而新的只需0.1秒。长度为250的原始实现实际上超过了计算时间限制(5秒),而新的只需0.12秒
由此看来,您的实现似乎需要指数时间,而我的实现是线性时间(忽略排序)
有趣的是,当数组大小为300万时,我仍然能得到0.26秒左右的时间(
ideone
的执行时间也会有一些波动,这是由于需求而产生的问题)那里有一篇社论,对每件事都做了很好的解释。难道你不明白吗?我不确定我是否明白。你为什么需要传递一个排序数组?练习是获取一个数组,如果它可以通过两个允许的操作中的一个进行排序,则返回。我认为必须传递一个排序数组会破坏整个目的。Youve误解-目标是查看是否可以使用一个操作对其进行排序,而不是实际进行排序。这并不妨碍我们通过与排序数组进行比较来使用反向工程方法。
private static boolean CheckSingleReverse(int[] A, int[] B)
{
// find region
int L = A.length;
int diffStart = -1, diffEnd = -1; boolean mid = false, found = false;
for (int i = 0; i < L; i++)
{
if (A[i] != B[i])
{
if (found)
{
if (i - diffEnd == 2 && !mid)
{
mid = true;
found = false;
diffEnd = -1;
}
else
return false;
}
else if (diffStart == -1)
diffStart = i;
}
else
if (diffStart != -1 && diffEnd == -1)
{
found = true;
diffEnd = i - 1;
}
}
if (diffEnd == -1)
{
if (A[L - 1] != B[L - 1])
diffEnd = L - 1;
else if (!found)
{
System.out.println("array is already sorted!");
return false;
}
}
// find out if it's reversed
int count = (diffEnd - diffStart + 1) / 2;
for (int i = 0; i < count; i++)
{
int oneEnd = diffStart + i, otherEnd = diffEnd - i;
if (!(A[oneEnd] == B[otherEnd] && A[otherEnd] == B[oneEnd]))
return false;
}
System.out.println("yes");
System.out.println("reverse " + (diffStart + 1) + " " + (diffEnd + 1));
return true;
}