Lintcode 144. 交错正负数

本文介绍了一种在数组中交错排列正负数的算法,通过双指针技术实现正负数的交替放置,同时考虑了正数和负数数量不同的特殊情况,提供了不消耗额外空间的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

144. 交错正负数

给出一个含有正整数和负整数的数组,重新排列成一个正负数交错的数组。

样例

给出数组[-1, -2, -3, 4, 5, 6],重新排序之后,变成[-1, 5, -2, 4, -3, 6]或者其他任何满足要求的答案

挑战

完成题目,且不消耗额外的空间。

注意事项

不需要保持正整数或者负整数原来的顺序。

这道题目比较难,使用O(N)的算法来做的时候使用双指针,奇数偶数指标交替向后走的方法。

注意,题目输入保证了当n为偶数的时候,正数和负数个数是完全相同的。

当n为奇数的时候,正数个数只会比负数个数多1

所以这里要特别处理正数和负数个数的情况

时间复杂度为O(N), 空间复杂度O(N)。 不改变数组的顺序

class Solution {
public:
    /*
     * @param A: An integer array.
     * @return: nothing
     */
    void rerange(vector<int> &A) {
        // write your code here
        vector<int> postive;
        vector<int> nagetive;
        for(auto a:A){
            if(a>=0) postive.push_back(a);
            else nagetive.push_back(a);
        }
        int i=0,j=0,k=0;
        // 如果正数个数大于负数的情况
        if(postive.size()>nagetive.size()){
            
            while(i!=postive.size() && j!=nagetive.size()){
                A[k++] = postive[i++];
                A[k++] = nagetive[j++];
            }
            while(i!=postive.size()) A[k++] = postive[i++];
        }
        // 如果负数个数大于正数的情况
        else{
            
            while(i!=postive.size() && j!=nagetive.size()){
                A[k++] = nagetive[j++];
                A[k++] = postive[i++];
            }
            while(j!=nagetive.size())A[k++] = nagetive[j++];
        }
        
    }
};

双指针做法

注意同样要判断两种情况, 时间复杂度为O(N), 这个做法会改变

class Solution {
public:
    /*
     * @param A: An integer array.
     * @return: nothing
     */
    void rerange(vector<int> &A) {
        
        int posNum = 0;
        int negNum = 0;
        for(int i : A){
            if(i > 0)
                posNum++;
            else
                negNum++;
        }
        
        if(posNum>=negNum){
            // 偶数下标放正数, 奇数下标放负数
            for(int i=0;i<A.size();i++){
                if(i%2==0 && A[i]>0) continue;
                else if(i%2==1 && A[i]<0) continue;
                else if(i%2==0 && A[i]<0){
                    int j=i+1;
                    while(j<A.size() && A[j]<0) j++; // 找到第一个A[j]>0的位置
                    if(j==A.size()) break;
                    swap(A[i],A[j]);
                }
                else if(i%2==1 && A[i]>0){
                    int j=i+1;
                    while(j<A.size() && A[j]>0) j++; // 找到第一个A[j]<0的位置
                    if(j==A.size()) break;
                    swap(A[i],A[j]);
                    
                }
            }
        }
        
        else{
            // 偶数下标放负数, 奇数下标放正数
            for(int i=0;i<A.size();i++){
                if(i%2==0 && A[i]<0) continue;
                else if(i%2==1 && A[i]>0) continue;
                else if(i%2==0 && A[i]>0){
                    int j=i+1;
                    while(j<A.size() && A[j]>0) j++; // 找到第一个A[j]>0的位置
                    if(j==A.size()) break;
                    swap(A[i],A[j]);
                }
                else if(i%2==1 && A[i]<0){
                    int j=i+1;
                    while(j<A.size() && A[j]<0) j++; // 找到第一个A[j]<0的位置
                    if(j==A.size()) break;
                    swap(A[i],A[j]);
                }
            }
        }
    }
};

如果不改变相对顺序

class Solution {
public:
    /*
     * @param A: An integer array.
     * @return: nothing
     */
    void rerange(vector<int> &A) {
        
        int posNum = 0;
        int negNum = 0;
        for(int i : A){
            if(i > 0)
                posNum++;
            else
                negNum++;
        }
        
        if(posNum>=negNum){
            // 偶数下标放正数, 奇数下标放负数
            for(int i=0;i<A.size();i++){
                if(i%2==0 && A[i]>0) continue;
                else if(i%2==1 && A[i]<0) continue;
                else if(i%2==0 && A[i]<0){
                    int j=i+1;
                    while(j<A.size() && A[j]<0) j++; // 找到第一个A[j]>0的位置
                    if(j==A.size()) break;
                    //swap(A[i],A[j]);               // 如果要不改变位置,不能交换, 只能一位一位的移动
                    int temp = A[j];                 
                    for(int k=j-1;k>=i;k--){
                        A[k+1] = A[k];
                    }
                    A[i] = temp;
                }
                else if(i%2==1 && A[i]>0){
                    int j=i+1;
                    while(j<A.size() && A[j]>0) j++; // 找到第一个A[j]<0的位置
                    if(j==A.size()) break;
                    //swap(A[i],A[j]);
                    int temp = A[j];                
                    for(int k=j-1;k>=i;k--){
                        A[k+1] = A[k];
                    }
                    A[i] = temp;
                    
                }
            }
        }
        
        else{
            // 偶数下标放负数, 奇数下标放正数
            for(int i=0;i<A.size();i++){
                if(i%2==0 && A[i]<0) continue;
                else if(i%2==1 && A[i]>0) continue;
                else if(i%2==0 && A[i]>0){
                    int j=i+1;
                    while(j<A.size() && A[j]>0) j++; // 找到第一个A[j]>0的位置
                    if(j==A.size()) break;
                    //swap(A[i],A[j]);
                    int temp = A[j];                
                    for(int k=j-1;k>=i;k--){
                        A[k+1] = A[k];
                    }
                    A[i] = temp;
                }
                else if(i%2==1 && A[i]<0){
                    int j=i+1;
                    while(j<A.size() && A[j]<0) j++; // 找到第一个A[j]<0的位置
                    if(j==A.size()) break;
                    //swap(A[i],A[j]);
                    int temp = A[j];                
                    for(int k=j-1;k>=i;k--){
                        A[k+1] = A[k];
                    }
                    A[i] = temp;
                }
            }
        }
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值