这是一个面试问题而不是作业。
给定1到2 ^ N的数组。例如:1 2 3 4 5 6 7 8(2 ^ 3)。想象这个数组写在纸上,我们需要将它折叠成一半,这样左半部分就会被镜像,然后移动到右半部分下方此
1 2 3 4 5 6 7 8
left | right
half | half
变为
5 6 7 8
4 3 2 1
然后下一个折叠我们将右侧改为一半,镜像并将其移动到左半部分之下,
5 6
4 3
8 7
1 2
纸张必须折叠,每次都改变方向(左 - 右 - 右),直到我们在这一列中包含所有元素
6
3
7
2
5
4
8
1
我的解决方案, 第一步 : 为原始数组的后半部分创建链接列表,并反转前半部分并将其与头部指针连接,
5 6 7 8
| | | |
4 3 2 1
将链表的头指针存储在名为headarray
的数组中迭代地说:
折叠头部阵列,对于每个折叠,前半部分和后半部分头部将被链接。链接后删除headarray的头指针。
继续,直到头部阵列中有一个头部指针。
但是面试官让我把它解决了。任何人都可以帮助解决堆栈中的问题,并指出我的解决方案是否有任何错误。提前致谢。
答案 0 :(得分:2)
使用堆栈和原始数组可以解决此问题。我不会为您编写解决方案,但我会指出如何解决它。
填写筹码的规则:
您开始从阵列末尾继续前进到堆栈:
如果迭代为奇数,则首先推动奇数半部分,
如果迭代甚至以偶数的一半开始
这有点抽象,所以让我们考虑你的例子:
iter = 1 ->1234
<-5678
箭头表示迭代的方向
从最后开始并填充堆栈; inter是奇数,所以从遇到的第一个奇数半开始
5
6
7
8
4 <-notice that the order of pushing the halfs on the stack is shown by the arrows
3
2
1
弹回堆栈:5 6 7 8 4 3 2 1
继续划分半场:
iter = 2 <-56
->78
<-43
->21
;奇数半身56
,43
;甚至一半78
,21
从最后开始并填充堆栈;国际米兰甚至从第一个偶数半开始
5
6
4
3
8 <-even halfs end, odd halfs start
7
1
2
重新弹出堆栈:5 6 4 3 8 7 1 2
再次划分细分,因为每个新半部分中只有一个元素,箭头仅用于突出显示规则:
iter = 3 ->5
<-6
->4
<-3
->8
<-7
->1
<-2
iter很奇怪,所以首先填充堆栈奇数半个
6
3
7
2
5
4
8
1
重新弹出堆栈,完成后:63725481
我希望这是有道理的;快乐的编码:)
答案 1 :(得分:0)
我找到了一个定律,即数组中的元素,其索引为(2*n-1, 2*n)
,n
为奇数,总是在其余元素之前排列你所折叠的方向。例如,数组12345678
,元素2367
始终位于1458
的前面。现在我使用dichotomy
来获取两个数组。接下来你可能会发现两个阵列中的定律。我希望这可以帮到你。
答案 2 :(得分:0)
也许你的面试官期望这样:
private int[] Fold(int pow)
{
if (pow < 0)
throw new Exception("illegal input");
int n = 1;
for (int factor = 1; factor <= pow; factor++)
n *= 2;
Stack<int> storage = new Stack<int>(n);
this.Add(n, 1, storage);
int[] result = new int[n];
for (int k = 0; k < n; k++)
result[k] = storage.Pop();
return result;
}
private void Add(int n, int value, Stack<int> storage)
{
storage.Push(value);
int m = n;
while (true)
{
int mirror = m + 1 - value;
if (mirror <= value)
break;
this.Add(n, mirror, storage);
m /= 2;
}
}
{证明你知道堆栈和递归;-)}
答案 3 :(得分:0)
这是一个迭代的递归解决方案;因此堆栈,虽然可能不是预期的。该函数根据给定的位置返回元素的起始位置。它似乎是时间O(1/2n(log n + 1))
和空格O(log n)
。
JavaScript代码:
function f(n,y,x,l){
var stack = [[n,y,x,l]];
while (stack[0]){
var temp = stack.pop();
var n = temp[0], y = temp[1], x = temp[2], l = temp[3];
var m = 1 << l;
if (m == 1)
return x;
if (l % 2 == 0){
if (y > m / 2)
stack.push([n * 2,y - m / 2,n + n - x + 1,l - 1]);
else
stack.push([n * 2,y,x,l - 1]);
} else if (y > m / 2){
stack.push([n * 2,y - m / 2,n - x + 1,l - 1]);
} else
stack.push([n * 2,y,x + n,l - 1]);
}
}
function g(p){
var n = 1 << p;
for (var i=1; i<n; i+=2){
var a = f(1,i,1,p);
console.log(a);
console.log(n - a + 1);
}
}
g(3)