5-104-(LeetCode- 151) 翻转字符串里的单词?

Posted arctic_fox

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了5-104-(LeetCode- 151) 翻转字符串里的单词?相关的知识,希望对你有一定的参考价值。

1. 题目

2. 解法

3. 总结

LeetCode翻转对

题目链接:493. 翻转对 - 力扣(LeetCode)

一、题目 

给定一个数组 nums ,如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对。你需要返回给定数组中的重要翻转对的数量。

示例 1:
输入: [1,3,2,3,1]
输出: 2

示例 2:
输入: [2,4,3,5,1]
输出: 3

注意:
给定数组的长度不会超过50000。
输入数组中的所有数字都在32位整数的表示范围内。

二、代码 

class Solution 
    public int reversePairs(int[] nums) 
        // 数组为空或不足两个元素直接返回0
        if (nums == null || nums.length < 2) 
            return 0;
        

        return process(nums, 0, nums.length - 1);
    
    
    // 递归驱动,将数据去进行分割
    public static int process(int[] nums, int l, int r) 
        // 递归出口,递归分割到只剩下一个数的时候,就返回,向上开始归并
        if (l == r) 
            return 0;
        

        int mid = l + ((r - l) >> 1);

        return process(nums, l, mid) + process(nums, mid + 1, r) + merge(nums, l, mid, r);
    

    /**
     * 划分成了两组,[L....M] 和 [M+1....R],对他们来进行处理
     */
    public static int merge(int[] nums, int l, int mid, int r) 
        // 记录本轮统计出来的翻转对个数
        int ans = 0;
        // 右组的下标起点
        int rightIndex = mid + 1;
        
        // 左右两组的下标都从左边开始向右移动
        for (int i = l; i <= mid; i++) 
            // 如果右组当前指向的数的二倍比左组当前指向的数小,说明这个数符合翻转对要求
            while (rightIndex <= r &&  (long) nums[rightIndex] * 2 < (long) nums[i]) 
                // 进入到merge方法的两组数肯定都分别已经排序好了,所以我们再将右组下标向右移动,判断下一个数是不是也满足要求
                // 遍历右组直到发现一个数的二倍比左组指向的数打,则结束本轮右组的遍历,因为数据是有序的,它本身已经比左组的数打了,它右边的数一定也是大的
                rightIndex++;
            
            // 当前右组指针-右组左边界就是所有符合翻转对数的个数,将其累加到ans中
            ans += rightIndex - (mid + 1);

            // 下面就将左组的指针右移,因为此时左组的数已经小于右组指向的数的二倍了,我们需要看一下比当前左组指向的数右边更大的数是不是能满足翻转对条件
        

        
        // 通过上面的过程,我们就求出了本轮的翻转对个数,下面我们再将两组数进行归并排序
        // 创建临时数组
        int[] help = new int[r - l + 1];
        int i = 0;
        int p1 = l;
        int p2 = mid + 1;
    
        // 进行归并排序
        while (p1 <= mid && p2 <= r) 
            help[i++] = nums[p1] <= nums[p2] ? nums[p1++] : nums[p2++];
        
        
        while ( p1 <= mid) 
            help[i++] = nums[p1++];
        

        while ( p2 <= r) 
            help[i++] = nums[p2++];
        

        // 将help中已经排序好的数写回到nums中
        for (int j = 0; j < help.length; j++) 
            nums[l + j] = help[j];
        

        // 返回翻转对个数
        return ans;
    

三、解题思路 

这道题就是用归并排序的思路,先去将大数据进行划分,划分成有序的小数据,然后对两组有序的数据进行遍历判断,可以先去对两组有序的小数据去遍历统计符合翻转对的个数,统计完之后再去将两组有序的小数据归并成一个有序的大数据,在返回给上一层。

这道题的关键就是只要是对两组有序的数据去统计翻转对个数就相对容易了。所以整道题就贯穿着归并排序的思想,在将数据逐渐排序的过程中,也完成了统计翻转对的操作。

开发者涨薪指南 48位大咖的思考法则、工作方式、逻辑体系

以上是关于5-104-(LeetCode- 151) 翻转字符串里的单词?的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode第151题—翻转字符串里的单词—Python实现

LeetCode第151题—翻转字符串里的单词—Python实现

leetcode151. 翻转字符串里的单词

LeetCode 151 翻转字符串里的单词

Leetcode No.151 翻转字符串里的单词

LeetCode 151. 翻转字符串里的单词