数组08--数组中的逆序对-jz35

题目概述

  • 算法说明
    在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
    对于50%的数据,size≤10^4
    对于75%的数据,size≤10^5
    对于100%的数据,size≤2*10^5
  • 测试用例
    输入描述:题目保证输入的数组中没有的相同的数字
    输入:
    [1,2,3,4,5,6,7,0]
    输出:
    7

解析&参考答案

  • 解析
    方法1: 使用for循环,但是效率很低;
    方法2: 使用归并排序的思想,先把数字分为2份,那么结果就是第一部分逆序对+第二部分逆序对+第一和第二之间的逆序对。
  • 参考答案
vim jz32.go
package main

import (
"fmt"
)

func InversePairs(data []int) int {
tmp := make([]int, len(data))

var mergeSort func(nums, tmp []int, left, right int) int
mergeSort = func(nums, tmp []int, left, right int) int {
if left >= right {
return 0
}
mid := left + (right-left)>>1
res := mergeSort(nums, tmp, left, mid) + mergeSort(nums, tmp, mid+1, right)

i := left
j := mid + 1

pos := left
for i <= mid && j <= right {
if nums[i] <= nums[j] {
tmp[pos] = nums[i]
i++
} else {
res += mid - i + 1
tmp[pos] = nums[j]
j++
}
pos++
}

for k := i; k <= mid; k++ {
tmp[pos] = nums[k]
pos++
}
for k := j; k <= right; k++ {
tmp[pos] = nums[k]
pos++
}
for i := 0; i < right-left+1; i++ {
nums[i+left] = tmp[i+left]
}
return res % 1000000007
}
return mergeSort(data, tmp, 0, len(data)-1)
}

func InversePairsV2(data []int) int {
// 该方法在数据量大的时候会超时
if data == nil || len(data) == 0 {
return 0
}
result := 0
for i := 0; i < len(data)-1; i++ {
for j := i + 1; j < len(data); j++ {
if data[i] > data[j] {
result += 1
}
}
}
return result % 1000000007
}

func main() {
// array := []int{1, 2, 3, 4, 5, 6, 7, 0}
// array := []int{7, 5, 6, 4}
array := []int{364, 637, 341, 406, 747, 995, 234, 971, 571, 219, 993, 407, 416, 366, 315, 301, 601, 650, 418, 355, 460, 505, 360, 965, 516, 648, 727, 667, 465, 849, 455, 181, 486, 149, 588, 233, 144, 174, 557, 67, 746, 550, 474, 162, 268, 142, 463, 221, 882, 576, 604, 739, 288, 569, 256, 936, 275, 401, 497, 82, 935, 983, 583, 523, 697, 478, 147, 795, 380, 973, 958, 115, 773, 870, 259, 655, 446, 863, 735, 784, 3, 671, 433, 630, 425, 930, 64, 266, 235, 187, 284, 665, 874, 80, 45, 848, 38, 811, 267, 575}
//result := InversePairsV2(array)
result := InversePairs(array)
fmt.Println(result)
}

vim 32_test.go
package main

import "testing"

var tests = []struct {
arr []int
result int
}{
{[]int{1, 2, 3, 4, 5, 6, 7, 0}, 7},
{[]int{7, 5, 6, 4}, 5},
{[]int{364, 637, 341, 406, 747, 995, 234, 971, 571, 219, 993, 407, 416, 366, 315, 301, 601, 650, 418, 355, 460, 505, 360, 965, 516, 648, 727, 667, 465, 849, 455, 181, 486, 149, 588, 233, 144, 174, 557, 67, 746, 550, 474, 162, 268, 142, 463, 221, 882, 576, 604, 739, 288, 569, 256, 936, 275, 401, 497, 82, 935, 983, 583, 523, 697, 478, 147, 795, 380, 973, 958, 115, 773, 870, 259, 655, 446, 863, 735, 784, 3, 671, 433, 630, 425, 930, 64, 266, 235, 187, 284, 665, 874, 80, 45, 848, 38, 811, 267, 575}, 2519},
}

func TestInversePairs(t *testing.T) {
for _, tt := range tests {
if actual := InversePairs(tt.arr); actual != tt.result {
t.Errorf("%v got %v, expected %d", tt.arr, InversePairs(tt.arr), tt.result)
}
}
}

func TestInversePairsV2(t *testing.T) {
for _, tt := range tests {
if actual := InversePairsV2(tt.arr); actual != tt.result {
t.Errorf("%v got %v, expected %d", tt.arr, InversePairsV2(tt.arr), tt.result)
}
}
}

注意事项

  1. to add

说明

  1. 当前使用 go1.15.8
  2. 参考牛客网--剑指offer 标题中jzn(n为具体数字)代表牛客网剑指offer系列第n号题目,例如 jz01 代表牛客网剑指offer中01号题目。

注意!!!

  • 笔者最近在学习 golang,因此趁机通过数据结构和算法来进一步熟悉下go语言
  • 当前算法主要来源于剑指 offer,后续会进一步补充 LeetCode 上重要算法,以及一些经典算法
  • 此处答案仅为参考,不一定是最优解,欢迎感兴趣的读者在评论区提供更优解