调整数组顺序使奇数位于偶数前面
输入一个长度为 n 整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前面部分,所有的偶数位于数组的后面部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
- 冒泡
- 直接插入、冒泡、基数、归并,这四个排序是稳定的
- 双指针
- 第一次遍历,查询有几个基数
- 第二次遍历,第一个指针先动到目标位置,第二个指针在头上。根据要求放置。
把数组排成最小的数
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组 {3,32,321},则打印出这三个数字能排成的最小数字为 321323。
- 重载比较
- 不是顺序比较两个字符串的每一个字符的大小,而是比较s1+s2与s2+s1的大小。重写比较的函数,然后用自带的排序调用这个函数,完成对数组的排序。
-
nums[i] = numbers[i] + "";
将int类型转化为字符串类型 -
(s1 + s2).compareTo(s2 + s1);
这个重写了compare这个方法。
a. 原先比较的是s1与s2谁大谁小。
b. 现在先比较s1+s2与s2+s1。若s1+s2小于s2+s1,返回负数。最终形成升序排列。 - 我的理解是 记住
(s1,s2) - > s1.compareTo(s2)
是升序,类推到(s1,s2) -> (s1 + s2).compareTo(s2 + s1)
。源码里相当于用我们重写的方法进行排序,在TimSort
这个类里面有一个binarySort
的方法。
import java.util.*;
public class Solution {
public String PrintMinNumber(int [] numbers) {
//空数组的情况
if(numbers == null || numbers.length == 0)
return "";
String[] nums = new String[numbers.length];
//将数字转成字符
for(int i = 0; i < numbers.length; i++)
nums[i] = numbers[i] + "";
//按照重载排序
Arrays.sort(nums, new Comparator<String>() {
public int compare(String s1, String s2) {
return (s1 + s2).compareTo(s2 + s1);
}
});
StringBuilder res = new StringBuilder();
//字符串叠加
for(int i = 0; i < nums.length; i++)
res.append(nums[i]);
return res.toString();
}
}
//第二种写法
Arrays.sort(nums, (s1, s2) -> (s1 + s2).compareTo(s2 + s1));
数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
- 分治
- 时间要求是log级的,属于这个级别的排序有 快速排序、堆排序、归并排序。这里用归并。
- 思路很简单,归并的结果是分成最小的一组进行比较。在最小的结果中,如果有符合要求的,结果+1。然后进入第二组的比较过程,此时根据情况,结果集对应增加。
- 因为每一组里面都是已经排序完成的,可以根据这个性质,来确认结果集应该加多少。比如2 3 和 0 5,2比0大,则2之后的都会比0大。
- 额外数组空间拿出来定义,减少创建、解析的时间。
private long cnt = 0;
private int[] tmp; // 在这里声明辅助数组,而不是在 merge() 递归函数中声明
public int InversePairs(int[] nums) {
tmp = new int[nums.length];
mergeSort(nums, 0, nums.length - 1);
return (int) (cnt % 1000000007);
}
private void mergeSort(int[] nums, int l, int h) {
if (h - l < 1)
return;
int m = l + (h - l) / 2;
mergeSort(nums, l, m);
mergeSort(nums, m + 1, h);
merge(nums, l, m, h);
}
private void merge(int[] nums, int l, int m, int h) {
int i = l, j = m + 1, k = l;
while (i <= m || j <= h) {
if (i > m)
tmp[k] = nums[j++];
else if (j > h)
tmp[k] = nums[i++];
else if (nums[i] <= nums[j])
tmp[k] = nums[i++];
else {
tmp[k] = nums[j++];
this.cnt += m - i + 1; // nums[i] > nums[j],说明 nums[i...mid] 都大于 nums[j]
}
k++;
}
for (k = l; k <= h; k++)
nums[k] = tmp[k];
}