(3/500)在线性时间内对二进制数组排序
来源:互联网 发布:mysql高级视频教程 编辑:程序博客网 时间:2024/06/07 10:54
给定一个二进制数组(数组元素是0和1),请对数组进行排序,要求时间复杂度为O(n),空间复杂度为O(1)。输出内容应该是所有的0在前,之后是所有的1。
例如,
输入:{ 1, 0, 1, 0, 1, 0, 0, 1 }
输出:{ 0, 0, 0, 0, 1, 1, 1, 1 }
1. 傻瓜式方法
一种简单的方法是计算数组中0的个数(假设为k),然后把数组的前k个元素置为0,其他的置为1。同样道理,也可以计算1的个数(假设为k),然后把前面的k个元素置为1,其他的置为0。二者选一即可。实现方式比较简单,代码就省略了。
2. 填充0的另一种想法
和计算0的个数相比,我们可以换种方法。如果当前元素是0,我们可以把0放到下一个可用的位置。在所有的元素都处理了之后, 把其它所有的元素都置为1。
C++语言实现:
#include <bits/stdc++.h>using namespace std; // Function to sort binary array in linear timeint Sort(int A[], int n){ // k stores index of next available position int k = 0; // do for each element for (int i = 0; i < n; i++) { // if current element is zero, put 0 at next free // position in the array if (A[i] == 0) A[k++] = 0; } // fill all remaining indexes by 1 for (int i = k; i < n; i++) A[k++] = 1;} // main functionint main(){ int A[] = { 0, 0, 1, 0,1, 1, 0, 1, 0, 0 }; int n = sizeof(A)/sizeof(A[0]); Sort(A, n); // print the rearranged array for (int i = 0 ; i < n; i++) cout << A[i] << " "; return 0;}java语言实现:
class SortBinaryArray{ // Function to sort binary array in linear time public static void Sort(int A[], int n) { // k stores index of next available position int k = 0; // do for each element for (int i = 0; i < n; i++) { // if current element is zero, put 0 at next free // position in the array if (A[i] == 0) A[k++] = 0; } // fill all remaining indexes by 1 for (int i = k; i < n; i++) A[k++] = 1; } // main function public static void main (String[] args) { int A[] = { 0, 0, 1, 0, 1, 1, 0, 1, 0, 0 }; int n = A.length; Sort(A, n); // print the rearranged array for (int i = 0 ; i < n; i++) System.out.print(A[i] + " "); }}
输出: 0 0 0 0 0 0 1 1 1 1
以上两种方案的时间复杂度都是O(n),空间复杂度都是o(1)。
3. 基于快速排序分而治之的算法
除了以上两种方法,我们还可以借用快速排序中分而治之的思想。这种方法的关键是使用1作为主元素(pivot element),然后创建一个分区过程,最后的结果就是排好序的。
C++语言实现:
#include <bits/stdc++.h>using namespace std; // Function to sort binary array in linear timeint Partition(int A[], int n){ int pivot = 1; int j = 0; // each time we encounter a 0, j is incremented and // 0 is placed before the pivot for (int i = 0; i < n; i++) { if (A[i] < pivot) { swap(A[i], A[j]); j++; } }} // main functionint main(){ int A[] = { 1, 0, 0, 0, 1, 0, 1, 1 }; int n = sizeof(A)/sizeof(A[0]); Partition(A, n); // print the rearranged array for (int i = 0 ; i < n; i++) cout << A[i] << " "; return 0;}
java语言实现:
class SortBinaryArray{ // Function to sort binary array in linear time public static void Sort(int A[], int n) { int pivot = 1; int j = 0; // each time we encounter a 0, j is incremented and // 0 is placed before the pivot for (int i = 0; i < n; i++) { if (A[i] < pivot) { // swap (A[i], A[j]) int temp = A[i]; A[i] = A[j]; A[j] = temp; j++; } } } // main function public static void main (String[] args) { int A[] = { 0, 0, 1, 0, 1, 1, 0, 1, 0, 0 }; int n = A.length; Sort(A, n); // print the rearranged array for (int i = 0 ; i < n; i++) System.out.print(A[i] + " "); }}
输出: 0 0 0 0 0 0 1 1 1 1
尽管以上各种方法时间复杂度是O(n),空间复杂度是O(1),明显第三种方法的时间更少。
4. 通过首尾两个索引排序
我还能想到另外一种解决方案,新建两个索引分别指向首尾(head 和 end),向中间聚拢,当head指向的数字不为0,并且end指向的数字不为1时,交换它们的位置,直到head大于或等于end。
闲话少说,上代码。偷一下懒,我就只写Java代码了。
public class SortBinaryArray2 { // Function to sort binary array in linear time public static void Sort(int A[], int n) { int head = 0; int end = A.length - 1; while( head < end ) { while( A[head] == 0 && head < A.length -1 ) { head ++; } while( A[end] == 1 && end > 0 ) { end --; } if( head >= end ) { break; } int temp = A[head]; A[head] = A[end]; A[end] = temp; } } public static void main(String[] args) { int A[] = { 0, 0, 1, 0, 1, 1, 0, 1, 0, 0 }; int n = A.length; Sort(A, n); // print the rearranged array for (int i = 0 ; i < n; i++) { System.out.print(A[i] + " "); } }}
这种方法是不是更省时? ^_^
练习:
1. 在原方案的基础上修改方案,把1放在前面。
2. 给定一个数组,在线性时间内(时间复杂度为O(n))排序,使所有的偶数排在奇数之前。
- (3/500)在线性时间内对二进制数组排序
- 排序---->在线性时间内排序
- 排序---->在线性时间内排序
- 一道排序笔试题,在o(n)时间内对一个数组进行排序
- 线性时间内求最大子数组和
- (p112)在O(n)时间内,对0到n^3-1区间内的n个整数进行排序
- 算法导论 学习笔记 第八章 线性时间内的排序
- 对线性表(例如整形数组的各种排序)
- 给定无序数组A,在线性时间内找到i和j,j>i,并且保证A[j]-A[i]是最大的。
- 线性时间内从一个数组中找出第K个最小的元素
- 先对数组排序,在进行折半查找(C++)
- 通过划分的方式在线性时间内找出一个序列中第K大的元素
- 选择算法-在线性时间内选择任意第几个小(大)的数
- 在线性时间内,求一组数中的第k大的数字
- 在线性时间内查询一组数的最大子向量和
- 对二维数组排序
- 对数组排序
- 对数组进行排序
- java基础第一章_进制
- mac 下配置GLEW + GLFW
- LeetCode 303. Range Sum Query
- 超全整理!Linux性能分析工具汇总合集
- jQuery中的DOM节点的创建与多种插入方式
- (3/500)在线性时间内对二进制数组排序
- 基本数据类型
- 安卓查看特定文件,并按钮查看下一个或上一个
- 【Maven学习】maven中依赖的配置详解
- CSS的伪类选择器
- 静态 常量 同步
- sql365 行转列,同时根据公司编码带上公司名称
- XSS也能getshell
- 我们离所谓的优秀有多远