Interleaving Positive and Negative Numbers

原题链接 : http://lintcode.com/zh-cn/problem/interleaving-positive-and-negative-numbers/

Given an array with positive and negative integers. Re-range it to interleaving with positive and negative integers.

注意

You are not necessary to keep the original order or positive integers or negative integers.

样例

Given [-1, -2, -3, 4, 5, 6], after re-range, it will be [-1, 5, -2, 4, -3, 6] or any other legal answer.

挑战

Do it in-place and without extra memory.

SOLUTION 1:

1. 先用parition把数组分为左边为负数,右边为正数。

2. 如果负数比较多,把多余的负数与尾部的值交换。(这样多余的数会放在数组的末尾)

3. left 指向数组的左边,right指向数组的右边减掉多余的数。

4. 第3步中,根据是正数多,还是负数多,起始位置要变一下。正数多,我们希望开始的是正数:

例如 3 -1 2

负数多,我们希望开始的是负数,如 -1 3 -2

5. 不断交换left, right指针,并一次前进步长2. 直到left, right 相遇。

 class Solution {
/**
* @param A: An integer array.
* @return an integer array
*/
// SOLUTION 2: 判断正数多还是负数多。
public static int[] rerange(int[] A) {
// write your code here // Check the input parameter.
if (A == null || A.length == 0) {
return A;
} int len = A.length; int left = -1;
int right = A.length; // divide the negative and positive integers.
while (true) {
while (left < A.length - 1 && A[++left] < 0); while (left < right && A[--right] > 0); if (left >= right) {
break;
} swap(A, left, right);
} // LEFT: point to the first positive number.
int negNum = left;
int posNum = len - left; int les = Math.min(negNum, posNum);
int dif = Math.abs(negNum - posNum); // 如果负数比较多,把多的负数扔到后面去
if (negNum > posNum) {
int cnt = dif;
int l = les;
int r = len - 1;
while (cnt > 0) {
swap(A, l, r);
l++;
r--;
cnt--;
} // 负数多的时候,负数在前,反之,正数在前
left = -1;
// 跳过右边不需要交换的值
right = A.length - dif;
} else {
// 正数在前
left = -2;
// 跳过右边不需要交换的值
right = A.length - dif + 1;
} /*
-1 -2 -5 -6 3 4 les = 2;
4 -2 -5 -6 3 -1
*/
// swap the negative and the positive
while (true) {
left += 2;
right -= 2; if (left >= les) {
break;
}
swap(A, left, right);
} return A;
} public static void swap(int[] A, int n1, int n2) {
int tmp = A[n1];
A[n1] = A[n2];
A[n2] = tmp;
}
}

SOLUTION 2(December 23th Refresh):

1. 扫一次确定是正数多还是负数多

2. 把奇数索引的所有的数字进行partition,如果是正数多,把正数放在后面,否则负数放在后面。

3. 令Index 1 = 奇数列,index 2 = 偶数列,扫描一次,遇到不符合正负条件的数字进行交换即可

 public static void swap(int[] A, int n1, int n2) {
int tmp = A[n1];
A[n1] = A[n2];
A[n2] = tmp;
} /*
Solution 2:
*/
public static int[] rerange(int[] A) {
// write your code here // Check the input parameter.
if (A == null || A.length <= 2) {
return A;
} int len = A.length; int cntPositive = 0; for (int num: A) {
if (num > 0) {
cntPositive++;
}
} // If positive numbers are more than negative numbers,
// Put the positive numbers at first.
int posPointer = 1;
int negPointer = 0; // means
boolean pos = false; if (cntPositive > A.length / 2) {
// Have more Positive numbers;
posPointer = 0;
negPointer = 1; pos = true;
} int i = 1;
int j = len - 2; if (pos) {
while (true) {
// Put the positive numbers at the end.
if (i < len && A[i] < 0) {
i += 2;
} if (j > i && A[j] > 0) {
j -= 2;
} if (i >= j) {
break;
} swap(A, i, j);
}
} else {
while (true) {
// Put the negative numbers at the end.
if (i < len && A[i] > 0) {
i += 2;
} if (j > i && A[j] < 0) {
j -= 2;
} if (i >= j) {
break;
} swap(A, i, j);
}
} // Reorder the negative and the positive numbers.
while (true) {
// Should move if it is in the range.
while (posPointer < len && A[posPointer] > 0) {
posPointer += 2;
} // Should move if it is in the range.
while (negPointer < len && A[negPointer] < 0) {
negPointer += 2;
} if (posPointer >= len || negPointer >= len) {
break;
} swap(A, posPointer, negPointer);
} return A;
}

