数组索引映射(虚拟索引)

1.例题

先看一道题,将一个乱序数组排序后,将前面一半翻转,将后面一半翻转,例如:

输入:4,1,2,3,5
输出:3,2,1,5,4

输入:5,2,3,1
输出:2,1,5,3

其实这个题目很简单,只需要将数组排序后,分为前后两部分,分别翻转即可。

void solution(vector<int> &nums)
{
    int n = nums.size();
    //排序
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n -  1 - i; ++j)
        {
            if (nums[j + 1] < nums[j])
            {
                swap(nums[j + 1], nums[j]);
            }
        }
    }
    //翻转
    for (int i = 0; i < n / 4; ++i)
    {
        swap(nums[i], nums[(n - 1) / 2  - i]);
        swap(nums[(n + 1) / 2 + i], nums[n - 1 - i]);
    }
}




2.引入概念

基本上上面的做法是大家常规的一种做法,但是有其他也比较简洁的做法吗?

上面的算法分为了:1.排序, 2.翻转两个步骤。有没有可能将两个步骤合并一起做呢?

我们先看,翻转实际上是对原数组的一种映射:

1,2,3,4,5 ———> 3,2,1,5,4
映射为: 0→2,1→1,2→0,3→4,4→3

1,2,3,4 ———> 2,1,4,3
映射为: 0→1,1→0,2→3,3→2

如果将原来的索引记为x,映射后的索引为y,不难得到映射关系为:

y = f ( x ) = ( ( n − 1 ) / 2 − x ) % n y =f(x)=((n-1)/2-x)\%n y=f(x)=((n1)/2x)%n

我们可以将新索引看做是一个新的数组b,那么:

a [ x ] = b [ f ( x ) ] a[x] = b[f(x)] a[x]=b[f(x)]

因为要排序,所以我们知道: a [ j ] < a [ i ] ( < i ) a[j]<a[i] ( < i) a[j]<a[i](<i) ,所以: b [ f ( j ) ] < b [ f ( i ) ] ( < i ) b[f(j)]<b[f(i)] ( < i) b[f(j)]<b[f(i)](<i)

那么我们只需要对: b [ f ( j ) ] b[f(j)] b[f(j)] 排序即可。

void solution(vector<int> &nums)
{
    int n = nums.size();
    
	#define a(i) nums[((3*n-1)/2 - (i))%n]

    //排序
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n -  1 - i; ++j)
        {
            if (a(j+1) < a(j))
            {
                swap(a(j + 1), a(j));
            }
        }
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值