2016阿里笔试题:一个最小数,一个最大数地,重排数组

2016阿里笔试题:一个最小数,一个最大数地,重排数组

@(algorithm)

问题描述

2017阿里笔试题

原始数组是排好序的,如:[0,1,2,3,4,5,6]

结果数组是一个最小数,一个最大数地重排数组。即:[0,6,1,5,2,4,3]

要求使用O(1)的空间复杂度,O(n)的时间复杂度。

参考

virtual index:
https://discuss.leetcode.com/topic/32929/o-n-o-1-after-median-virtual-indexing/2

分析

首先分析初始数组的下标与结果数组的下标的关系:

ori0123456
dst0246531

很明显,当原始下标ori <= (len - 1) / 2的时候dst = ori * 2

ori0123
dst0246

否则:

ori456
dst531

这个关系似乎不太容易看得出来,可以用dst = a * ori + b拟合

得到dst = -2 * ori + 13,再猜一下13与len=7有关,应该是13 = len * 2 - 1

即:dst = -2 * ori + 2 * len - 1

然后就可以根据这个映射写出映射函数了。

最后利用迭代,把数组的元素依次替换。

代码

#include <iostream>
using namespace std;

int findIndex(int ori, int len)
{
    if (ori <= (len - 1) / 2)
    {
        return ori * 2;
    }
    else
    {
        return -2 * ori + 2 * len - 1;
    }
}

void print(int* a, int len)
{
    for (int i = 0; i < len; i++)
    {
        cout << a[i] << " ";
    }
    cout << endl;
}

void printNewIndex(int* a, int len)
{
    for (int i = 0; i < len; i++)
    {
        cout << findIndex(i, len) << " ";
    }
    cout << endl;
}

void shuffle(int *a, int len)
{
    // 2个元素以下的数组无需调整
    if (len <= 2)
        return;
    // 当前位置
    int nowpos = 1;
    // 下一个位置
    int nextpos = findIndex(nowpos, len);
    // 记录下一个位置的值
    int tmp = a[nextpos];
    // 更改下一个位置的值为当前位置的值
    a[nextpos] = a[nowpos];
    for (int i = 2; i < len; i++)// 循环len-2次
    {
        nowpos = nextpos;// 当前位置是上一个的nextpos
        nextpos = findIndex(nowpos, len);// 使用函数查找下一个位置
        swap(tmp, a[nextpos]);// 交换下一个位置的值和tmp
    }
}

int main(int argc, const char * argv[]) 
{
    // insert code here...
    int a[7] = {1,3,5,7,9,11,13};
    int len = 7;
    cout << "原始数组:\n";
    print(a, len);
    cout << "变换后的index:\n";
    printNewIndex(a, len);
    cout << "变换后的数组:\n";
    shuffle(a, len);
    print(a, len);
    return 0;
}
点赞