当前位置: 首页 > article >正文

51. 数组中的逆序对


comments: true
difficulty: 困难
edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9851.%20%E6%95%B0%E7%BB%84%E4%B8%AD%E7%9A%84%E9%80%86%E5%BA%8F%E5%AF%B9/README.md

面试题 51. 数组中的逆序对

题目描述

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

 

示例 1:

输入: [7,5,6,4]
输出: 5

 

限制:

0 <= 数组长度 <= 50000

解法

方法一:归并排序

归并排序的过程中,如果左边的数大于右边的数,则右边的数与 左边的数之后的数 都构成逆序对。

时间复杂度 O ( n × log ⁡ n ) O(n \times \log n) O(n×logn),空间复杂度 O ( n ) O(n) O(n)。其中 n n n 为数组长度。

Python3
class Solution:
    def reversePairs(self, nums: List[int]) -> int:
    	def merge_sort(l, r):
	            if l >= r:
	                return 0
	            mid = (l + r) >> 1
	            ans = merge_sort(l, mid) + merge_sort(mid + 1, r) #对左右子序列进行递归排序,
	            
	            #以下为merge操作:先两个两个排序归并,再四个四个排序归并,,,
	            tmp = [] # 合并后的结果序列
	            i, j = l, mid + 1 # 左,右子序列的指针
	            while i <= mid and j <= r:
	                if nums[i] <= nums[j]: #1.如果左子序列的元素小于等于右子序列的元素,将左子序列的元素添加到结果序列中
	                    tmp.append(nums[i])
	                    i += 1 #2.左子序列指针向后移动一位
	                else:
	                    ans += mid - i + 1 #核心:如果左边的数大于右边的数,则右边的数与 左边的数之后的数 都构成逆序对
	                    tmp.append(nums[j]) #3.否则,将右子序列的元素添加到结果序列中
	                    j += 1 #4.右子序列指针向后移动一位
	            # 将剩余的元素直接添加到结果序列中     
	            tmp.extend(nums[i : mid + 1])
	            tmp.extend(nums[j : r + 1])
	            nums[l : r + 1] = tmp
	            return ans
	        return merge_sort(0, len(nums) - 1)
Java
class Solution {
    private int[] nums;
    private int[] t;

    public int reversePairs(int[] nums) {
        this.nums = nums;
        int n = nums.length;
        this.t = new int[n];
        return mergeSort(0, n - 1);
    }

    private int mergeSort(int l, int r) {
        if (l >= r) {
            return 0;
        }
        int mid = (l + r) >> 1;
        int ans = mergeSort(l, mid) + mergeSort(mid + 1, r);
        int i = l, j = mid + 1, k = 0;
        while (i <= mid && j <= r) {
            if (nums[i] <= nums[j]) {
                t[k++] = nums[i++];
            } else {
                ans += mid - i + 1;
                t[k++] = nums[j++];
            }
        }
        while (i <= mid) {
            t[k++] = nums[i++];
        }
        while (j <= r) {
            t[k++] = nums[j++];
        }
        for (i = l; i <= r; ++i) {
            nums[i] = t[i - l];
        }
        return ans;
    }
}
C++
class Solution {
public:
    int reversePairs(vector<int>& nums) {
        int n = nums.size();
        if (n == 0) {
            return 0;
        }
        int t[n];
        function<int(int, int)> mergeSort = [&](int l, int r) -> int {
            if (l >= r) {
                return 0;
            }
            int mid = (l + r) >> 1;
            int ans = mergeSort(l, mid) + mergeSort(mid + 1, r);
            int i = l, j = mid + 1, k = 0;
            while (i <= mid && j <= r) {
                if (nums[i] <= nums[j]) {
                    t[k++] = nums[i++];
                } else {
                    ans += mid - i + 1;
                    t[k++] = nums[j++];
                }
            }
            while (i <= mid) {
                t[k++] = nums[i++];
            }
            while (j <= r) {
                t[k++] = nums[j++];
            }
            for (i = l; i <= r; ++i) {
                nums[i] = t[i - l];
            }
            return ans;
        };
        return mergeSort(0, n - 1);
    }
};
Go
func reversePairs(nums []int) int {
	n := len(nums)
	t := make([]int, n)
	var mergeSort func(l, r int) int
	mergeSort = func(l, r int) int {
		if l >= r {
			return 0
		}
		mid := (l + r) >> 1
		ans := mergeSort(l, mid) + mergeSort(mid+1, r)
		i, j, k := l, mid+1, 0
		for i <= mid && j <= r {
			if nums[i] <= nums[j] {
				t[k] = nums[i]
				k, i = k+1, i+1
			} else {
				ans += mid - i + 1
				t[k] = nums[j]
				k, j = k+1, j+1
			}
		}
		for ; i <= mid; i, k = i+1, k+1 {
			t[k] = nums[i]
		}
		for ; j <= r; j, k = j+1, k+1 {
			t[k] = nums[j]
		}
		for i = l; i <= r; i++ {
			nums[i] = t[i-l]
		}
		return ans
	}
	return mergeSort(0, n-1)
}
TypeScript
function reversePairs(nums: number[]): number {
    const mergeSort = (l: number, r: number): number => {
        if (l >= r) {
            return 0;
        }
        const mid = (l + r) >> 1;
        let ans = mergeSort(l, mid) + mergeSort(mid + 1, r);
        let i = l;
        let j = mid + 1;
        const t: number[] = [];
        while (i <= mid && j <= r) {
            if (nums[i] <= nums[j]) {
                t.push(nums[i++]);
            } else {
                ans += mid - i + 1;
                t.push(nums[j++]);
            }
        }
        while (i <= mid) {
            t.push(nums[i++]);
        }
        while (j <= r) {
            t.push(nums[j++]);
        }
        for (i = l; i <= r; ++i) {
            nums[i] = t[i - l];
        }
        return ans;
    };
    return mergeSort(0, nums.length - 1);
}
JavaScript
/**
 * @param {number[]} nums
 * @return {number}
 */
