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<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));

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

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 从尾到头打印链表 从尾到头反过来打印出每个结点的值。 感觉更优-递归打123的逆序,先打23逆序再打1,先打3逆序...
    柠檬树LeTr阅读 412评论 0 0
  • 重建二叉树 根据二叉树的前序遍历和中序遍历的结果,重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的...
    柠檬树LeTr阅读 179评论 0 0
  • 矩阵中的路径 判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可...
    柠檬树LeTr阅读 330评论 0 0
  • 和为 S 的两个数字 在有序数组中找出两个数,使得和为给定的数 S。如果有多对数字的和等于 S,输出两个数的乘积最...
    柠檬树LeTr阅读 519评论 0 0
  • 剪绳子 把一根绳子剪成多段,并且使得每段的长度乘积最大。 优-动态规划 现有一个数组,用来存储每一个长度下,最优的...
    柠檬树LeTr阅读 133评论 0 0

友情链接更多精彩内容