谜题:在一次解析中对包含 0 和 1 的数组进行排序。

Posted

技术标签:

【中文标题】谜题:在一次解析中对包含 0 和 1 的数组进行排序。【英文标题】:Puzzle: Sort an array of 0's and 1's in one parse. 【发布时间】:2013-07-27 21:05:10 【问题描述】:

是否可以在不使用辅助数组的情况下在一次解析中按降序排列仅由 1 和 0 组成的数组? 例如:假设您有一个数组a[]=1,0,0,0,1,0,1,为此预期的输出将是a[]=1,1,1,0,0,0,0

我已经编写了下面的 C 代码,但它在 2 次解析中找到了解决方案。可以优化吗?

void arrange(int a[],int n) 
    int i,count=0;
    for(i=0;i<n;i++) 
            if(a[i]==1)
                    count++;
            a[i]=0;
    
    for(i=0;i<count;i++) 
            a[i]=1;
    

【问题讨论】:

您在寻找什么样的优化?一次数据传递? 是的,解决方案应该是一次解析。 Parse 和 pass 是不同的东西,即使它们的发音相同(它们可能是某些人的同音字)。您的代码代表一个解析。 【参考方案1】:
for (size_t i = 0, count = 0; i < n; i++) 
  if (a[i] == 1) a[count++] = 1;
  if (i >= count) a[i] = 0;

【讨论】:

如果 a[0] 最初是 1 怎么办? 糟糕。谢谢,吉姆,我会解决这个问题的。 @Inspired 我认为a[count+=a[i]] |= a[i] 将不再需要第一个if 声明。第二个 if 也可以删除,如果我们将循环分成两个,第一个循环遍历 1 直到遇到 0,第二个循环从那里接替。 @unxnut 那么代码将是无分支的,太好了。在我看来,count 的初始值应该是 -1,因为 a[count+=a[i]] 太早增加了count 我喜欢这个。这对我来说很不明显,这是正确的:-)【参考方案2】:

让我试试这个:

void arrange(int a[],int n)

    int* p = a;
    int* q = &a[n-1];

    while (p <= q) 
    
        while (*p == 1 && p <= q) /* Find a Zero, starting from the front */
        
            ++p;
        
        while (*q == 0 && p <= q) /* Find a One, starting from the back */
        
            --q;
        

        if (p < q) /* *p == Zero, and *q == One, and p is to the left of q. */
        
            *p = 1; 
            *q = 0;
        
    

这适用于两个指针,一个从前面开始,另一个从后面开始,它们都向中间移动直到相遇。

一路上,如果两个指针在左边找到一个0,在右边找到一个1,交换值,然后继续。

(代码未经测试,但轮廓看起来很扎实)

【讨论】:

谢谢,我编译好了。它工作正常。当我在参数 n 中发送大小时,我们需要将代码 int* q = &amp;a[n] 更改为 int* q = &amp;a[n-1] 好主意,但似乎有点太复杂了:) 它们确实有道理,但在格式化为评论时却没有。我会将我的代码粘贴到答案中,然后将其删除 - 你可以看到。 @JonathanLeffler;您应该为您的代码制作并附上屏幕截图链接(对于 @hacks:它太大而不能成为一个好的屏幕截图,它是对答案的评论(尽管是一个很大的评论),这就是为什么它被删除为非答案的原因。努力达到 10k,你也可以看到它。 :D【参考方案3】:

递归呢?一如既往的简洁优雅。

void countAndRewrite(int arr[], size_t n, size_t *cone, size_t total)

    if (n) 
        if (arr[0])
            ++*cone;

        countAndRewrite(arr + 1, n - 1, cone, total);
        arr[0] = total - n < *cone;
    


int main()

    int arr[] =  0, 1, 0, 1, 1, 1, 0 ;
    size_t cone = 0;
    countAndRewrite(arr, 7, &cone, 7);
    for (size_t i = 0; i < 7; i++)
    printf("arr[%zu] = %d\n", i, arr[i]);

    return 0;

【讨论】:

理解起来有点复杂,我通常避免递归解决方案。无论如何感谢您的帮助:) 优雅,是的,但简单? :) 不错的解决方案。 @Inspired 谢谢!同样,这取决于您的口味 :) 我觉得它很直观。也许我只是忙于实现我的虚拟机,我总是从堆栈的角度思考:P @H2CO3 好吧,对于二叉树:queue.push(root); while (!queue.empty()) node = queue.front(); queue.pop(); if (node!=NULL) process_node(node); queue.push(node-&gt;left); queue.push(node-&gt;right); :) @Inspired 是的,就是这样!【参考方案4】:

试一试!

(读取 cmets):

#include<stdio.h>
int main(void)
    int a[]=1,0,0,0,1,0,1;
    int n = 7,
        i,
        index = 0;

   while(index < n && a[index]) index++; // skip initial 1's
   for(i = index; i < n; i++)  
     if(a[i]) a[index++] = 1; // if `1` at a[i] make its 0 and
     a[i] = 0;                // make at index 1. 
   

   for(i = 0; i < n; i++)
        printf("%3d", a[i]);
   
    return 1;

检查工作代码@ideone的链接:

案例 1: 1,0,0,0,1,0,1案例 2: 1,0,1,1,1,0,0,1,0,1, 1案例 3: @987654323 @案例 4: 0, 0, 0, 0, 0, 0, 0案例 5: 0, 0, 0, 1, 1, 1, 1

所以我认为它是正确的! 很简单,只需要n 迭代。 复杂性明智O(n)

【讨论】:

我认为1,0,0,1,1,0,1会失败让我检查一下 这对于1,1,1,...,1 将失败(超出while 循环中的数组边界)。 所有解决方案(甚至 2 次通过)的时间复杂度为 O(n),因为 O(n) = O(2*n)。 @Inspired 是的,它只需要n 迭代甚至没有 2n ..更好一点...不? @GrijeshChauhan 更好,是的,但仍然是 O(n) 或 O(2*n) 或 O(1000*n)。我只是在强调大O的含义。【参考方案5】:

只是另一种方式。

有两个枢轴,一个从开始,另一个在结束,如下所示,

for(int i=0, j=n-1;i<j;)

if(a[i]==1 && a[j]==0) swap(a[i],a[j]);
else if(a[i]==1 && a[j]==1) j--;
else if(a[i]==0 && a[j]==0) i++;
else if(a[i]==0 && a[j]==1) j--; i++;

【讨论】:

【参考方案6】:
#include<iostream>

using namespace std;

int main() 
    int arr[] = 1, 1, 1, 1, 1, 0, 0, 0;
    int N = sizeof(arr) / sizeof(arr[0]);
    int p = 0, q = 1;

while (q != N) 
    if (arr[p] > arr[q]) 
        arr[p] = 0;
        arr[q] = 1;
        p++;
        q++;
    
    else 
        q++;
        if (arr[p] == 0)
            p++;
    


for (int i = 0; i < N; i++)
    cout << arr[i];

return 0;

【讨论】:

以上是关于谜题:在一次解析中对包含 0 和 1 的数组进行排序。的主要内容,如果未能解决你的问题,请参考以下文章

数据结构与算法之深入解析“滑动谜题”的求解思路与算法示例

如何在python中对存储xy坐标的二维数组进行排序?

如何在 .Net 中创建和解析标签、长度、值 (TLV) 并在 Base64 中对其进行编码

如何在 PHP 数组中对格式项目进行编号

如何在iOS中对包含数字和名称的字符串数组进行排序

LeetCode——滑动谜题