LeetCode 1470. 重新排列数组

给你一个数组 nums ,数组中有 2n 个元素,按 [x1,x2,…,xn,y1,y2,…,yn] 的格式排列。

请你将数组按 [x1,y1,x2,y2,…,xn,yn] 格式重新排列,返回重排后的数组。

1 <= n <= 500
nums.length == 2n
1 <= nums[i] <= 10^3

法一:由于每个数字都是正数且大小不超过1000,因此在一个int的32位中,数据部分只用到了低位的10个bit。我们可以先把每个数字应在位置的第11~20bit设为结果,最后再右移10bit以只留下正确结果,这种思路时间复杂度为O(n),空间复杂度为O(1)。

每个数字应在位置分析如下:

01234567    // 排序前下标
04152637    // 排序后下标

// 前n个数字下标变化
0->0
1->2
2->4
3->6
// 设下标为i,规律为i->2*i

// 后n个数字下标变化
4->1
5->3
6->5
7->7
// 规律为i->2*(i-n)+1

代码如下:

class Solution {
public:
    vector<int> shuffle(vector<int>& nums, int n) {
        for (int i = 0; i < 2 * n; ++i) {
            int j = i < n ? 2 * i : 2 * (i - n) + 1;    // j为i应放在的下标
            nums[j] |= (nums[i] & 1023) << 10;
        }

        for (int &num : nums) {
            num >>= 10;
        }

        return nums;
    }
};

法二:由于数字都是正数,我们可以将数字取负来标记已经在正确位置的数字,当我们遍历到一个数字时,如果它的值大于0,需要计算这个数字应该在的位置,然后将这个数字放到它应该在的位置并取负以说明它已经处于正确的位置,而这个位置原来的数字放到取代它的数字的原位置,此时我们要记录下这个被取代位置的数字的下标,以计算它的正确位置,直到数组中所有数字都为负数,说明所有数字都在自己正确的位置了,最后再对每个数组中的数字取负即可,这种方法的时间复杂度为O(n),而空间复杂度为O(1):

class Solution {
public:
    vector<int> shuffle(vector<int>& nums, int n) {
        for (int i = 0; i < 2 * n; ++i) {
            if (nums[i] > 0) {
                int j = i;
                while (nums[i] > 0) {
                    j = j < n ? 2 * j : 2 * (j - n) + 1;    // j为i应在的下标,同时i和j交换了位置,也记录下来了下标j以在下次循环中计算之前下标j的数字应在的下标
                    swap(nums[i], nums[j]);
                    nums[j] = -nums[j];    
                }
            }
        }

        for (int &num : nums) {
            num = -num;
        }

        return nums;
    }
};

法三:创建新数组直接填充,时间复杂度为O(n),时间复杂度为O(n):

class Solution {
public:
    vector<int> shuffle(vector<int>& nums, int n) {
        vector<int> res(nums.size());
 
        int index = 0;
        for (int i = 0; i < n; ++i) {
            res[index++] = nums[i];
            res[index++] = nums[i + n];
        }
        return res;
    }
};
posted @   epiphanyy  阅读(11)  评论(0编辑  收藏  举报  
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示