SOLUTION 3(December 23th Refresh):

在SOL2的基础上改进:

1. 在统计正负数个数时,把负数放在最后。

2. 如果发现正数比较多,把数列翻转。

3. 令Index 1 = 奇数列,index 2 = 偶数列,扫描一次,遇到不符合正负条件的数字进行交换即可

 /*
Solution 3:
*/
public static int[] rerange(int[] A) {
// write your code here // Check the input parameter.
if (A == null || A.length <= 2) {
return A;
} int len = A.length; int cntPositive = 0; // store the positive numbers index.
int i1 = 0; for (int i2 = 0; i2 < len; i2++) {
if (A[i2] > 0) {
cntPositive++; // Put all the positive numbers at in the left part.
swap(A, i1++, i2);
}
} // If positive numbers are more than negative numbers,
// Put the positive numbers at first.
int posPointer = 1;
int negPointer = 0; if (cntPositive > A.length / 2) {
// Have more Positive numbers;
posPointer = 0;
negPointer = 1; // Reverse the array.
int left = 0;
int right = len -1;
while (left < right) {
int tmp = A[left];
A[left] = A[right];
A[right] = tmp;
left++;
right--;
}
} // Reorder the negative and the positive numbers.
while (true) {
// Should move if it is in the range.
while (posPointer < len && A[posPointer] > 0) {
posPointer += 2;
} // Should move if it is in the range.
while (negPointer < len && A[negPointer] < 0) {
negPointer += 2;
} if (posPointer >= len || negPointer >= len) {
break;
} swap(A, posPointer, negPointer);
} return A;
}

SOLUTION 4(December 23th Refresh):

在SOL3的基础上改进:

翻转数列的一步修改为:把右边的负数移动到左边即可。可以优化复杂度。其它与SOL3一致。

感谢Lansheep大神提供思路!

 /*
Solution 4:
把reverse的步骤简化了一下
*/
public static int[] rerange(int[] A) {
// write your code here // Check the input parameter.
if (A == null || A.length <= 2) {
return A;
} int len = A.length; int cntPositive = 0; // store the positive numbers index.
int i1 = 0; for (int i2 = 0; i2 < len; i2++) {
if (A[i2] > 0) {
cntPositive++; // Put all the positive numbers at in the left part.
swap(A, i1++, i2);
}
} // If positive numbers are more than negative numbers,
// Put the positive numbers at first.
int posPointer = 1;
int negPointer = 0; if (cntPositive > A.length / 2) {
// Have more Positive numbers;
posPointer = 0;
negPointer = 1; // Reverse the array.
int left = 0;
int right = len -1;
while (right >= cntPositive) {
swap(A, left, right);
left++;
right--;
}
} // Reorder the negative and the positive numbers.
while (true) {
// Should move if it is in the range.
while (posPointer < len && A[posPointer] > 0) {
posPointer += 2;
} // Should move if it is in the range.
while (negPointer < len && A[negPointer] < 0) {
negPointer += 2;
} if (posPointer >= len || negPointer >= len) {
break;
} swap(A, posPointer, negPointer);
} return A;
}

GITHUB:

https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/lintcode/array/Rerange.java

