LeetCode493. 翻转对 - Java & Go - 归并排序

LeetCode493. 翻转对

LeetCode493. 翻转对
在这里插入图片描述

1 算法

  • 算法
    • 1.归并排序
    • 2.对数组进行归并排序
      • 2.1 首先数组分成两个子数组分别递归归并,加到结果中,这时两个子数组都变成有序的了
      • 2.2 对两个有序的子数组可以很快求得满足条件的翻转对
        • 遍历左子数组每个元素
        • 对左子数组的每个元素,在右子数组找到满足条件的范围,加到结果中
        • 当遍历到左子数组下一个元素时,不必重新从头遍历右子数组找到满足条件的范围,因为两个子数组都是有序的,接着上次遍历不满足nums[i] > 2 * nums[j]的j的位置即可,以此减少时间复杂度
  • 相似题目

2 Java

public int reversePairs(int[] nums) {
    if (nums == null || nums.length <= 1) {
        return 0;
    }

    return reversePairs(nums, 0, nums.length - 1);
}
    
private int reversePairs(int[] nums, int left, int right) {
    if (left == right) {
        return 0;
    } else {
        int mid = (left + right) >> 1;
        int n1 = reversePairs(nums, left, mid);
        int n2 = reversePairs(nums, mid+1, right);
        int result = n1 + n2;

        int j = mid + 1;
        for (int i = left; i <= mid; i++) {
            while (j <= right && (long) nums[i] > 2 * (long) nums[j]) {
                j++;
            }
            result += (j - mid - 1);
        }
        
        int[] sorted = new int[right - left + 1];
        int p1 = left, p2 = mid + 1, i = 0;
        while (p1 <= mid || p2 <= right) {
            if (p1 > mid) {
                sorted[i++] = nums[p2++];
            } else if (p2 > right) {
                sorted[i++] = nums[p1++];
            } else {
                if (nums[p1] < nums[p2]) {
                    sorted[i++] = nums[p1++];
                } else {
                    sorted[i++] = nums[p2++];
                }
            }
        }
        System.arraycopy(sorted, 0, nums, left, sorted.length);
        return result;
    }   
}

3 Go

func reversePairs(nums []int) int {
	if nums == nil || len(nums) <= 1 {
		return 0
	}

	return reversePairsRecursion(nums, 0, len(nums) - 1)
}

func reversePairsRecursion(nums []int, left, right int) int {
	if left == right {
		return 0
	} else {
		mid := (left + right) >> 1
		n1 := reversePairsRecursion(nums, left, mid)
		n2 := reversePairsRecursion(nums, mid + 1, right)
		result := n1 + n2

		j := mid + 1
		for i := left; i <= mid; i++ {
			for j <= right && nums[i] > 2 * nums[j] {
				j++
			}
			result += j - mid - 1
		}

		sorted := make([]int, right-left+1)
		p1, p2, i := left, mid + 1, 0
		for p1 <= mid || p2 <= right {
			if p1 > mid {
				sorted[i] = nums[p2]
				p2++
			} else if p2 > right {
				sorted[i] = nums[p1]
				p1++
			} else {
				if nums[p1] < nums[p2] {
					sorted[i] = nums[p1]
					p1++
				} else {
					sorted[i] = nums[p2]
					p2++
				}
			}
			i++
		}
		for k := 0; k < len(sorted); k++ {
			nums[left + k] = sorted[k]
		}

		return result
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值