Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.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_Sorting - Fatal编程技术网

Java 字典最小排列,使得所有相邻字母都是不同的

Java 字典最小排列,使得所有相邻字母都是不同的,java,arrays,algorithm,sorting,Java,Arrays,Algorithm,Sorting,这是一个额外的学校任务,我们还没有得到任何教学,我也没有寻找一个完整的代码,但一些开始的提示将非常酷。回到家后,我将发布我在Java中迄今为止所做的事情,但这里有一些我已经做过的事情 因此,我们必须做一个排序算法,例如将“AAABBB”排序到ABABAB。最大输入大小为10^6,并且必须在1秒内完成。如果有多个答案,按字母顺序排列的第一个答案就是正确的答案。我开始测试不同的算法,甚至在没有字母顺序要求的情况下对它们进行排序,只是为了看看结果如何 第一版: 将ascii码保存到整数数组中,其中索引

这是一个额外的学校任务,我们还没有得到任何教学,我也没有寻找一个完整的代码,但一些开始的提示将非常酷。回到家后,我将发布我在Java中迄今为止所做的事情,但这里有一些我已经做过的事情

因此,我们必须做一个排序算法,例如将“AAABBB”排序到ABABAB。最大输入大小为10^6,并且必须在1秒内完成。如果有多个答案,按字母顺序排列的第一个答案就是正确的答案。我开始测试不同的算法,甚至在没有字母顺序要求的情况下对它们进行排序,只是为了看看结果如何

第一版:

将ascii码保存到整数数组中,其中索引是ascii码,值是该字符在字符数组中出现的数量。 然后我选择了两个最高的数字,并开始将它们依次发送到新的字符数组,直到某个数字更高,然后我交换到它。它工作得很好,但当然顺序不对

第二版:


遵循相同的想法,但停止选择出现次数最多的数字,而是按照索引在数组中的顺序选择索引。在输入类似于CBAYYY之前,工作正常。算法将其排序为abcyy而不是AYBYCY。当然,我可以试着为那些Y's找到一些空闲的位置,但是在那一点上,它开始花费太长的时间

一个有趣的问题,有一个有趣的调整。是的,这是一种排列或重新排列,而不是一种排序。不,引用的问题不是重复的

算法

  • 计算字符频率
  • 按字母顺序从最低的两个字符交替输出
  • 当每个人都筋疲力尽时,移动到下一个
  • 在某一点上,最高频率的字符正好是剩余字符的一半。在这一点上,切换到按字母顺序依次输出所有该字符和其他剩余字符
  • 需要注意避免一次关闭错误(输入字符的奇数与偶数)。否则,仅仅编写代码并使其正常工作就是一个挑战


    请注意,有一种特殊情况,其中字符数为奇数,一个字符的频率从(半加1)开始。在这种情况下,您需要从算法中的步骤4开始,依次交替输出所有一个字符

    还要注意的是,如果一个字符包含超过一半的输入,那么在这种特殊情况下,就不可能有解决方案。这种情况可以通过检查频率提前检测到,或者在尾部由所有一个字符组成的执行过程中检测到。检测这个病例不是规范的一部分



    由于不需要排序,复杂性为O(n)。每个字符检查两次:一次是计数,一次是添加到输出中。其他所有内容都将摊销。

    首先计算数组中的每个字母数:

    例如,你有3-A,2-B,1-C,4-Y,1-Z

    1) 然后你每次把最低的一个(它是一个),你可以把

    因此,你可以从以下几点开始:

    A

    那么你不能再放A了,所以你放B:

    AB

    然后:

    阿巴巴茨

    如果你仍然有至少两种角色,这些方法就有效了。但在这里你仍然有3个Y

    2) 要把最后几个字符放进去,你只需从第一个Y开始,按开头的方向在2上插入一个(我不知道这是否是用英语表达的好方法)

    所以,abaybycyz

    3) 然后取Y so YBYAYCY之间的子序列,对Y之间的字母进行排序:

    BAC=>ABC

    然后你到达

    Abayaybycz

    这应该是你问题的解决办法

    要完成所有这些工作,我认为
    LinkedList
    是最好的方法


    我希望它能有所帮助:)

    我的想法如下。通过正确的实现,它几乎可以是线性的

    首先建立一个函数来检查解决方案是否可行。应该很快。类似于最常见字母>所有字母的1/2,如果可以是第一个,则将其考虑在内


    然后,在仍有字母剩余的情况下,取与前一个字母不同的按字母顺序排列的第一个字母,使进一步的解决方案成为可能。

    正确的算法如下:

  • 构建输入字符串中字符的直方图
  • 将出现的字符放入优先级队列/树集中,按出现次数最高、字母顺序最低的顺序排列
  • 具有CharacterOccess类型的辅助变量
  • 当PQ不为空时循环

  • 拿着PQ的头并保存它
  • 将头部的字符添加到输出中
  • 如果设置了辅助变量=>则将其重新添加到PQ中
  • 将保留的头存储在辅助变量中,少出现1次,除非出现次数最终为0(然后将其取消设置)
  • 如果输出的大小==输入的大小,这是可能的,并且您已经得到了答案。否则这是不可能的


  • 复杂性是O(N*log(N))

    制作一个字符频率的双向表:
    字符->计数
    计数->字符
    。记录存储最后一个字符的
    可选
    (或没有)。存储字符总数

    如果(字符总数-1)While不是完全重复的,那么给出用尽可能少的相邻相等字母枚举所有置换的算法的部分可以调整为只返回最小值,因为它的最优性证明要求每个递归调用产生至少一个置换。测试代码之外的更改范围是按排序顺序尝试键,并在t之后中断
    from collections import Counter
    from itertools import permutations
    from operator import itemgetter
    from random import randrange
    
    
    def get_mode(count):
        return max(count.items(), key=itemgetter(1))[0]
    
    
    def enum2(prefix, x, count, total, mode):
        prefix.append(x)
        count_x = count[x]
        if count_x == 1:
            del count[x]
        else:
            count[x] = count_x - 1
        yield from enum1(prefix, count, total - 1, mode)
        count[x] = count_x
        del prefix[-1]
    
    
    def enum1(prefix, count, total, mode):
        if total == 0:
            yield tuple(prefix)
            return
        if count[mode] * 2 - 1 >= total and [mode] != prefix[-1:]:
            yield from enum2(prefix, mode, count, total, mode)
        else:
            defect_okay = not prefix or count[prefix[-1]] * 2 > total
            mode = get_mode(count)
            for x in sorted(count.keys()):
                if defect_okay or [x] != prefix[-1:]:
                    yield from enum2(prefix, x, count, total, mode)
                    break
    
    
    def enum(seq):
        count = Counter(seq)
        if count:
            yield from enum1([], count, sum(count.values()), get_mode(count))
        else:
            yield ()
    
    
    def defects(lst):
        return sum(lst[i - 1] == lst[i] for i in range(1, len(lst)))
    
    
    def test(lst):
        perms = set(permutations(lst))
        opt = min(map(defects, perms))
        slow = min(perm for perm in perms if defects(perm) == opt)
        fast = list(enum(lst))
        assert len(fast) == 1
        fast = min(fast)
        print(lst, fast, slow)
        assert slow == fast
    
    
    for r in range(10000):
        test([randrange(3) for i in range(randrange(6))])