Lintcode: Interleaving Positive and Negative Numbers 解题报告的更多相关文章

  1. [LintCode] Interleaving Positive and Negative Numbers

    Given an array with positive and negative integers. Re-range it to interleaving with positive and ne ...

  2. Interleaving Positive and Negative Numbers

    Given an array with positive and negative integers. Re-range it to interleaving with positive and ne ...

  3. 【九度OJ】题目1442:A sequence of numbers 解题报告

    [九度OJ]题目1442:A sequence of numbers 解题报告 标签(空格分隔): 九度OJ 原题地址:http://ac.jobdu.com/problem.php?pid=1442 ...

  4. 【LeetCode】129. Sum Root to Leaf Numbers 解题报告(Python)

    [LeetCode]129. Sum Root to Leaf Numbers 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/pr ...

  5. 【LeetCode】386. Lexicographical Numbers 解题报告(Python)

    [LeetCode]386. Lexicographical Numbers 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博 ...

  6. 【LeetCode】165. Compare Version Numbers 解题报告(Python)

    [LeetCode]165. Compare Version Numbers 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博 ...

  7. USACO Section2.2 Runaround Numbers 解题报告 【icedream61】

    runround解题报告---------------------------------------------------------------------------------------- ...

  8. 【LeetCode】1022. Sum of Root To Leaf Binary Numbers 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 DFS 日期 题目地址:https://leetco ...

  9. 【LeetCode】628. Maximum Product of Three Numbers 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 方法一:排序 日期 题目地址:https://lee ...

随机推荐

  1. Android开发环境——Eclipse ADT相关内容汇总

     Android开发环境将分为SDK相关内容.Eclipse ADT相关内容.模拟器AVD相关内容.调试器DDMS相关内容.日志LogCat相关内容.连接驱动ADB相关内容.内存泄露检测工具MAT相关 ...

  2. 树莓派UFW防火墙简单设置

    ufw是一个主机端的iptables类防火墙配置工具,比较容易上手.如果你有一台暴露在外网的树莓派,则可通过这个简单的配置提升安全性. 安装方法 sudo apt-get install ufw 当然 ...

  3. B. Eight Point Sets

    B. Eight Point Sets http://codeforces.com/contest/334/problem/B   time limit per test 1 second memor ...

  4. 【Spring】基于SpringMVC的图片验证码功能实现

    后台实现代码: ImgController.java 文件 package cn.shop.controller; import java.awt.Color; import java.awt.Fon ...

  5. 【Algorithm】自顶向下的归并排序

    一. 算法描述 自顶向下的归并排序:采用分治法进行自顶向下的程序设计方式,分治法的核心思想就是分解.求解.合并. 先将长度为N的无序序列分割平均分割为两段 然后分别对前半段进行归并排序.后半段进行归并 ...

  6. golang学习 ----获取URL

    package main import ( "fmt" "io/ioutil" "net/http" "os" ) fu ...

  7. Oracle 12C -- 基于sequence的列的默认值

    12C支持先创建一个sequence,然后再将该sequence指定为某个列的值的默认表达式. 和"identity column"具有以下不同点: ·对列的个数没有限制 ·seq ...

  8. Cg入门11:Vertex Shader - 几何变换 —MVP矩阵变换(旋转、缩放)

    旋转.缩放demo C# Code: Shader Code: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize ...

  9. (面试题)如何查找Oracle数据库中的重复记录

    今天做了个面试题:查找Oracle数据库中的重复记录,下面详细介绍其他方法(参考其他资料) 本文介绍了几种快速查找ORACLE数据库中的重复记录的方法. 下面以表table_name为例,介绍三种不同 ...

  10. excel中对数据进行分类求和

    我们在用excel处理数据时,常常需要按不同的类别分别汇总数据.例如下图中需要求出每个业务员的总销售金额等. 通常情况下我们的数据量很大,而且需要较快的统计出来结果,所以我们要用一定的技巧才能计算出来 ...