290 · 排序方案

对于有一个排好序的数组,它的元素可以从队首或者队尾加入或弹出,即双端队列。
每当我们需要插入一个元素,并且保持它是排好序的,可以选择做两种操作

    从队首或队尾弹出一个元素。
    将待插入元素加入到队首或队尾。
    将之前弹出的元素重新加入到队首或队尾。

每插入一个元素后要保持队列是递增的。
现在给你一个待插入元素的数组,请按顺序插入到一个空数组中,并计算出最少操作次数。

待插入的数组 numsnumsnums 的长度为 nnn,1≤n≤1051 \le n \le 10^51≤n≤105.
数组中的每个数字各不相同,1≤numi≤n1 \le num_i \le n1≤numi​≤n。
样例中,最少需要 666 步:

    将 111 放入队尾。
    将 333 放入队尾。
    将 444 放入队尾。
    将 111 从队首取出。
    将 222 放入队首。
    将 111 放入队首。

样例

输入:
[1,3,4,2]

输出:
6

struct Tree
{
    int start, end, count;
    Tree **child;

    Tree(int a, int b, int c)
    {
        start = a;
        end = b;
        count = c;
        child = nullptr;
    }


};

Tree* create(int start, int end, int n)
{
    Tree * root = nullptr;
    if (start == end)
    {
        root = new Tree(start,end,0);
        return root;
    }
    root = new Tree(start, end, 0);
    root->child = (Tree**)malloc(sizeof(Tree*) * n);
    int num = (end - start) / n;
    int index = start;
    Tree *node = nullptr;
    for (int i = 0; i < n; i++)
    {
        if (index + num > end)
        {
            root->child[i] = create(index, end, n);
            break;
        }
        node = create(index, index + num, n);
        root->child[i] = node;
        index += num + 1;
        if (index > end)
        {
            break;
        }
    }
    return root;
}

void adjustTreeCount(Tree* root, int num,int n)
{
    if (nullptr == root)
    {
        return;
    }
    if (num > root->end )
    {
        return;
    }
    if ((num == root->start) && (num == root->end))
    {
        root->count++;
        return;
    }
    Tree *node = nullptr;
    for (int i = 0; i < n; i++)
    {
        node = root->child[i];
        if (nullptr == node)
        {
            return;
        }
        if (num > node->end)
        {
            continue;
        }
        if (num < node->start)
        {
            return;
        }
        adjustTreeCount(node, num, n);
        root->count++;
        return;
    }
}


long long sumTreeCount(Tree* root, int num, int n)
{
    if (nullptr == root)
    {
        return 0;
    }
    if (num >= root->end)
    {
        return root->count;
    }
    if (num < root->start)
    {
        return 0;
    }
    long long ret = 0;
    Tree *node = nullptr;
    for (int i = 0; i < n; i++)
    {
        node = root->child[i];
        if (num >= node->end)
        {
            ret += node->count;
        }
        else if (num >= node->start)
        {
            ret += sumTreeCount(node, num, n);
        }
        else if (num < node->start)
        {
            break;
        }
    }
    return ret;
}


long long sortedArrangement6(vector<int> &nums) {
    long long count = 0;
    int n = 10;
    Tree* root = create(0, 100000, n);

    for (int i = 0; i < nums.size(); i++)
    {
        int left = sumTreeCount(root, nums[i],n);
        int right = i - left;
        count += 2 * min(left, right) + 1;
        adjustTreeCount(root, nums[i], n);
    }
    return count;
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值