把数组排成最小的数_数组中的逆序对(归并统计法)_数字在升序数组中出现的次数_丑数(剑指offer)

简介: 把数组排成最小的数_数组中的逆序对(归并统计法)_数字在升序数组中出现的次数_丑数(剑指offer)

排序

把数组排成最小的数

题目链接

image.png

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

这里题目重点就是自己设计一个排序,通过Comparator接口!

字符串拼接s1 + s21>s2 + s1说明s1和s2位置需要交换!


image.png

相似题目:数据流中的中位数

image.png


读懂题意!


import java.util.*;
public class Solution {
    //将数据流保存在table中!
    private ArrayList<Integer> table = new ArrayList<>();
    public void Insert(Integer num) {
        //在table数据流中插入num值!
        if(table.isEmpty()){
            //直接尾插
            table.add(num);
        }else{
            //不为空,找到合适位置插入!升序排序!
            int i = 0;
            for(i = 0;i< table.size();i++){
                if(table.get(i)>num){
                    //找到了合适位置!
                    table.add(i,num);
                    break;
                }
            }
            if(i==table.size()){
                //尾插!
                table.add(i,num);
            }
        }
    }
    public Double GetMedian() {
        //计算中位数!
        if(table.isEmpty()){
            return 0.0;
        }else{
            int size = table.size();
            if(size%2==0){
                //偶数!
                return (double)(table.get(size/2)+table.get(size/2-1))/2;
            }else{
                //奇数
                return (double)table.get(size/2);
            }
        }
    }
}

插入考虑边界问题!

数组中的逆序对(归并统计法)

题目链接


image.png


image.png


public class Solution {
    private int sum = 0;//保存结果值!
    public int InversePairs(int [] array) {
        //归并统计法!
        //采用归并排序的思想,在毕竟合并时统计逆序对的组数!
        if(array.length<2){
            //无逆序队
            return 0;
        }
        //进行归并统计!
       mergeSort(array,0,array.length-1);
        return sum; 
    }
    public void mergeSort(int[] array,int left,int right){
        //进行先分!
        int mid = left + (right-left)/2;
       if(left<right){
           //左区间!
           mergeSort(array,left,mid);
           //右区间!
           mergeSort(array,mid+1,right);
           //后和并
           merge(array,left,mid,right);
       }
    }
    public void merge(int[] array,int left,int mid,int right){
        //我们进行合并时需要有个临时数组保存
        int[] tmp = new int[right-left+1];
        //记录临时数组开始下标位置!
        int tmpIndex = 0;
        //记录原数组开始下标位置(临时数组数据需要放入到原数组中)
        int arrayIndex = left;
        //左区间开始位置!
        int l = left;
        //右区间开始位置!
        int r = mid+1;
         //进行比较合并!
        while(l<=mid&&r<=right){
           if(array[l]<=array[r]){
               //无逆序,直接将l下标保存在临时数组!
               tmp[tmpIndex++] = array[l++];
           }else{
               //逆序,交换(就将r下标位置保存)
               tmp[tmpIndex++] = array[r++];
               //记录逆序对数!
               //进行归并时,左右数组已经分别有序!
               //l大于r下标元素,也就是l到mid区间都大于r下标元素
               //所以逆序对数为 l下标位置到 r位置个数!
               sum += mid - l +1;
               sum %= 1000000007;
           }
        }
        //区间长度不相等,有剩余值!
        while(l<=mid){
            tmp[tmpIndex++] = array[l++];
        }
        while(r<=right){
            tmp[tmpIndex++] = array[r++];
        }
        //将元素放回到原数组!
        for(int x : tmp){
            array[arrayIndex++] = x;
        }
    }
}

数字在升序数组中出现的次数

题目链接

image.png

public class Solution {
    public int GetNumberOfK(int [] array , int k) {
       //数组以有序!
        //二分查找!
        int l = 0,r = array.length-1; 
        int mid = l + (r-l)/2;
        boolean flg = false;
        while(l<=r){
            mid = l + (r-l)/2;
            if(array[mid]>k){
                //定位在左区间!
                r = mid-1;
            }else if(array[mid]<k){
                //定位在右区间!
                l = mid+1;
            }else{
                //相等!
                //找到!
                flg = true;
                break;
            }
        }
        if(flg){
            for(int i = l;i<=mid;i++){
                if(array[i]==k){
                    //相等区间左边界!
                    l = i;
                    break;
                }
            }
            for(int i = r;i>=mid;i--){
                if(array[i]==k){
                    //相等区间右边界!
                    r = i;
                    break;
                }
            }
            return r - l +1;
        }
        return 0;
    }
}
public class Solution {
    public int GetNumberOfK(int [] array , int k) {
        //直接找到边界,[left,right) 左闭右开!
       return bisearch(array,k+0.5) - bisearch(array,k-0.5);
    }
    public int bisearch(int[] array,double k){
        int left = 0,right = array.length-1;
        while(left<=right){
            int mid = left + (right-left)/2;
            if(array[mid]<k){
                left = mid + 1;
                }else{
               right = mid - 1; 
            }
        }
        //这里二分如果没找到返回的是大于该值的一个下标
        return left;
    }
}

