[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 ...
随机推荐
- 接口测试入门(4)--接口自动化测试框架 / list和map用法 / 随机选取新闻 (随机数生成) / 接口相关id映射
一.接口自动化测试框架 为了更好的组织测试方法,测试用例并且持续集成,我们选择了 java+testNG(测试用例组织)+gitlab(代码版本管理)+Jenkins(持续集成工具) 作为一整套的自 ...
- mybatis-java-依赖注入
第一种 setXXX形式的注入 我们的所有dao都会继承自定义的BaseDao,因此在BaseDao中完成对所有dao的注入 在DaoUtil中增加方法injectDao()来注入具体的dao pac ...
- JS中基本的一些兼容问题 可能解释的不会太清楚
做兼容注意: 一如果两个都是属性,用逻辑||做兼容 二如果有一个是方法 用三目运算符做兼容 三多个属性或方法封装函数做兼容 一:谷歌浏览器和火狐浏览器鼠标滚动条兼容 1.document.docume ...
- L1正则化及其推导
\(L1\)正则化及其推导 在机器学习的Loss函数中,通常会添加一些正则化(正则化与一些贝叶斯先验本质上是一致的,比如\(L2\)正则化与高斯先验是一致的.\(L1\)正则化与拉普拉斯先验是一致的等 ...
- 微信公众号开发——关于“WeixinJSBridge.call('closeWindow');”无效的问题
最近在做微信公众号的开发,再做一个jsp的用户绑定页面,设置了一个timestamp,想实现的是当链接超时时alert一个窗口提示然后关闭网页窗口 但是呢,在jsp页面内直接 out.print(&q ...
- 【设计模式】module模式&&Revealing module (揭示)模式
写在前面 <head first设计模式>里有一篇文章,是说使用模式的心智, 1.初学者"心智" :"我要为HELLO WORLD找个模式" 2.中 ...
- 【京东账户】——Mysql/PHP/Ajax爬坑之用户登录
一.引言 实现京东的账户项目,功能模块之一,用户登录.要用到的是Apach环境,Mysql.PHP以及Ajax. 二.依据功能创建库.表.记录 创建库:jd 创建表:登录表 添加三条记录 CREATE ...
- 解决外部编辑器修改Eclipse文件延迟刷新【补充】
在之前的文章,使用gulp解决外部编辑器修改Eclipse文件延迟刷新,原理是用gulp把更改过的项目文件直接复制一份到Tomcat的webapp.root下, 现在补充另外一种方法,双击Server ...
- 自己写实现char TO wchar_t 的转换
wchar_t CharToWChart(char nChar){ wchar_t nR; nR=nChar+32*256; return nR;}//--------------- ...
- 几个 Cookie 操作例子的分析
MDN 上提供了操作 Cookie 的若干个例子,也有一个简单的 cookie 框架,今天尝试分析一下,最后是 jquery-cookie 插件的分析. document.cookie 的操作例子 例 ...