Algorithm 寻找最终安排
我在最近的采访中遇到了这个问题: 给定一个表示在哪个位置插入的数字的对数组,我们需要找到最终的排列。如果在那个位置已经有一个数字,我们需要将数组从那个位置移到右边,并将那个数字放在所需的位置 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}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>代码>运算符
约束: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)。