栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

LeetCode315、计算右侧小于当前元素的个数(采用归并)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

LeetCode315、计算右侧小于当前元素的个数(采用归并)

给你一个整数数组 nums ,按要求返回一个新数组 counts 。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。

示例 1:
输入:nums = [5,2,6,1]
输出:[2,1,1,0]
解释:
5 的右侧有 2 个更小的元素 (2 和 1)
2 的右侧仅有 1 个更小的元素 (1)
6 的右侧有 1 个更小的元素 (1)
1 的右侧有 0 个更小的元素

示例 2:
输入:nums = [-1]
输出:[0]

示例 3:
输入:nums = [-1,-1]
输出:[0,0]

提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104

此题我们也采用归并的方式来完成。

此题要求我们只能向后看,看后面的小于当前要判断的值

但是在这个题当中,我们不仅要在辅助数组当中保留原始数组的中的数据还要有索引数据,所以在这我们就可以直接在辅助数组当中直接存入索引,然后通过索引去输入数组中查询数据来进行大小的比较。

代码的演示和详细注释:

public class Demo315 {
    public static void main(String[] args) {
        int[] a = {5,2,6,1};
        List b = countSmaller(a);
        System.out.println(b);
    }


    private static List countSmaller(int[] nums) {
        int len = nums.length;
        List res = new ArrayList<>(len); //创建一个List的变量

        int[] indexes = new int[len];         //记录原数组中的索引数组
        for (int i = 0; i < len; i++) {       //将索引填充到数组当中
            indexes[i] = i;
        }
        int[] temp = new int[len];      //设置一个全局的辅助数组
        int[] ans = new int[len];       //记录修改后的数组。在ArrayList上直接弄不太方便
        reversePairs(nums, 0, len - 1, indexes, temp, ans);

        for (int i = 0; i < len; i++) {//在最后给List导入数据,并最后返回数组
            res.add(ans[i]);
        }
        return res;
    }

    
    private static void reversePairs(int[] nums, int left, int right, int[] indexes, int[] temp, int[] ans) {
        if (left == right) {    //当左边和右边的索引一样的时候,就是分到只要一个的时候,结束方法
            return;           //并返回0
        }
        int mid = (right + left) / 2;
        //获得当前要排序数组的中间的索引(因为这个题给的数组长度在相加也还在int之类,所以直接加是可以的

        reversePairs(nums, left, mid, indexes, temp, ans);//先对左边的进行分组
        reversePairs(nums, mid + 1, right, indexes, temp, ans);//然后对右边的进行分组
        mergeAndCount(nums, left, mid, right, indexes, temp, ans);//给ans数值计算值
    }

    
    private static void mergeAndCount(int[] nums, int left, int mid, int right, int[] indexes, int[] temp, int[] ans) {
        for (int i = left; i <= right; i++) {
            temp[i] = indexes[i];//给辅助数组赋索引值
        }

        //i,j,k都与上面图中的互相对应着
        int i = left;
        int j = mid + 1;
        for (int k = left; k <= right; k++) {
            if (i == mid + 1) {
                indexes[k] = temp[j];//这里进行的是数组索引的交换
                j++;
            } else if (j == right + 1) {
                indexes[k] = temp[i];
                i++;
                // j - mid - 1 ==>  right + 1 - mid -1 ==> right - mid;
                ans[indexes[k]] += (right - mid);
            } else if (nums[temp[i]] <= nums[temp[j]]) { //nums[temp[i]]通过索引在输入数组当中得到数据
                indexes[k] = temp[i];
                i++;
                // j - mid - 1 见图说为什么 (๑•̀ㅂ•́)و✧
                ans[indexes[k]] += (j - mid - 1);
            } else {
                indexes[k] = temp[j];
                j++;
            }
        }
    }
}

还是不太明白的话,可以看看这两篇:
一、java实现归并排序
二、剑指offer 51. 数组中的逆序对

欢迎大家在评论区交流

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/847229.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号