需要帮助来解决hackerrank挑战

阿拉姆

我正在尝试解决hackerrank中的“几乎已排序”挑战,问题是:

给定具有元素的数组,是否可以仅使用以下操作之一按升序对该数组进行排序?

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

输入格式第一行包含单个整数,它指示数组的大小。

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

样本输入#1

2
4 2

样本输出#1


交换1 2

样本输入2

3

3 1 2

样本输出2

样本输入#3

6

1 5 4 3 2 6

样本输出#3

是的

倒车2 5

我试图解决挑战,并且我的代码正在运行,但是对于大型数组来说似乎很慢。

请您帮助我为上述问题找到更好的解决方案。

下面是我的代码:

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;
    }
}
用户名

对于以下代码,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
}

CheckSingleReverse

你正在做WAY太多了!乍一看来,您似乎很无情地强迫了每种可能的情况。

您可以做的是找到所有数字都不相同区域如果其中有两个以上,或者两个以上被一个以上的元素分隔,则立即返回false。

上面出现“多个”的原因是由于奇数长度区域-中间元素将是相同的。如果找到这两个区域,请将它们视为一个。然后,您可以继续查找该区域是否反转。

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

只是为了让您了解性能提升,在ideone.com数组长度为150的情况下,最初的实现CheckSingleReverse花费了1.83秒,而新的实现只花费了0.1秒。原始长度为250,实际上超出了计算时间限制(5秒),而新的仍然只花费了0.12秒。

由此看来,您的实现似乎花费了指数时间,而我的是线性时间(忽略排序)。

有趣的是,在阵列大小为300万的情况下,我仍然需要大约0.26秒的时间(ideone执行时间也会有所波动,根据需求而定)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

需要帮助来解决联接表问题

需要帮助来解决ORA-12154

解决hackerrank的“总结N系列”挑战

需要帮助解决具有挑战性的数据结构问题

需要有关编程挑战解决算法的帮助

需要您的帮助来解决Aerospike还原问题

需要帮助来解决目录的正则表达式

需要帮助来解决语法错误消息

Flutter应用构建失败,需要帮助来解决依赖关系

我需要帮助来解决嵌套的FORM问题

我需要帮助来解决C语言中的这段代码

需要帮助来解决Raspberry Pi上matplotlib的性能问题

我需要帮助来了解编程挑战

儿童糖果Hackerrank挑战:优化解决方案

需要帮助解决缓慢的查询

需要帮助解决功能问题

需要帮助解决 Pythonhackerrank 问题

Java脚本,我需要帮助来解决一个任务

PowerBI 需要帮助来解决自定义 KPI 创建的多个查询

需要帮助来提出R中的正则表达式解决方案

需要帮助来优化Project Euler问题#12的解决方案

我需要帮助来解决绘图表面中的 matlab 问题

需要帮助来优化动态编程问题解决方案

我需要帮助来解决为什么MySQL查询花费比预期更长的时间的问题

需要帮助来解决Unnamed并在熊猫的dataframe中进行更改

我遇到CSS故障,需要一些帮助来解决

我需要帮助来解决升级问题,“获取升级失败”,是从12.04到12.10

NSInvalidArgumentException”,原因:“无效谓词:n RHS,需要帮助来解决此问题

需要帮助来解决-未捕获的ReferenceError:未定义数据