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

举报
bug郭 发表于 2022/10/06 21:56:36 2022/10/06
【摘要】 排序 把数组排成最小的数题目链接import java.util.*;public class Solution { public String PrintMinNumber(int [] numbers) { //空数组的情况 if(numbers == null || numbers.length == 0) return "";...

排序

把数组排成最小的数

题目链接

image-20220614101954876

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-20220614102313815

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

image-20220614105843930
读懂题意!

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-20220618091015199

image-20220618091139288

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-20220618094847172

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

alt

丑数

链接

image-20220619084735513

解题思路:

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

有了上面的定义我们就可以知道,丑数的形式就是2^x3^y5^z
所以我们可以定义一个数组res,存储第n个丑数。
因为我们要将丑数按从小到大的顺序排序,所以我们就得将对应的丑数放在对应的下标位置,小的放前面。
因为最小的丑数就是1,所以我们初始化res[0]=1,那么接下来的一个丑数是什么呢?我们自己知道是2。
但是我们能不能有一个格式,去将得到接下来的丑数是谁呢?
这个时候上面我们的出来的丑数的格式就起作用了,丑数的形式无非就是这样2x3y5z
所以我们就将res[n]去乘以 2、3、5,然后比较出最小的那个,就是我们当前的下一个丑数了。

33

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];
    }
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。