image.png


丑数

链接

image.png

解题思路:


我们先看到题目,把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。


有了上面的定义我们就可以知道,丑数的形式就是2x3y5^z

所以我们可以定义一个数组res,存储第n个丑数。

因为我们要将丑数按从小到大的顺序排序,所以我们就得将对应的丑数放在对应的下标位置,小的放前面。

因为最小的丑数就是1,所以我们初始化res[0]=1,那么接下来的一个丑数是什么呢?我们自己知道是2。

但是我们能不能有一个格式,去将得到接下来的丑数是谁呢?

这个时候上面我们的出来的丑数的格式就起作用了,丑数的形式无非就是这样2x3y5z

所以我们就将res[n]去乘以 2、3、5,然后比较出最小的那个,就是我们当前的下一个丑数了。

image.png

public class Solution {
    public int GetUglyNumber_Solution(int index) {
        if(index==0){
            return 0;
        }
        //利用 丑数: 2^x*3^y*5^z!
        int[] arr = new int[index];//保存前index丑数值!
        arr[0] = 1;
        int i2 = 0,i3 = 0,i5 = 0;//记录2/3/5分别相乘的次数!
        for(int i = 1;i<index;i++){
            //将3个中最小丑数放在前面!
            //每次都是求出最小的丑数!
            arr[i] = Math.min(arr[i2]*2,Math.min(arr[i3]*3,arr[i5]*5));
            if(arr[i]==arr[i2]*2){
                //说明这里的 2 相乘次数加一!
                i2++;
            }
            if(arr[i]==arr[i3]*3){
                //说明这里的 3 相乘次数加一!
                i3++;
            }
            if(arr[i]==arr[i5]*5){
                //说明这里的 5 相乘次数加一!
                i5++;
            }
        }
        return arr[index-1];
    }
}
目录
相关文章
|
XML 开发框架 .NET
|
机器学习/深度学习 自然语言处理 算法
Transformer 模型:入门详解(1)
动动发财的小手,点个赞吧!
13836 1
Transformer 模型:入门详解(1)
|
Java API Maven
Java工具篇之反射框架Reflections
Reflections通过扫描classpath,索引元数据,并且允许在运行时查询这些元数据。 使用Reflections可以很轻松的获取以下元数据信息: - [x] 获取某个类型的全部子类 - [x] 只要类型、构造器、方法,字段上带有特定注解,便能获取带有这个注解的全部信息(类型、构造器、方法,字段) - [x] 获取所有能匹配某个正则表达式的资源 - [x] 获取所有带有特定签名的方法,包括参数,参数注解,返回类型 - [x] 获取所有方法的名字 - [x] 获取代码里所有字段、方法名、构造器的使用权
1726 0
|
8月前
|
存储 监控 NoSQL
NoSQL与Redis配置与优化
通过合理配置和优化Redis,可以显著提高其性能和可靠性。选择合适的数据结构、优化内存使用、合理设置持久化策略、使用Pipeline批量执行命令、以及采用分布式集群方案,都是提升Redis性能的重要手段。
141 7
|
JavaScript
Vue2图片懒加载(vue-lazyload)
这篇文章介绍了如何在Vue 2项目中使用`vue-lazyload`插件来实现图片的懒加载功能,包括安装插件、注册配置以及在页面中的具体使用方法。
500 0
Vue2图片懒加载(vue-lazyload)
|
缓存 监控 关系型数据库
MySQL PXC 集群死锁分析案例
前不久一个系统死锁导致部分业务受到影响,今次补上详细的节点日志分析过程。
308 1
|
Java 数据库连接 数据库
Unable to evaluate the expression Method threw ‘org.hibernate.LazyInitializationException‘ exceptio
Unable to evaluate the expression Method threw ‘org.hibernate.LazyInitializationException‘ exceptio
|
Docker 容器
docker 离线镜像导入
前言:之前做了一个医院的项目,一般医院使用的服务器都是内网环境,所以自己整合了一下Docker离线部署的方法分享给大家。
733 0
|
弹性计算 容灾 安全
阿里云服务器配置购买指南2023
阿里云服务器配置购买指南2023,适合新手小白的图文指导教程,阿里云服务器选购指南!如何选择一款适合自己的阿里云服务器?
440 0
阿里云服务器配置购买指南2023
|
缓存 负载均衡 应用服务中间件
如何在 Nginx 中隐藏版本号
Nginx 是一款高性能的 Web 服务器软件,它支持反向代理、负载均衡、缓存等功能。在使用 Nginx 的过程中,有时候我们需要隐藏 Nginx 的版本号,以增强服务器的安全性。