重新排列包含正数和负数的数组

给定一个包含正数和负数的整数数组,重新排列它,使得所有的负数排在前面,所有的正数排在后面。正数间和负数间的相对顺序保持不变。期望时间复杂度是O(n), 空间复杂度是O(1).

例如: 给定 [-1,2,-2,3,5,-4], 重新排列后变成 [-1,-2,-4,2,3,5]

分析: 1. 最简单的算法是O(n^2), 遇到每个负数都把它移动到数组前面已经排列好的负数部分后面。

2. O(n)的算法暂时没想出来,似乎比较难,下面给出一个O(nlogn)的算法。基本思想类似于Merge Sort. 空间复杂度由于用到递归,是O(logn). 不过可以很容易改写为bottom-up的迭代版本。

void Main()
{
	int[] nums = new int[] {-1, 2, -2, 3, 5, -4};

	Reorder(nums, 0, nums.Length-1);
}

// Define other methods and classes here
public void Reorder(int[] nums, int start, int end)
{
    if(start >= end) {
	    return;
	}

	int middle = start + (end-start)/2;
	Reorder(nums, start, middle);
	Reorder(nums, middle+1, end);
	Merge(nums, start, middle, end);
}

private void Merge(int[] nums, int start, int end)
{
    int i = start;
	while(nums[i] < 0 && i <= end) i++;
	int j = end;
	while(nums[j] >= 0 && j >= start) j--;

	// Shift the negative part to the front
	if(i < j) {
	   int k = j;
	   while(k>=i && nums[k]<0) k--;

	   Reverse(nums, i, k);
	   Reverse(nums,k+1,j);
	   Reverse(nums,i,j);
	}
}

private void Swap(int[] nums, int i, int j)
{
    int t = nums[i];
	nums[i] = nums[j];
	nums[j] = t;
}

private void Reverse(int[] nums, int i, int j)
{
    while(i < j) {
	    Swap(nums, i, j);
		i++;
		j--;
	}
}

下面是自底向上的迭代版本。空间复杂度是O(1).

public void Reorder(int[] nums)
{
    int n = nums.Length;

	for(int size = 1; size < n; size += size)
	{
	    for(int low = 0; low < n-size; low+=size+size)
		{
		    Merge(nums, low, Math.Min(low+size+size-1, n-1));
		}
	}
}

  

时间: 2024-10-13 15:02:09

重新排列包含正数和负数的数组的相关文章

给定一个只包含正整数的非空数组,返回该数组中重复次数最多的前N个数字 ,返回的结果按重复次数从多到少降序排列(N不存在取值非法的情况)

1 """ 2 #给定一个只包含正整数的非空数组,返回该数组中重复次数最多的前N个数字 3 #返回的结果按重复次数从多到少降序排列(N不存在取值非法的情况) 4 解题思路: 5 1.设定一个空字典,去存储列表中的值和值出现的次数 6 2.使用L.count()方法可以统计出L中值出现的次数 7 3.使用sorted方法可以进行排序,sorted(iterable,key,reverse) 8 注意key是函数 9 4.列表中的元祖取值 d[i][j] i是哪一个元祖,j是元祖

输入一个整形数组(可能有正数和负数),求数组中连续子数组(最少有一个元素)的最大和。要求时间复杂度为O(n)(解决)

输入一个整形数组(可能有正数和负数),求数组中连续子数组(最少有一个元素)的最大和.要求时间复杂度为O(n). 输入描述: [重要]第一行为数组的长度N(N>=1) 接下来N行,每行一个数,代表数组的N个元素 输出描述: 最大和的结果 输入例子1: 8 1 -2 3 10 -4 7 2 -5 输出例子1: 18 思路:对输入的数组进行计算, import java.util.Scanner; public class Main { public static void main(String[]

真正的正数、负数、整数等正则表达式,网上好多都是错的

1 /// <summary> 2 /// 判断字符串是否是数字 3 /// </summary> 4 /// <param name="str"></param> 5 /// <param name="nt"></param> 6 /// <returns></returns> 7 /// <summary> 8 public static bool IsN

C#设置textBox只能输入数字(正数,负数,小数)简单实现

/* *设置textBox只能输入数字(正数,负数,小数) */ public static bool NumberDotTextbox_KeyPress(object sender, KeyPressEventArgs e) { //允许输入数字.小数点.删除键和负号 if ((e.KeyChar < 48 || e.KeyChar > 57) && e.KeyChar != 8 && e.KeyChar != (char)('.') && e

例6:设缓冲区DATA中有一组单字节有符号数,以0为结束标志。写一个程序实现如下功能:把前5个正数依次送入缓冲区PDATA,把前5个负数依次送入缓冲区MDATA;如正数或负数不足5个,则用0补足。

自解: 1 DSEG SEGMENT 2 DATA DB -1,1,-2,2,3,-3,-4,4,5,-5,-6,6,0 3 PDATA DB 0,0,0,0,0 4 MDATA DB 0,0,0,0,0 5 DSEG ENDS 6 ;------------------------------------ 7 CSEG SEGMENT 8 ASSUME DS:DSEG,CS:CSEG 9 START: 10 MOV AX,DSEG 11 MOV DS,AX 12 13 MOV BX,OFFSE

6个包含EGPCS信息的全局数组

$HTTP_COOKIE_VARS(简写:$_COOKIE) 包含作为请求的一部分进行传递的cookie值,数组的键是cookie名. $HTTP_GET_VARS(简写:$_GET) 包含做为GET请求的一部分进行传递的参数,数组的键是表单参数名称. $HTTP_POST_VARS(简写:$_POST) 包含做为POST请求的一部分进行传递的参数,数组的键是表单参数名. $HTTP_POST_FILES(简写:$_FILES) 包含有关上传文件的信息. $HTTP_SERVER_VARS(简写

编一个程序,输入10个整数,并放在数组中,先降序输出全部的数,再统计并输出当中正数、负数和零的个数

public class Demo1 { public static void main(String[] args) { List<Integer> list = new ArrayList<Integer>(); list.add(-1); list.add(-2); list.add(-4); list.add(0); list.add(2); list.add(5); list.add(9); list.add(7); list.add(-9); list.add(-7);

偶然在博客中见对百度一个面试题的探讨,写些自己的看法以及指出探讨中不对的观点:百度面试题:求绝对值最小的数 有一个已经排序的数组(升序),数组中可能有正数、负数或0,求数组中元素的绝对值最小的数,要求,不能用顺序比较的方法(复杂度需要小于O(n)),可以使用任何语言实现 例如,数组{-20,-13,-4, 6, 77,200} ,绝对值最小的是-4。

今天申请了博客园账号,在下班后阅览博客时发现了一个关于百度面试题探讨的博客(其实是个很基础的问题),此博客url为:http://www.blogjava.net/nokiaguy/archive/2013/01/30/394920.html 其中下面有人评论为: 有序列表查找显然二分啊,博主貌似对java的arrays和collections不是很熟. private static int getMinAbsoluteValue(final int[] source) { int index

python_exercise_给定一个只包含正整数的非空数组,返回该数组中重复次数最多的前N个数字 ,返回的结果按重复次数从多到少降序排列(N不存在取值非法的情况)

# 设定给出的非空数组为list_a,如下list_a = [8,1,3,5,1,2,45,8,5,7,7,8,8,8,8,8,8,5,5] # 将list_a去重,留下唯一值list_a_set = set(list_a) # 将list_a去重后的值作为字典的key放到字典中list_a_dict = {x:None for x in list_a_set} # 遍历将list_a去重后的唯一值,统计唯一值出现的次数.把次数作为字典的value放到字典中for l in list_a_set