Java排序算法题-00

调整数组顺序使奇数位于偶数前面

输入一个长度为 n 整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前面部分,所有的偶数位于数组的后面部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

  1. 冒泡
  • 直接插入、冒泡、基数、归并,这四个排序是稳定的
  1. 双指针
  • 第一次遍历,查询有几个基数
  • 第二次遍历,第一个指针先动到目标位置,第二个指针在头上。根据要求放置。

https://github.com/CyC2018/CS-Notes/blob/master/notes/21.%20%E8%B0%83%E6%95%B4%E6%95%B0%E7%BB%84%E9%A1%BA%E5%BA%8F%E4%BD%BF%E5%A5%87%E6%95%B0%E4%BD%8D%E4%BA%8E%E5%81%B6%E6%95%B0%E5%89%8D%E9%9D%A2.md


把数组排成最小的数

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组 {3,32,321},则打印出这三个数字能排成的最小数字为 321323。

  1. 重载比较
  • 不是顺序比较两个字符串的每一个字符的大小,而是比较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() {
            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));

https://www.nowcoder.com/practice/8fecd3f8ba334add803bf2a06af1b993?tpId=13&tqId=11185&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking&from=cyc_github


数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

  1. 分治
  • 时间要求是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];
}

https://github.com/CyC2018/CS-Notes/blob/master/notes/51.%20%E6%95%B0%E7%BB%84%E4%B8%AD%E7%9A%84%E9%80%86%E5%BA%8F%E5%AF%B9.md


引用仓库:https://github.com/CyC2018/CS-Notes/blob/master/notes/%E5%89%91%E6%8C%87%20Offer%20%E9%A2%98%E8%A7%A3%20-%20%E7%9B%AE%E5%BD%95.md

你可能感兴趣的:(Java排序算法题-00)