【问题标题】:Order array such that all positive numbers appear first排序数组,使所有正数首先出现
【发布时间】:2013-01-06 04:29:46
【问题描述】:

我正在用 C# 编写代码来对数组进行排序,我想要右侧的所有负值和左侧的所有正值,不应该按降序排列

namespace SortApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] newInt = new int[] { 5, -2, -1, -4, -20, 6, 7, -14, 15, -16, 8, 9, 10 };
            int size = 12, i= 0;             // or newInt.Length

            for (i = 0; i < newInt.Length; i++)
            {
                if (newInt[i] < 0 && newInt[size] > 0)
                {
                    int temp = newInt[i];
                    newInt[i] = newInt[size];
                    newInt[size] = temp;
                    size--;
                }
            }
            for (i = 0; i < newInt.Length; i++)
            {
                Console.Write(newInt[i]);
                Console.Write(" ");
            }
        }
    }
}

但输出是这样的(-20 在错误的一边):

5 10 9 8 -20 6 7 -14 15 -16 -4 -1 -2

但预期的输出是:

5 10 9 8 15 6 7 -14 -20 -16 -4 -1 -2 

为什么我的代码没有产生预期的输出?

【问题讨论】:

  • @pst 我不同意,他们在询问他们的具体解决方案,这不是一个完整的排序,而只是“在右侧有负面影响”。搜索排序算法并不能解决他们的问题。
  • 预期输出为:5 10 9 8 15 6 7 -14 -20 -16 -4 -1 -2,不便之处敬请见谅
  • 在您预期的输出情况下,排序也不稳定(15 出现在 6 之前),因此,虽然理解算法不正确的原因很重要,但类似这样的东西在 LINQ 中可以工作:@987654324 @

标签: c# arrays sorting


【解决方案1】:

您的解决方案错误地决定了何时结束循环。此外,它在循环头中无条件地增加i,并且从不减少size,即使它指向负数。

以下是解决方法:

for (i = 0; i < size ; ) {
    if (newInt[i] < 0 && newInt[size] >= 0) {
        int temp = newInt[i];
        newInt[i] = newInt[size];
        newInt[size] = temp;
        size--;
        i++;
        continue;
    }
    if (newInt[i] >= 0) {
        i++;
    }
    if (newInt[size] < 0) {
        size--;
    }
}

这是demo on ideone

您可以为leftright 指针使用更易读的标识符来重写此循环,而不是使用isize。这将使您的算法在代码中看起来更加“对称”,以识别其设计中的对称性:

int left = 0, right = newInt.Length-1;
while (left < right) {
    if (newInt[left] < 0 && newInt[right] >= 0) {
        int temp = newInt[left];
        newInt[left] = newInt[right];
        newInt[right] = temp;
        right--;
        left++;
        continue;
    }
    if (newInt[left] >= 0) {
        left++;
    }
    if (newInt[right] < 0) {
        right--;
    }
}

这里是an ideone link to the alternative implementation

【讨论】:

  • @MustansirSabir 欢迎您!如果您的问题已解决,您可能希望通过单击旁边复选标记的灰色轮廓来接受答案。这表明您不再为这个问题寻找改进的解决方案,并为您赢得一个全新的堆栈溢出徽章。
  • 给定数组{0, -1, 1, 0},这将永远不会终止。您需要确定0 被认为是正面还是负面,并相应地调整您的代码(即newInt[right] &gt;= 0)。
  • @JimMischel 说得很好——非常感谢!现在已修复。
【解决方案2】:

试试这个解决方案:

var newInt = new[] {5, -2, -1, -4, -20, 6, 7, -14, 15, -16, 8, 9, 10};
var solution = newInt.GroupBy(i => i > 0).
    SelectMany(g => g).
    ToArray();

您的算法的问题在于,当您减少size 时,您最终会使newInt[size] 指向一个负值,并且不会输入if 块。

【讨论】:

    【解决方案3】:

    一个相当简单的解决方案的总体思路是开始一个索引,在数组的开头将其称为left,在数组的末尾将另一个称为right

    递增left,直到找到负数,或直到left == right。当你遇到负数时,递减 right 直到找到正数,或者直到 right == left

    如果left 正在索引一个负数而right 正在索引一个正数,则交换这两项并再次开始增加left

    总体思路,未经测试:

    int left = 0;
    int right = a.Length-1;
    while (left < right)
    {
        if (a[left] < 0)
        {
            while (right > left)
            {
                if (a[right] >= 0)
                {
                    // swap here
                    int temp = a[left];
                    a[left] = a[right];
                    a[right] = temp;
                    break;
                 }
                 --right;
            }
        }
        ++left;
    }
    

    【讨论】:

      【解决方案4】:

      这会以最少的循环产生所需的顺序

      int[] newInt = new int[] { 5, -2, -1, -4, -20, 6, 7, -14, 15, -16, 8, 9, 10 };
      int lt = 0;
      int rt = newInt.Length - 1;
      while (true) {
          // Find first negative number
          while (newInt[lt] >= 0 && lt < rt) {
              lt++;
          }
      
          // Find last positive number
          while (newInt[rt] < 0 && rt > lt) {
              rt--;
          }
      
          if (lt == rt) {
              break; // Finished
          }
      
          // Swap
          int temp = newInt[lt];
          newInt[lt] = newInt[rt];
          newInt[rt] = temp;
      }
      //TODO: Print result
      

      【讨论】:

      • 给定数组{0, -1, 1, 0},这将永远不会终止。它将永远交换第一个和最后一个项目。 0 是正面还是负面?
      • 你是对的。我现在将 0 视为阳性。另一种可能性是在正数和负数之间放置 0。但这需要额外的治疗。
      【解决方案5】:

      如果您可以使用泛型和 linq,那么最简单的解决方案就是:

      int[] newInt = new int[] { 5, -2, -1, -4, -20, 6, 7, -14, 15, -16, 8, 9, 10 };
      newInt.ToList().Sort();
      newInt.Reverse();
      newInt = newInt.ToArray();
      

      希望这会有所帮助!

      【讨论】:

      • Sort的返回类型是void
      • OP 不想排序。他想要 2 个分区,每个分区一个用于负值和正值
      • @pst -> “不应该是递减顺序”,看源代码逻辑,他想把所有的nevatives移到右边(没有任何排序)
      • Kundan 我故意不想以任何顺序对数字进行排序我只想将所有负值放在右边,所有正值放在左边,不想使用任何 bult -in 函数,你的代码肯定会运行良好
      • @Tilak 不,这是不正确的,正常的排序达到预期的结果。他/她显然不在乎订购。查看预期的输出情况。
      猜你喜欢
      • 1970-01-01
      • 2018-09-02
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 2021-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多