Algorithm 寻找最终安排

Algorithm 寻找最终安排,algorithm,data-structures,Algorithm,Data Structures,我在最近的采访中遇到了这个问题: 给定一个表示在哪个位置插入的数字的对数组,我们需要找到最终的排列。如果在那个位置已经有一个数字,我们需要将数组从那个位置移到右边,并将那个数字放在所需的位置 e、 g.A={0,1,2,3,4},B={0,1,2,1,2}(Ai表示一个数字,Bi表示其所需位置),因此数组C可以按如下方式填充: C={0,{0,1,{0,1,{0,1,2,{0,3,1,2,{0,4,1,2}=>{0,3,1,2,{0,3,4,1,2} 约束:0 首先,让我们考虑 t>代码>运算符

我在最近的采访中遇到了这个问题:

给定一个表示在哪个位置插入的数字的对数组,我们需要找到最终的排列。如果在那个位置已经有一个数字,我们需要将数组从那个位置移到右边,并将那个数字放在所需的位置

e、 g.A={0,1,2,3,4},B={0,1,2,1,2}(Ai表示一个数字,Bi表示其所需位置),因此数组C可以按如下方式填充:

C={0,{0,1,{0,1,{0,1,2,{0,3,1,2,{0,4,1,2}=>{0,3,1,2,{0,3,4,1,2}


约束:0

首先,让我们考虑<代码> t>代码>运算符,对于一个位置<代码> i <代码>,返回<代码> t(i)=i+1 < /COD>(即元素被切换到右边) 显然,

T(T(i))=i+2
,我们可以注意到
T^n(i)=i+n

现在考虑一个节点为

的链表
{
    idx: i,//idx of the value upon insertion (as found in B)
    value:value,
    tn:Number //T^n
}
伪代码

insertElem(L, i, val):
    node = L
    while node
        acc += node.tn //sum all the shifts
        curIdx = node.idx + acc
        if curIdx == i:
            insertElemBefore(node, i, val)
            node.tn++
            return
        if curIdx > i:
            insertElemBefore(node, i, val)
        node = node.next
    //we could not find any elem to shift
    //just insert elem at the end
函数插入器(L,i,val){
设el={idx:i,val:val,tn:0}
设acc=0;
设front=L;
while(L.next){
设next=L.next;
acc+=next.tn;
如果(acc+next.idx>=i){
L.next=el;
如果(acc+next.idx==i){
el.next=next;
next.tn++;
}
返回前线;
}
L=L.next;
}
L.next=el;
el.next=null;
返回前线;
}
主功能(A、B){
设L={next:null}
B.forEach((idx,i)=>{
L=插入项(L,idx,A[i]);
});
设v=[];
while(L=L.next){
v、 推(L.val);
}
返回v;
}

控制台.log(main([01,1,3.4],[01,1,1,2])< < /代码> 首先,让我们考虑<代码> t>代码>运算符,对于一个位置<代码> i <代码>,返回<代码> t(i)=i+1 (即元素被切换到右边) 显然,
T(T(i))=i+2
,我们可以注意到
T^n(i)=i+n

现在考虑一个节点为

的链表
{
    idx: i,//idx of the value upon insertion (as found in B)
    value:value,
    tn:Number //T^n
}
伪代码

insertElem(L, i, val):
    node = L
    while node
        acc += node.tn //sum all the shifts
        curIdx = node.idx + acc
        if curIdx == i:
            insertElemBefore(node, i, val)
            node.tn++
            return
        if curIdx > i:
            insertElemBefore(node, i, val)
        node = node.next
    //we could not find any elem to shift
    //just insert elem at the end
函数插入器(L,i,val){
设el={idx:i,val:val,tn:0}
设acc=0;
设front=L;
while(L.next){
设next=L.next;
acc+=next.tn;
如果(acc+next.idx>=i){
L.next=el;
如果(acc+next.idx==i){
el.next=next;
next.tn++;
}
返回前线;
}
L=L.next;
}
L.next=el;
el.next=null;
返回前线;
}
主功能(A、B){
设L={next:null}
B.forEach((idx,i)=>{
L=插入项(L,idx,A[i]);
});
设v=[];
while(L=L.next){
v、 推(L.val);
}
返回v;
}

log(main([0,1,2,3,4],[0,1,2,1,2]))
提示:考虑按相反顺序插入数字。最后一次插入总是在它想要的位置;它对早期插入的最终位置有什么影响?这种“效应”可以用每次插入的O(n)时间直接计算,或者用某些数据结构用每次插入的O(logn)时间直接计算。在O(logn)中执行此操作的方法是什么。我听说芬威克树在这里工作,但不知道如何使用它。是的,芬威克树会很好地工作。但我不只是告诉你答案,而是想让你自己去发现它。我建议用文字描述您需要为每个插入按相反顺序计算的内容,并提出一种以每次插入O(n)时间计算的简单方法。然后阅读有关Fenwick树的文章,看看是否可以应用它们来加速到O(logn)。最后一次插入总是在它想要的位置;它对早期插入的最终位置有什么影响?这种“效应”可以用每次插入的O(n)时间直接计算,或者用某些数据结构用每次插入的O(logn)时间直接计算。在O(logn)中执行此操作的方法是什么。我听说芬威克树在这里工作,但不知道如何使用它。是的,芬威克树会很好地工作。但我不只是告诉你答案,而是想让你自己去发现它。我建议用文字描述您需要为每个插入按相反顺序计算的内容,并提出一种以每次插入O(n)时间计算的简单方法。然后阅读有关芬威克树的文章,看看你是否可以应用它们来加速到O(logn)。