[LeetCode] Reverse Pairs 翻转对
Reverse Pairs 翻转对
题意
计算数组里面下标i小于j,但是i的值要大于j的值的两倍的搭配的个数(也就是可能会有多种搭配);网址
做法
这道题显然是不允许使用最简单的方法:两次循环,逐次进行判断,这样做的时间复杂度就是O(n^2),OJ无法通过,需要考虑另外的实现方式;
class Solution(object):
def reversePairs(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
count = 0
for i in range(len(nums)):
for j in range(i+1, len(nums)):
if nums[i] > 2 * nums[j]:
count += 1
return count
分治法
利用分治法,将这个问题分成多个问题,每个小问题求出解后,再求出大问题的解,类似归并排序的做法。
可以设想一个数组分成两边的数组,而且两个数组还是有序的,分别记录两个下标i和j,因为i必然小于j,如果当前i的值已经大于当前j的值的*2,那么当前的i和j之前的值显然也必然满足情况,所以直接计算j从中间的位置移动的距离,这就是当前i求出来的个数,然后移动i,只要满足条件的i,就计算他们的求出来的个数,最后都累加起来,就是最终的结果。
class Solution(object):
res = 0
def reversePairs(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
self.merge_sort(nums, 0, len(nums)-1)
return self.res
def merge_sort(self, nums, left, right):
if right <= left:
return
mid = (left + right) // 2
self.merge_sort(nums, left, mid)
self.merge_sort(nums, mid+1, right)
# 统计个数
count = 0
i, j = left, mid+1
while i <= mid:
if j > right or nums[i] <= 2 * nums[j]:
i += 1
self.res += count
else:
j += 1
count += 1
nums[left:right + 1] = sorted(nums[left:right+1])
或者:
class Solution(object):
def reversePairs(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
return self.merge_sort(nums, 0, len(nums) - 1)
def merge_sort(self, nums, left, right):
if left >= right:
return 0
mid = (left + right) // 2
res = self.merge_sort(nums, left, mid) + self.merge_sort(nums, mid+1, right)
i, j = left, mid+1
while i <= mid:
while j <= right and nums[i] > nums[j] * 2:
j += 1
res += j - (mid + 1)
i += 1
nums[left:right + 1] = sorted(nums[left:right + 1])
return res
树状数组
树状数组的原理可以参考我的这篇博客,使用树状数组是因为其能够保证较少的时间复杂度来计算前面存在多少个符合规定的数字。
class FenwickTree(object):
def __init__(self, n):
self.n = n
self.sums = [0] * (n + 1)
def low_bit(self, x):
return x & -x
def add(self, x, val):
while x <= self.n:
self.sums[x] += val
x += self.low_bit(x)
def get_sum(self, x):
result = 0
while x > 0:
result += self.sums[x]
x -= self.low_bit(x)
return result
class Solution(object):
def reversePairs(self, nums):
"""
:param nums: [int]
:return: int
"""
nums2 = [x * 2 for x in nums]
dmap = {v: k for k, v in enumerate(sorted(set(nums + nums2)), start=1)}
fenwick = FenwickTree(len(dmap))
ans = 0
for n in nums2[::-1]:
ans += fenwick.get_sum(dmap[n/2]-1)
fenwick.add(dmap[n], 1)
return ans
它的做法是将数组里乘以2的值对应的下标计算出来,注意需要进行排序,这样才能保证后面BIT获取sum的时候是正确的,然后循环从后面开始是因为求的是逆序对,这样设置的时候则从后面开始设置,然后获取的sum函数意为计算nums中的值所在树中的位置前面存在多少个比n*2要大的值,然后设置的时候要设置nums2中的值,因为题目要求的就是比nums2的值要大的个数。
又或者都统一起来,将获取的index和设置的index都为nums中的值或许更容易理解一些,如下:
import bisect
class Solution(object):
def reversePairs(self, nums):
"""
:param nums: [int]
:return: int
"""
nums2 = sorted([x * 2 for x in nums])
n = len(nums2)
fenwick = FenwickTree(n)
order, binary_order = {}, {}
for i in range(n):
binary_order[i] = bisect.bisect_left(nums2, nums[i]) # num中的值在nums2中的位置
order[nums2[i]/2] = i+1 # nums中的值对应的位置
ans = 0
for i in range(n-1, -1, -1):
ans += fenwick.get_sum(binary_order[i]) # 获取前面存在多少个数
fenwick.add(order[nums[i]], 1) # 设置num的位置
return ans
[LeetCode] Reverse Pairs 翻转对的更多相关文章
- [LeetCode] 493. Reverse Pairs 翻转对
Given an array nums, we call (i, j) an important reverse pair if i < j and nums[i] > 2*nums[j] ...
- [LintCode] Reverse Pairs 翻转对
For an array A, if i < j, and A [i] > A [j], called (A [i], A [j]) is a reverse pair.return to ...
- LeetCode -Reverse Pairs
my solution: class Solution { public: int reversePairs(vector<int>& nums) { int length=num ...
- [LeetCode] Reverse String 翻转字符串
Write a function that takes a string as input and returns the string reversed. Example: Given s = &q ...
- [LeetCode] Reverse Integer 翻转整数
Reverse digits of an integer. Example1: x = 123, return 321 Example2: x = -123, return -321 click to ...
- 493 Reverse Pairs 翻转对
给定一个数组 nums ,如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对.你需要返回给定数组中的重要翻转对的数量.示例 1:输入: ...
- [Swift]LeetCode493. 翻转对 | Reverse Pairs
Given an array nums, we call (i, j) an important reverse pair if i < j and nums[i] > 2*nums[j] ...
- [LeetCode] Reverse Words in a String II 翻转字符串中的单词之二
Given an input string, reverse the string word by word. A word is defined as a sequence of non-space ...
- [LeetCode] 190. Reverse Bits 翻转二进制位
Reverse bits of a given 32 bits unsigned integer. For example, given input 43261596 (represented in ...
随机推荐
- MinHook测试与分析(x86下 E8,E9,EB,CALL指令测试,且逆推测试微软热补丁)
依稀记得第一次接触Hook的概念是在周伟民先生的书中-><<多任务下的数据结构与算法>>,当时觉得Hook的本质就是拦截,就算到现在也是如此认为. 本篇文章是在x86下测 ...
- SpringMVC第六篇【校验、统一处理异常】
Validation 在我们的Struts2中,我们是继承ActionSupport来实现校验的-它有两种方式来实现校验的功能 手写代码 XML配置 这两种方式也是可以特定处理方法或者整个Action ...
- Oracle-表的字段增加修改删除操作
表结构修改 ALTER TABLE SCOTT.TEST RENAME TO TEST1--修改表名 ALTER TABLE SCOTT.TEST RENAME COLUMN NAME TO NAME ...
- Mybatis学习(三)XML配置文件之mybatis-config.xml
1.MyBatis的配置文件结构 1.1 properties 这些是外部化的,可替代的属性,这些属性也可以配置在典型的 Java 属性配置文件中,或者通过 properties 元素的子元素来传递. ...
- Centos7搭建kubernetes搭建
安装前的准备工作: Kubernetes包提供了一些服务:kube-apiserver,kube-scheduler,kube-controller-manager,kubelet,kube-prox ...
- EntityFramework 6.x多个上下文迁移实现分布式事务
前言 自从项目上了.NET Core平台用上了EntityFramework Core就再没碰过EntityFramework 6.x版本,目前而言EntityFramework 6.x是用的最多,无 ...
- CentOS7下安装MariaDB
环境:Window10 上建立 VMWare 虚拟机,EasyInstaller 方式安装 CentOS 7 1. “失败”的经历 备份原 repo 文件,并更改 yum 源(方法详见修改yum源)为 ...
- apollo实现c#与android消息推送(三)
3 实现c#消息推送服务 c#实现消息推送必须引入M2Mqtt.dll,源码 a 连接apache apollo代理服务器的代码.需要引入using uPLibrary.Networking.M2Mq ...
- 委托、事件、Observer观察者模式的使用解析二
一.设计模式-Observer观察者模式 Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新.Observer模式是一种 ...
- Java面向对象 Main函数 静态的应用 单例设计模式
Java面向对象 Main函数 静态的应用与单例设计模式 知识概要 (1)Main函数的细解 (2)静态的应用,静态变量,静态代码块,静态函数 (3)单例设计模式 1.M ...