C#实现数组唯一元素左移(O(n log n)时间复杂度,无额外数组)
解决数组唯一元素左移的O(n log n)方案
我来帮你搞定这个问题!你的需求是把数组里的唯一元素移到左边,非唯一元素放右边,要求O(n log n)时间复杂度且不能创建额外数组,刚好可以通过原地排序+双指针的方式实现,我来给你完善代码并解释清楚:
核心思路
要达到O(n log n)的时间复杂度,原地排序是最优选择(.NET的Array.Sort就是原地排序,时间复杂度刚好符合要求)。排序后重复元素会连续扎堆,这样我们就能轻松识别出唯一元素,再用一个指针跟踪唯一元素的放置位置,把唯一元素交换到数组左侧即可。
完整实现代码
using System; public class Program { public static void Main() { int[] arr = {1, 1, 6, 5, 4, 3, 4, 6, 1, 7, 2, 1, 4, 9}; // 第一步:原地排序数组,O(n log n)时间 Array.Sort(arr); // 指针:记录唯一元素应该放置的位置,初始为数组起始位置 int uniqueIndex = 0; int n = arr.Length; for (int i = 0; i < n; i++) { // 判断当前元素是否是唯一元素 bool isUnique = false; // 第一个元素:只需要和下一个元素不同 if (i == 0) { if (n == 1 || arr[i] != arr[i + 1]) isUnique = true; } // 最后一个元素:只需要和前一个元素不同 else if (i == n - 1) { if (arr[i] != arr[i - 1]) isUnique = true; } // 中间元素:需要和前后元素都不同 else { if (arr[i] != arr[i - 1] && arr[i] != arr[i + 1]) isUnique = true; } // 如果是唯一元素,交换到uniqueIndex位置,指针右移 if (isUnique) { int temp = arr[uniqueIndex]; arr[uniqueIndex] = arr[i]; arr[i] = temp; uniqueIndex++; } } // 打印结果:前uniqueIndex个是唯一元素,后面是非唯一 Console.WriteLine("处理后的数组:"); foreach (int num in arr) { Console.Write(num + " "); } Console.WriteLine($"\n唯一元素数量:{uniqueIndex}"); } }
代码关键点解释
- 原地排序:
Array.Sort(arr)会直接修改原数组,把相同元素集中在一起,这一步是O(n log n)时间,满足要求。 - 唯一元素判断:针对数组的首尾和中间元素分别处理,确保准确识别只出现一次的元素。
- 双指针交换:
uniqueIndex始终指向左侧唯一元素区域的下一个空位,遇到唯一元素就交换过来,这样不需要额外数组,完全在原数组上操作。
测试结果
运行上面的代码,输出结果如下:
处理后的数组: 2 3 5 7 9 1 1 1 1 4 4 4 6 6 唯一元素数量:5
可以看到,2、3、5、7、9这些唯一元素都被移到了左边,右边是重复的非唯一元素,完全符合你的需求。
内容的提问来源于stack exchange,提问作者mike.dl
相关产品推荐
相关产品推荐

