java 排序算法中的重叠

hxzsmxv2  于 2023-05-27  发布在  Java
关注(0)|答案(2)|浏览(158)

排序重叠
该程序的目的是遍历整数序列,并确定数组中每个序列的长度和顺序(升序或降序)。例如给定数组
[53, 50, 41, 8, 64, 35, 17, 76, 58, 3, 75, 1, 99, 56, 2]
它应该能识别每个序列
[53,50,41,8][64,35,17][76,58,3][75,1][99,56,2]将它们排序为[8,41,50,53][17,35,64][3,58,76][1,75][2,56,99]
但我只能在对当前最大的数字排序后查找下一个最大的数字序列。
这是我的代码

public static void descendingStructure(int[] x, ArrayList<Integer> y) {

        int descending = 1;

        int maxDescending = 1;

        int descendingRunStart = x.length - 1;

        int descendingRunEnd = x.length - 1;

        
        for (int i = 1; i < x.length; i++) {
            {
                if (x[i] < x[i - 1]) {
                    descending++;

                } else if (x[i] > x[i - 1]) {

                    if (descending > 1) {
                        if (descending > maxDescending) {
                            maxDescending = descending;
                            descendingRunStart = i - descending;
                            descendingRunEnd = i - 1;
                        }
                        descending = 1;

                    }
                }
            }
        }
        if (descending > maxDescending) {

            maxDescending = descending;
            descendingRunStart = x.length - descending;
            descendingRunEnd = x.length - 1;
        }
        if (maxDescending <= 1) {
            return;
        }

        for (int i = descendingRunStart; i < descendingRunEnd; i++) {
            y.add(i);
        }
        sortSubArray(x, descendingRunStart, descendingRunEnd);

        System.out.println(Arrays.toString(x));
        descendingStructure(x, y);
    }

Here is my results after running my code
我以为会有一个数组
[8, 41, 50, 53, 17, 35, 64, 3, 58, 76, 1, 75, 2, 56, 9]
但我得到了
[8, 41, 50, 53, 17, 35, 64, 3, 58, 1, 75, 76, 2, 56, 99]

cnwbcb6i

cnwbcb6i1#

您可能希望将此问题视为操作finite state machine

算法

状态由五个部分组成(假设我们正在检查x1,其中x0是前一个元素,x2是后一个元素:

  • was_up - x0 < x1
  • was_down - x0 > x1
  • up - x1 < x2
  • down - x1 > x2
  • ldx-最后子序列的索引

在这个状态机中我们只需要区分两种情况。如果was_updown为真,或者was_downup为真,则表示方向改变。对于这种情况,我们将对当前子序列进行排序,然后重置为初始状态,将ldx更新为新子序列的开始。
对于所有其他状态,was_up变为upwas_down变为down,我们继续下一个元素。
下面的代码可以更精确地说明该算法。

示例代码

#include <iostream>

using std::cout, std::endl;

int main(int argc, const char *argv[]) {
    std::vector<int> data = { 53, 50, 41, 8, 64, 35, 17, 76, 58, 3, 75, 1, 99, 56, 2 };

    int ldx{};
    bool was_up{}, was_down{};
    for (auto i = 0; i < data.size() - 1; ++i) {
        bool up = data[i] < data[i+1];
        bool down = data[i] > data[i+1];
        if ((was_up and down) or (was_down and up)) {
            std::sort(&data[ldx], &data[i+1]);
            ldx = i + 1;
            was_down = false;
            was_up = false;
        } else {
            was_down = down;
            was_up = up;
        }
    }
    std::sort(&data[ldx], &data[data.size()]);

    for (auto elem : data)
        cout << elem << " ";

    return 0;
}

输出

8 41 50 53 17 35 64 3 58 76 1 75 2 56 99
ars1skjm

ars1skjm2#

关于你的代码的一些评论:

  • y被写入,但从未被读取,因此它是无用的
  • 第一个循环没有规定两个连续的数组值何时相等,当这种情况发生时,您将得到不一致的运行。这里我假设递减序列是 * 严格 * 递减的,所以else部分后面不应该有条件。
  • 你所谓的排序实际上是反转。它在这里有相同的结果,但用于revering的算法比用于排序的算法具有更好的时间复杂度。
  • 您提出的主要问题:当一个子数组被排序时,它会影响函数的下一次递归执行。
  • 遗憾的是,你在循环之后有重复的代码。在循环内部,您可以查看i+1而不是i-1,并检测递减序列的最后一个索引。
  • 遗憾的是你必须再次扫描整个数组才能找到下一个递减序列。

我推荐这个算法:
1.在一个循环中收集所有递减序列,但不要反转任何内容。只要记录下所有的序列
1.将这些序列按长度排序
1.执行这些序列的反转。
在第一步中,您甚至可以收集序列,并使用它们的长度作为列表中的索引,并在该索引处的子列表中注册起始索引。这样就不再需要第二步;在这个列表的列表上循环将按照它们的大小顺序给予序列。
下面是一个实现:

public static void reverseSubArray(int[] arr, int first, int last) {
        while (first < last) {
            int temp = arr[first];
            arr[first++] = arr[last];
            arr[last--] = temp;
        }
    }
    
    public static void descendingStructure(int[] arr) {
        List<List<Integer>> startPerRunLength = new ArrayList<List<Integer>>(arr.length + 1);
        // Initialise: for each possible run length, create an empty list of run-start indices.
        for (int runLength = 0; runLength <= arr.length; runLength++) {
            startPerRunLength.add(new ArrayList<>());
        }
        // Detect all runs and register their starting index in the list dedicated to the run length.
        for (int i = 0, runStart = 0; i < arr.length; i++) {
            if (i + 1 >= arr.length || arr[i] <= arr[i + 1]) {
                // Current index is the last of a descending sequence
                startPerRunLength.get(i - runStart + 1).add(runStart);
                runStart = i + 1;
            }
        }
        // Iterate over the runs in order of their descending size
        for (int runLength = arr.length; runLength > 1; runLength--) {
            for (int runStart : startPerRunLength.get(runLength)) {
                reverseSubArray(arr, runStart, runStart + runLength - 1);
                System.out.println(Arrays.toString(arr));
            }
        }
    }

    public static void main(String[] args) {
        // Example run
        int arr[] = {53, 50, 41, 8, 64, 35, 17, 76, 58, 3, 75, 1, 99, 56, 2};
        System.out.println(Arrays.toString(arr));
        descendingStructure(arr);
    }

该输出:

[53, 50, 41, 8, 64, 35, 17, 76, 58, 3, 75, 1, 99, 56, 2]
[8, 41, 50, 53, 64, 35, 17, 76, 58, 3, 75, 1, 99, 56, 2]
[8, 41, 50, 53, 17, 35, 64, 76, 58, 3, 75, 1, 99, 56, 2]
[8, 41, 50, 53, 17, 35, 64, 3, 58, 76, 75, 1, 99, 56, 2]
[8, 41, 50, 53, 17, 35, 64, 3, 58, 76, 75, 1, 2, 56, 99]
[8, 41, 50, 53, 17, 35, 64, 3, 58, 76, 1, 75, 2, 56, 99]

相关问题