Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 需要帮助解决黑客银行的挑战吗_Java_Arrays_Algorithm_Reverse_Swap - Fatal编程技术网

Java 需要帮助解决黑客银行的挑战吗

Java 需要帮助解决黑客银行的挑战吗,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 我试图解决这个难题,我的代码也在运行,但对于大型阵列来说,速度似乎很慢 恳请您帮

我正试图解决hackerrank中的一个“几乎分类”难题问题是:

给定一个包含元素的数组,能否仅使用以下操作之一按升序对该数组进行排序

交换两个元素。 反转一个子段

输入格式 第一行包含一个整数,表示数组的大小

下一行包含由空格分隔的整数

样本输入#1

2
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;   
}