var reversePairs = function (nums) {
    const mergeSort = (l, r) => {
        if (l >= r) {
            return 0;
        }
        const mid = (l + r) >> 1;
        let ans = mergeSort(l, mid) + mergeSort(mid + 1, r);
        let i = l;
        let j = mid + 1;
        let t = [];
        while (i <= mid && j <= r) {
            if (nums[i] <= nums[j]) {
                t.push(nums[i++]);
            } else {
                ans += mid - i + 1;
                t.push(nums[j++]);
            }
        }
        while (i <= mid) {
            t.push(nums[i++]);
        }
        while (j <= r) {
            t.push(nums[j++]);
        }
        for (i = l; i <= r; ++i) {
            nums[i] = t[i - l];
        }
        return ans;
    };
    return mergeSort(0, nums.length - 1);
};
C#
public class Solution {
    private int[] nums;
    private int[] t;

    public int ReversePairs(int[] nums) {
        this.nums = nums;
        int n = nums.Length;
        this.t = new int[n];
        return mergeSort(0, n - 1);
    }

    private int mergeSort(int l, int r) {
        if (l >= r) {
            return 0;
        }
        int mid = (l + r) >> 1;
        int ans = mergeSort(l, mid) + mergeSort(mid + 1, r);
        int i = l, j = mid + 1, k = 0;
        while (i <= mid && j <= r) {
            if (nums[i] <= nums[j]) {
                t[k++] = nums[i++];
            } else {
                ans += mid - i + 1;
                t[k++] = nums[j++];
            }
        }
        while (i <= mid) {
            t[k++] = nums[i++];
        }
        while (j <= r) {
            t[k++] = nums[j++];
        }
        for (i = l; i <= r; ++i) {
            nums[i] = t[i - l];
        }
        return ans;
    }
}
Swift
class Solution {
    private var nums: [Int] = []
    private var temp: [Int] = []

    func reversePairs(_ nums: [Int]) -> Int {
        self.nums = nums
        let n = nums.count
        self.temp = [Int](repeating: 0, count: n)
        return mergeSort(0, n - 1)
    }

    private func mergeSort(_ left: Int, _ right: Int) -> Int {
        if left >= right {
            return 0
        }
        let mid = (left + right) / 2
        var count = mergeSort(left, mid) + mergeSort(mid + 1, right)
        var i = left
        var j = mid + 1
        var k = left

        while i <= mid && j <= right {
            if nums[i] <= nums[j] {
                temp[k] = nums[i]
                i += 1
            } else {
                count += mid - i + 1
                temp[k] = nums[j]
                j += 1
            }
            k += 1
        }

        while i <= mid {
            temp[k] = nums[i]
            i += 1
            k += 1
        }

        while j <= right {
            temp[k] = nums[j]
            j += 1
            k += 1
        }

        for i in left...right {
            nums[i] = temp[i]
        }

        return count
    }
}

http://www.kler.cn/a/305953.html

相关文章:

  • 算法学习第一弹——C++基础
  • 探索Python的HTTP利器:Requests库的神秘面纱
  • C++编程技巧与规范-类和对象
  • LeetCode【0033】搜索旋转排序数组
  • Vue 的生命周期函数 和 Vuex
  • Flutter Getx状态管理
  • 使用 Spring Boot + Vue + ElementUI 构建简易评分系统
  • 信息安全工程师(3)TCP/IP协议簇
  • 软件测试工程师面试整理-测试生命周期
  • gingivitis
  • CSS3中的@media查询
  • HTML5超酷炫的水果蔬菜在线商城网站源码系列模板1
  • 如何调试本地npm package
  • MySQL之表的约束
  • 基于springboot的校企招聘管理系统的设计与实现
  • HTTPS的加密流程:保护你的数据传输
  • 关于决策树的一些介绍(二)
  • 物联网之Arduino编程语言
  • 【stm32笔记】使用rtt-studio与stm32CubeMx联合创建项目
  • 鸿蒙 ArkUI组件一
  • 三十七、Gin完成登陆功能
  • solidity-20-sendeth
  • MySQL——数据库的高级操作(三)权限管理(2)授予权限
  • 自动驾驶自动泊车场景应用总结
  • RAII 与 std::lock_guard 在 C++ 中的应用:自动化互斥锁管理与线程安全
  • 【6大设计原则】迪米特法则:解密软件设计中的“最少知识原则”