简体   繁体   English

一种线性时间算法,可重新排列负整数和正整数,中间有零

[英]A linear-time algorithm that rearrange negative and positive integers with zeroes in between

Problem:问题:

  • Array has positive, negative, and 0 integers, and values are not necessarily unique.数组有正数、负数、0整数,值不一定唯一。
  • The positive values are to the right of zeroes, and the negative values are to the left of zeroes.正值在零的右边,负值在零的左边。 The positive and the negative values do not have to be sorted.不必对正值和负值进行排序。 However, the zeros must be in between the positive and negative integers.但是,零必须在正整数和负整数之间。
  • The algorithm must run in linear time .该算法必须在线性时间内运行。

Some acceptable answers I can think of are the following:我能想到的一些可接受的答案如下:

  • [-3, -1, -9, 0, 5, 2, 9]
  • [-5, -2, 0, 0, 5, 2, 9]
  • [-3, 0, 0, 0, 4, 1]

My thought process and attempts:我的思考过程和尝试:

The process is very similar to the quicksort algorithm where we can choose 0 to be our pivot point.该过程与快速排序算法非常相似,我们可以选择 0 作为我们的 pivot 点。 Ideally, this shouldn't be an issue because we can simply search for the index of 0 and set that index as our pivot point to replace at the end.理想情况下,这应该不是问题,因为我们可以简单地搜索 0 的索引并将该索引设置为我们的 pivot 点以在最后替换。 However, from what I understand the search process itself requires at least O(nLog(n)) run time (such as binary search), and therefore cannot be used in this case.但是,据我了解,搜索过程本身至少需要 O(nLog(n)) 运行时间(例如二进制搜索),因此不能在这种情况下使用。

One extreme solution to this that I can think of that runs in a linear time is using the linear select algorithm where we split the array into subgroups of 5 and find the median of the medians of the subgroups.我能想到的一个在线性时间内运行的极端解决方案是使用线性 select 算法,在该算法中,我们将数组分成 5 个子组并找到子组中位数的中位数。 However, I doubt this will work since the median isn't always going to be 0, therefore the pivot point isn't always guaranteed to be 0.但是,我怀疑这是否可行,因为中位数并不总是为 0,因此 pivot 点并不总是保证为 0。

What's really throwing me off in the problem is that the negative and positive integers do not have to be sorted but simultaneously must be partitioned by zeroes.真正让我失望的是,负整数和正整数不必排序,但同时必须用零分区。

What I have so far:到目前为止我所拥有的:

I was able to modify the partitioning process of the quick sort algorithm.我能够修改快速排序算法的分区过程。 The following runs in a linear time, but the problem is that it is not able to place the zeroes in the appropriate positions.以下以线性时间运行,但问题是它无法将零放置在适当的位置。

This is the output that I am able to get with the current progress I have:这是 output ,我目前的进展情况如下:

void partition(T a[], int lo, int n) {
    size_t i = lo, j;
    for (j = i; j < n; j++){
        if (a[j] < 0){
          std::swap(a[i], a[j]);
          i++;
        }
    }
}

Using array of [9, -3, -6, 1, 3,4,-22,0]使用[9, -3, -6, 1, 3,4,-22,0]
Output of the code is [ -3 -6 -22 1 3 4 9 0 ] Output 的代码是[ -3 -6 -22 1 3 4 9 0 ]

Thank you very much in advance for any feedback that you may have.非常感谢您提供任何反馈。

A simple linear algorithm in two iterations can be to first push all negative numbers to the left, and in a second iteration push all positives numbers to the right.两次迭代中的简单线性算法可以是首先将所有负数推向左侧,然后在第二次迭代中将所有正数推向右侧。

void rearrange(T a[], int n) {
  int next_to_place= 0;
  for (int i = 0; i < n; i++) {
    if (a[i] < 0) {
      std::swap(a[i], a[next_to_place++]);
    }
  }
  for (int i = next_to_place; i < n; i++) {
    if (a[i] == 0) {
      std::swap(a[i], a[next_to_place++]);
    }
  }
}

This is suboptimal, as you can probably solve it with a single iteration (which will be more cache friendly), but it is linear and simple to understand.这是次优的,因为您可能可以通过一次迭代来解决它(这将更加缓存友好),但它是线性的并且易于理解。

You can achieve this by maintaining the count of zeroes and storing the positive numbers and negative numbers in a seperate vector/list.您可以通过保持零计数并将正数和负数存储在单独的向量/列表中来实现这一点。

Please see the following implementation (self explanatory):请参阅以下实现(不言自明):

#include <iostream>
#include <vector>

int main()
{
    int arr[7] = {-3, -1, -9, 0, 5, 2, 9};
    
    int n = sizeof(arr)/sizeof(int);
    
    int count_zeros = 0;
    int count_positives = 0;
    int count_negatives = 0;
    
    std::vector<int> negative_numbers;
    std::vector<int> positive_numbers;
    
    for(int i=0;i<n;i++){
        
        if(arr[i] == 0){
            count_zeros ++;
        }
        
        else if(arr[i] > 0){
            
            positive_numbers.push_back(arr[i]);
        }
        
        else if(arr[i] < 0){
            
            negative_numbers.push_back(arr[i]);
        }
    }
    
    //Print all negative numbers:
    for(int i=0;i<negative_numbers.size();i++){
        std::cout<<negative_numbers[i] << " ";
    }
    
    //Print all zeroes:
    for(int i=0;i<count_zeros;i++){
        std::cout<< 0 << " ";
    }
    
    //Print all positive numbers:
    for(int i=0;i<positive_numbers.size();i++){
        std::cout<<positive_numbers[i] << " ";
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM