📜  门| GATE-CS-2016(套装1)|第 57 题(1)

📅  最后修改于: 2023-12-03 15:12:43.282000             🧑  作者: Mango

题目介绍

该题目是2016年的GATE CS考试中出现的,属于套装1中的第57道题目。该题考察了程序员的算法和数据结构基础。

题目描述

给定一个长度为n的数组,数组每个元素的值为1到n(包含n)之间的整数,且每个元素的值不重复。现在我们需要按照以下方式排序数组:

  1. 如果数组中某个元素的值为x,则把x前面的所有数依次移动到数组的后面,直到x成为数组的第一个元素,其他的元素则按它们原来的顺序排列。

例如,如果我们有一个数组[4,1,6,3,5,2],把值为3的元素移动到数组的首部,我们会得到一个新数组[3,4,1,6,5,2]。

  1. 按照上述方法依次处理数组中的每个元素,直到数组排序完成。

例如,如果我们有一个数组[4,1,6,3,5,2],我们首先把值为4的元素移动到数组的首部,得到新数组[4,1,6,3,5,2]。我们接着把值为1的元素移动到数组的首部,得到新数组[1,4,6,3,5,2]。我们继续这个过程,最终得到一个有序的数组[1,2,3,4,5,6]。

编写一个函数,该函数接收一个包含n个元素的数组,按照上述方式排序并返回一个新数组。

函数签名
def sort_array(n: int, arr: List[int]) -> List[int]:
    """
    对一个长度为n的数组进行排序,并返回排序后的数组。
    
    参数:
        n: 数组的长度,保证 1 <= n <= 10^5
        arr: 含有n个元素的数组,每个元素的值为1到n(包含n)之间的整数,且每个元素的值不重复。
        
    返回:
        List[int]类型的数组,为排序后的数组。
    """
    pass
例子
assert sort_array(6, [4,1,6,3,5,2]) == [1,2,3,4,5,6]
题目分析
算法

此类问题是一个典型的重排问题。一般的重排问题可以采用逆向思维的方式解决:从前往后考虑将所有元素都放到它应该在的位置上,那么有序数组的元素显然就在它们的原位置上,而非有序的元素会被移动到后面去。

下面我们尝试采用这种方式来实现我们的排序函数。

首先,我们定义一个map记录每个元素应该在的位置。利用这个map我们可以方便地把一个元素插入到它应该在的位置。但是这个插入过程需要保证插入顺序和原顺序一致,所以我们需要借助之前教程中提到的双向链表来实现。

时间复杂度

此算法的时间复杂度为O(n),因为我们每次只分配了一个双向节点,所以整个算法的空间复杂度为O(n)。同时这是一种在线算法,所以该算法比许多其他算法更加适用于实时数据流。

代码实现

下面是本题的参考实现,供大家参考。

from typing import List

class Node(object):
    def __init__(self, val=0, next=None, prev=None, index=None):
        self.val = val
        self.next = next
        self.prev = prev
        self.index = index

def sort_array(n: int, arr: List[int]) -> List[int]:
    node_map, prev_node, head_node, tail_node = {}, None, None, None
    for i, element in enumerate(arr):
        node_map[element] = Node(element, prev_node, None, i + 1)
        if i == 0:
            head_node = node_map[element]
        prev_node = node_map[element]
    tail_node = prev_node

    for element in reversed(range(1, n + 1)):
        node = node_map[element]
        if not node: continue
        prev_node, i = node.prev, node.index
        while prev_node and prev_node.val > node.val:
            prev_node.index += 1
            node.index -= 1
            node.prev, prev_node.prev, prev_node.next = prev_node.prev, node, node
            if prev_node == head_node:
                head_node = node
            prev_node = node.prev
        if node.index != i:
            node.index = i - 1
            tail_node.next, node.prev, tail_node = node, tail_node, node

    res, node = [], head_node
    while node:
        res.append(node.val)
        node = node.next
    return res
总结

本题要求了程序员对于基本的数据结构和算法的掌握,是一个考验算法基本功的好题目。