Open azl397985856 opened 3 years ago
这类的题目,都可以用归并做,归并天然有顺序的概念,只要在merge的时候加cnt即可。是很重要的技巧。但因为这里是nums[i] > 2 * nums[j] 无法直接在原来的排序代码里面计算,需要另外计算
class Solution:
def __init__(self):
self.cnt = 0
def solve(self, nums):
def merge_sort(nums):
if len(nums) <= 1:
return nums
mid = len(nums) // 2
left = merge_sort(nums[:mid])
right = merge_sort(nums[mid:])
return merge(left, right)
def merge(left, right):
i, j = 0, 0
res = []
# 不能直接在合并的代码里面计算,要另外计算
while i < len(left) and j < len(right):
if left[i] > 3 * right[j]:
self.cnt += len(left) - i
j += 1
else:
i += 1
i, j = 0, 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
res.append(left[i])
i += 1
else:
res.append(right[j])
j += 1
res += left[i:]
res += right[j:]
return res
merge_sort(nums)
return self.cnt
从左到右扫一遍,借助一个新的序列,每次相当于在新的序列里面用最右二分查找数值(3n)可以插入的地方,然后把n也用最右二分插入。这题数列看上去不是有序的,但是由于i>j的要求,可以一个个放进新的序列,形成一个新的有序的数列,比较巧妙。
但是直接用list复杂度和暴力是一样的。需要优化insert的复杂度,可以用SortedList
class Solution:
def solve(self, nums):
def bisect_right(arr, x):
l, r = 0, len(arr) - 1
while l <= r:
mid = l + (r - l) // 2
if arr[mid] <= x:
l = mid + 1
else:
r = mid - 1
return l
res = 0
d = []
for n in nums:
# 找到3n最右插入的位置
i = bisect_right(d, 3 * n)
res += len(d) - i
d.insert(bisect_right(d, n), n)
return res
# 优化insert
from sortedcontainers import SortedList
class Solution:
def solve(self, nums):
res = 0
d = SortedList()
for n in nums:
# 找到3n最右插入的位置
i = d.bisect_right(3 * n)
res += len(d) - i
d.add(n)
return res
这类的题目,都可以用归并做,归并天然有顺序的概念,只要在merge的时候加cnt即可。是很重要的技巧。但因为这里是nums[i] > 2 * nums[j] 无法直接在原来的排序代码里面计算,需要另外计算
class Solution:
def __init__(self):
self.cnt = 0
def solve(self, nums):
def merge_sort(nums):
if len(nums) <= 1:
return nums
mid = len(nums) // 2
left = merge_sort(nums[:mid])
right = merge_sort(nums[mid:])
return merge(left, right)
def merge(left, right):
i, j = 0, 0
res = []
# 不能直接在合并的代码里面计算,要另外计算
while i < len(left) and j < len(right):
if left[i] > 3 * right[j]:
self.cnt += len(left) - i
j += 1
else:
i += 1
i, j = 0, 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
res.append(left[i])
i += 1
else:
res.append(right[j])
j += 1
res += left[i:]
res += right[j:]
return res
merge_sort(nums)
return self.cnt
从左到右扫一遍,借助一个新的序列,每次相当于在新的序列里面用最右二分查找数值(3n)可以插入的地方,然后把n也用最右二分插入。这题数列看上去不是有序的,但是由于i>j的要求,可以一个个放进新的序列,形成一个新的有序的数列,比较巧妙。
但是直接用list复杂度和暴力是一样的。需要优化insert的复杂度,可以用SortedList
class Solution:
def solve(self, nums):
def bisect_right(arr, x):
l, r = 0, len(arr) - 1
while l <= r:
mid = l + (r - l) // 2
if arr[mid] <= x:
l = mid + 1
else:
r = mid - 1
return l
res = 0
d = []
for n in nums:
# 找到3n最右插入的位置
i = bisect_right(d, 3 * n)
res += len(d) - i
d.insert(bisect_right(d, n), n)
return res
# 优化insert
from sortedcontainers import SortedList
class Solution:
def solve(self, nums):
res = 0
d = SortedList()
for n in nums:
# 找到3n最右插入的位置
i = d.bisect_right(3 * n)
res += len(d) - i
d.add(n)
return res
class Solution:
def solve(self, A):
d = SortedList()
ans = 0
for a in A:
i = d.bisect_right(a * 3)
ans += len(d) - i
d.add(a)
return ans
import java.util.*;
class Solution {
public int solve(int[] nums) {
List<Integer> list = new ArrayList<Integer>();
int count = 0;
for(int i = 0;i < nums.length;i++){
int pos = findFirstGt(list,nums[i] * 3);
count += (list.size() - pos);
list.add(findFirstGt(list,nums[i]),nums[i]);
}
return count;
}
private int findFirstGt(List<Integer> list,int target){
if(list.isEmpty()){
return 0;
}
int start = 0;
int lastIdx = list.size() - 1;
int end = lastIdx;
while(start <= end){
int mid = start + (end - start)/2;
if(list.get(mid) <= target){
start = mid + 1;
}else {
end = mid - 1;
}
}
return start;
}
}
class Solution {
public int solve(int[] nums) {
if (nums == null || nums.length == 0) return 0;
TreeMap<Integer, Integer> map = new TreeMap<>();
map.put(nums[i], 1);
int count = 0;
for (int i = 1; i < nums.length; i++){
Map<Integer, Integer> candidates = map.tailMap(nums[i] * 3, false);
for (int n : candidates.keySet()){
count += candidates.get(n);
}
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
}
return count;
}
}
Time Complexity: O(NlogN), Space Complexity: O(n)
时间 logn
空间 n
from sortedcontainers import SortedList
class Solution:
def solve(self, A):
sl = SortedList()
ans = 0
for a in A:
n = sl.bisect_right(a*3)
ans += len(sl) - n
sl.add(a)
class Solution:
def solve(self, nums):
sl = SortedList()
ret = 0
for n in nums:
idx = sl.bisect_right(n*3)
ret += len(sl) - idx
sl.add(n)
return ret
Use binary search and build your own sorted array. The idea is if one number in left array qualities for nums[i] * 3 < num[j]
, then every num beyond this num in the sorted array should all qualify for it.
from sortedcontainers import SortedList
class Solution:
def solve(self, nums):
d = SortedList()
ans = 0
for num in nums:
i = d.bisect_right(num * 3)
ans += len(d) - i
d.add(num)
return ans
class Solution {
public int solve(int[] nums) {
if (nums == null || nums.length == 0) return 0;
TreeMap<Integer, Integer> map = new TreeMap<>();
map.put(nums[i], 1);
int count = 0;
for (int i = 1; i < nums.length; i++){
Map<Integer, Integer> candidates = map.tailMap(nums[i] * 3, false);
for (int n : candidates.keySet()){
count += candidates.get(n);
}
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
}
return count;
}
}
class Solution:
def solve(self, nums):
def binarySearch(temp, target):
left = 0
right = len(temp)
while left<right:
mid = (right+left)//2
if temp[mid]<= target:
left = mid+1
else:
right = mid
return left
count = 0
temp = []
for num in nums:
smaller_count = binarySearch(temp,num*3)
print(temp,smaller_count)
count += len(temp) - smaller_count
idx = binarySearch(temp,num)
temp.insert(idx,num)
return count
二分法(参考官网,双for循环会超时)
``
public class Solution extends VersionControl {
public int solve(int[] nums) {
List<Integer> list = new ArrayList();
int ret = 0;
for (int i = 0; i < nums.length; i++) {
int where = find(list, nums[i] * 3);
ret += list.size() - where;
list.add(find(list, nums[i]), nums[i]);
}
return ret;
}
public int find(List<Integer> list, int find) {
int l = 0;
int r = list.size();
while (l < r) {
int mid = l + (r - l) / 2;
if (list.get(mid) > find) {
r = mid;
} else {
l = mid + 1;
}
}
return l;
}
}
时间复杂度:O(n^2logn)
空间复杂度:O(n)
使用 SortedList cur
遍历数组, 然后 bisect_right 查找 大于等于 n*2 的第一个数的 位置 loc
res += len(cur) - loc 因为大于等于 n * 2 的数是从 cur[loc, len(cur)-1]
然后将 n 加入 cur 中
from sortedcontainers import SortedList
import bisect
class Solution:
def reversePairs(self, nums: List[int]) -> int:
res = 0
cur = SortedList()
for n in nums:
loc = cur.bisect_right(n*2)
res += len(cur) - loc
cur.add(n)
return res
时间复杂度: O(nlogn)
空间复杂度: O(n)
from sortedcontainers import SortedList
class Solution:
def solve(self, A):
d = SortedList()
ans = 0
for a in A:
i = d.bisect_right(a * 3)
ans += len(d) - i
d.add(a)
return ans
时间复杂度:O(NLogN)
空间复杂度:O(N)
class Solution:
def solve(self, nums):
if not nums:
return 0
comp = []
count = 0
for i in range(len(nums)):
insInd = bisect_right(comp, 3 * nums[i])
count += len(comp) - insInd
insort(comp, nums[i])
return count
class Solution: def isPrime(self,num:int) -> bool: if num == 1: return False for i in range(2,num): if num % i == 0 and num != i: return False return True def count_one(self,num): count = 0 while num != 0: if num %2 == 1: count += 1 num = int(num/2) return count def countPrimeSetBits(self, left: int, right: int) -> int: answer = 0 for i in range(left,right+1): if self.isPrime(self.count_one(i)) == True: answer += 1 return answer
''' class Solution: def solve(self, nums): def binarySearch(temp, target): left = 0 right = len(temp) while left<right: mid = (right+left)//2 if temp[mid]<= target: left = mid+1 else: right = mid return left count = 0 temp = [] for num in nums: smaller_count = binarySearch(temp,num*3) print(temp,smaller_count) count += len(temp) - smaller_count idx = binarySearch(temp,num) temp.insert(idx,num) return count '''
class Solution:
def solve(self, nums):
if not nums:
return 0
comp = []
count = 0
for i in range(len(nums)):
insInd = bisect_right(comp, 3 * nums[i])
count += len(comp) - insInd
insort(comp, nums[i])
return count
int solve(vector<int>& nums) {
map<int, int> mymap;
int ans = 0;
for (auto& num : nums)
{
auto iter = mymap.upper_bound(3*num);
if (iter != mymap.end())
{
for (auto it = iter; it != mymap.end(); it++)
ans += it->second;
}
if (mymap.count(num) > 0)
mymap[num]++;
else mymap[num] = 1;
}
return ans;
}
var reversePairs = function (nums) {
if (nums.length == 0) {
return 0;
}
let count = 0;
function mergeSort(nums, start, end) {
if (start == end) {
return 0;
}
const mid = start + ((end - start) >> 1);
mergeSort(nums, start, mid);
mergeSort(nums, mid + 1, end);
let i = start;
let j = mid + 1;
while (i <= mid && j <= end) {
if (nums[i] > 2 * nums[j]) {
count += mid - i + 1;
j++;
} else {
i++;
}
}
i = start;
j = mid + 1;
const temp = new Array(end - start + 1);
let index = 0;
while (i <= mid && j <= end) {
if (nums[i] < nums[j]) {
temp[index] = nums[i];
index++;
i++;
} else {
temp[index] = nums[j];
index++;
j++;
}
}
while (i <= mid) {
temp[index] = nums[i];
index++;
i++;
}
while (j <= end) {
temp[index] = nums[j];
index++;
j++;
}
for (let i = start, k = 0; i <= end; i++, k++) {
nums[i] = temp[k];
}
}
mergeSort(nums, 0, nums.length - 1);
return count;
};
时间复杂度:O(NLogN)
空间复杂度:O(N)
vector<int> vec;
int reversePairs(vector<int>& nums) {
return merge_sort(nums, 0, nums.size() - 1);
}
int merge_sort(vector<int> &nums, int left, int right){
if (left >= right) {
return 0;
}
int mid = left + ((right - left) >> 1);
int res = merge_sort(nums, left, mid) + merge_sort(nums, mid + 1, right);
//计数
for (int i = left, j = mid + 1; i <= mid; ++i){
while (j <= right && nums[j] * 2ll < nums[i]){
++j;
}
res += j - mid - 1;
}
vec.clear();
//合并
int i = left, j = mid + 1;
while (i <= mid && j <= right){
if (nums[i] <= nums[j]) {
vec.push_back(nums[i++]);
}
else {
vec.push_back(nums[j++]);
}
}
while (i <= mid) {
vec.push_back(nums[i++]);
}
while (j <= right) {
vec.push_back(nums[j++]);
}
for (i = left, j = 0; j < vec.size(); ++i, ++j) {
nums[i] = vec[j];
}
return res;
}
这一题算二分么,实在想不到,所以在没思路的情况下又一次看了题解
class Solution {
public int solve(int[] nums) {
if(nums.length<2)return 0;
ArrayList
}
public int indexofright(ArrayList<Integer> list,int a){
int l = 0,r =list.size()-1;
while(l<=r){
int mid = l + (r - l) / 2;
if(list.get(mid) <= a){
l = mid +1;
}else{
r = mid -1;}
}
return l;
}
}
先写一个暴力解
class Solution:
def solve(self, nums):
count = 0
for i in range len(nums):
for j in range(i, len(nums)):
if nums[i] > nums[j]*3:
count+=1
return count
先将队列进行排序之后再进行二分法查找
class Solution:
def solve(self, nums):
sl = SortedList()
ret = 0
for n in nums:
idx = sl.bisect_right(n*3)
ret += len(sl) - idx
sl.add(n)
return ret
class Solution {
public int countPrimeSetBits(int L, int R) {
int ans = 0;
for (int n = L; n <= R; ++n)
if (isPrime(bits(n))) ++ans;
return ans;
}
private boolean isPrime(int n) {
if (n <= 1) return false;
if (n == 2) return true;
for (int i = 2; i <= (int)Math.sqrt(n); ++i)
if (n % i == 0) return false;
return true;
}
private int bits(int n) {
int s = 0;
while (n != 0) {
s += n & 1;
n >>= 1;
}
return s;
}
}
//空间复杂: O(n)
//时间复杂:O(nlogn)
class Solution: def solve(self, nums): def bisect_right(arr, x): l, r = 0, len(arr) - 1 while l <= r: mid = l + (r - l) // 2 if arr[mid] <= x: l = mid + 1 else: r = mid - 1 return l res = 0 d = [] for n in nums:
i = bisect_right(d, 3 * n)
res += len(d) - i
d.insert(bisect_right(d, n), n)
return res
class Solution { public int countPrimeSetBits(int L, int R) { int ans = 0; for (int n = L; n <= R; ++n) if (isPrime(bits(n))) ++ans; return ans; }
private boolean isPrime(int n) {
if (n <= 1) return false;
if (n == 2) return true;
for (int i = 2; i <= (int)Math.sqrt(n); ++i)
if (n % i == 0) return false;
return true;
}
private int bits(int n) {
int s = 0;
while (n != 0) {
s += n & 1;
n >>= 1;
}
return s;
}
}
762.Number Stream to Intervals
入选理由
暂无
题目地址
https://binarysearch.com/problems/Triple-Inversion
前置知识
- 二分法
题目描述
Given a list of integers nums, return the number of pairs i < j such that nums[i] > nums[j] * 3. Constraints n ≤ 100,000 where n is the length of nums Example 1 Input nums = [7, 1, 2] Output 2 Explanation We have the pairs (7, 1) and (7, 2)
from sortedcontainers import SortedList
class Solution:
def solve(self, A):
list1=SortedList()
res1=0
for a in A:
i=list1.bisect_right(a*3)#寻找插入位置
res1+=len(list1)-i
list1.add(a)
return res1
if __name__=="__main__":
sol=Solution()
print(sol.solve([10,1,2,3,6,7]))
时间复杂度:O(nlog(n)) 空间复杂度:O(n)
class Solution { public int countPrimeSetBits(int L, int R) { int ans = 0; for (int n = L; n <= R; ++n) if (isPrime(bits(n))) ++ans; return ans; }
private boolean isPrime(int n) { if (n <= 1) return false; if (n == 2) return true; for (int i = 2; i <= (int)Math.sqrt(n); ++i) if (n % i == 0) return false; return true; }
private int bits(int n) { int s = 0; while (n != 0) { s += n & 1; n >>= 1; } return s; } }
class Solution: def solve(self, nums): if not nums: return 0 comp = [] count = 0 for i in range(len(nums)): insInd = bisect_right(comp, 3 * nums[i]) count += len(comp) - insInd insort(comp, nums[i]) return count
vector<int> temp;
int merge(vector<int>& nums, int s, int e) {
int i = s, mid = s + (e - s) / 2, j = mid + 1, t = s, k = 0, ret = 0;
while (i <= mid and j <= e) {
if (nums[i] > nums[j]) {
while (t <= mid and nums[t] <= nums[j] * 3) {
t++;
}
ret += (mid - t + 1);
temp[k++] = nums[j++];
} else {
temp[k++] = nums[i++];
}
}
while (i <= mid) temp[k++] = nums[i++];
while (j <= e) temp[k++] = nums[j++];
for (int k = 0, i = s; k < e - s + 1; k++) {
nums[i++] = temp[k];
}
return ret;
}
int mergeSort(vector<int>& nums, int s, int e) {
if (s >= e) return 0;
int m = s + (e - s) / 2;
return mergeSort(nums, s, m) + mergeSort(nums, m + 1, e) + merge(nums, s, e);
}
int solve(vector<int>& nums) {
temp.resize(nums.size(), 0);
return mergeSort(nums, 0, nums.size() - 1);
}
import java.util.*;
class Solution10 {
public static void main(String[] args) {
int [] nums = {7, 1, 2};
solve(nums);
}
public static int solve(int[] nums) {
List<Integer> list = new ArrayList();
int ret = 0;
for (int i = 0; i < nums.length; i++) {
int where = find(list, nums[i] * 3);
// 后面的均可以匹配
ret += list.size() - where;
// 根据大小排序
list.add(find(list, nums[i]), nums[i]);
}
return ret;
}
// 二分查找
public static int find(List<Integer> list, int find) {
int l = 0;
int r = list.size();
while (l < r) {
int mid = l + (r - l) / 2;
if (list.get(mid) > find) {
r = mid;
} else {
l = mid + 1;
}
}
return l;
}
}
class Solution: def init(self): self.cnt = 0 def reversePairs(self, nums): """ :type nums: List[int] :rtype: int """ def msort(A):
L = len(A)
if L <= 1: # base case
return A
else: # recursive case
return merger(msort(A[:int(L/2)]), msort(A[int(L/2):]))
def merger(left, right):
l, r = 0, 0 # increase l and r iteratively
while l < len(left) and r < len(right):
if left[l] <= 3*right[r]:
l += 1
else:
self.cnt += len(left)-l # COUNT here
r += 1
res = [] # merger
i, j = 0, 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
res += left[i],
i += 1
else:
res += right[j],
j += 1
while i != len(left):
res += left[i],
i += 1
while j != len(right):
res += right[j],
j += 1
return res
msort(nums)
return self.cnt
二分查找与insort插入
import bisect
class Solution:
def solve(self, nums):
if not nums:
return 0
comp = []
count = 0
for i in range(len(nums)):
insInd = bisect.bisect_right(comp, 3 * nums[i])
count += len(comp) - insInd
bisect.insort(comp, nums[i])
return count
class Solution {
public int countPrimeSetBits(int L, int R) {
int ans = 0;
for (int n = L; n <= R; ++n)
if (isPrime(bits(n))) ++ans;
return ans;
}
private boolean isPrime(int n) {
if (n <= 1) return false;
if (n == 2) return true;
for (int i = 2; i <= (int)Math.sqrt(n); ++i)
if (n % i == 0) return false;
return true;
}
private int bits(int n) {
int s = 0;
while (n != 0) {
s += n & 1;
n >>= 1;
}
return s;
}
}
int merg_sort(vector<int>& nums)
{
if(nums.size() < 2){
return 0;
}
vector<int> lv, rv;
int ans = 0;
int ii, jj, kk;
int mid;
mid = nums.size() >> 1;
for(ii = 0; ii < mid; ++ ii){
lv.push_back(nums[ii]);
}
for(; ii < nums.size(); ++ ii){
rv.push_back(nums[ii]);
}
ans += merg_sort(lv);
ans += merg_sort(rv);
ii = 0;
jj = 0;
kk = 0;
while(ii < lv.size() && jj < rv.size()){
if(lv[ii] <= rv[jj]){
nums[kk++] = lv[ii++];
continue;
}
int ll = ii;
int rr = lv.size() - 1;
if(lv[rr] > 3 * rv[jj]){
int mm;
while(ll < rr){
mm = ll + rr >> 1;
if(lv[mm] > 3 * rv[jj]){
rr = mm;
}else{
ll = mm + 1;
}
}
ans += lv.size() - rr;
}
nums[kk ++] = rv[jj ++];
}
while(ii < lv.size()){
nums[kk ++] = lv[ii ++];
}
while(jj < rv.size()){
nums[kk ++] = rv[jj ++];
}
return ans;
}
int solve(vector<int>& nums) {
int n = nums.size();
if(n < 2) return 0;
int ans = merg_sort(nums);
return ans;
}
n数组长度
import java.util.*;
class Solution {
public int solve(int[] nums) {
List
public int find(List<Integer> list,Integer num){
Integer left = 0;
Integer right = list.size();
Integer mid = 0;
while(left < right){
mid = left + (right - left) / 2;
if(list.get(mid)>num){
right = mid;
}
else{
left = mid + 1;
}
}
return left;
}
}
思路:第一反应是使用暴力,时间复杂度要O(n*n),看了解析后才知道原来可以使用二分来完成,但需要自己构建一个有序的数组。
public static int solve(int[] nums) { if (nums == null || nums.length == 0) return 0; int arr[] = new int[nums.length]; int index = 0; arr[index++] = nums[0]; int res = 0; for(int i=1;i<nums.length;i++){ int temp = nums[i]*3; //使用二分法 int left = 0,right = index-1; while(left<=right){ int mid = (right-left)/2 + left; if(arr[mid]>temp){ left=mid + 1; }else { right = mid -1; } } //进行插入 res += left; int j =index; for(;j>left;j--){ arr[j]=arr[j-1]; } arr[j] = nums[i]; } return res; }
var reversePairs = function (nums) {
if (nums.length == 0) {
return 0;
}
let count = 0;
function mergeSort(nums, start, end) {
if (start == end) {
return 0;
}
const mid = start + ((end - start) >> 1);
mergeSort(nums, start, mid);
mergeSort(nums, mid + 1, end);
let i = start;
let j = mid + 1;
while (i <= mid && j <= end) {
if (nums[i] > 2 * nums[j]) {
count += mid - i + 1;
j++;
} else {
i++;
}
}
i = start;
j = mid + 1;
const temp = new Array(end - start + 1);
let index = 0;
while (i <= mid && j <= end) {
if (nums[i] < nums[j]) {
temp[index] = nums[i];
index++;
i++;
} else {
temp[index] = nums[j];
index++;
j++;
}
}
while (i <= mid) {
temp[index] = nums[i];
index++;
i++;
}
while (j <= end) {
temp[index] = nums[j];
index++;
j++;
}
for (let i = start, k = 0; i <= end; i++, k++) {
nums[i] = temp[k];
}
}
mergeSort(nums, 0, nums.length - 1);
return count;
};
javascript
function tripleInversion(nums) {
if (!nums.length || nums.length === 1) return 0
let count = 0
while (nums.length > 1) {
let last = nums.pop()
let tripleLast = last * 3
for (let el of nums) {
if (el > tripleLast) count++
}
}
return count
}
class Solution { public int countPrimeSetBits(int L, int R) { int ans = 0; for (int n = L; n <= R; ++n) if (isPrime(bits(n))) ++ans; return ans; }
private boolean isPrime(int n) {
if (n <= 1) return false;
if (n == 2) return true;
for (int i = 2; i <= (int)Math.sqrt(n); ++i)
if (n % i == 0) return false;
return true;
}
private int bits(int n) {
int s = 0;
while (n != 0) {
s += n & 1;
n >>= 1;
}
return s;
}
}
Using merge sort to solve this problem. Increase the count of pairs during each merge operation.
Referring to the solution.
class Solution:
def solve(self, nums):
self.count = 0
def merge(nums, start, mid, end, temp):
i = start
j = mid + 1
while i <= mid and j <= end:
if nums[i] <= nums[j]:
temp.append(nums[i])
i += 1
else:
temp.append(nums[j])
j += 1
s, l = start, mid + 1
while s <= mid and l <= end:
if nums[s] <= 3 * nums[l]:
s += 1
else:
self.count += mid - s + 1
s += 1
while i <= mid:
temp.append(nums[i])
i += 1
while j <= end:
temp.append(nums[j])
j += 1
for i in range(len(temp)):
nums[start + i] = temp[i]
temp.clear()
def merge_sort(nums, start, end, temp):
if start >= end :
return
mid = start + (end - start) // 2
merge_sort(nums, start, mid, temp)
merge_sort(nums, mid + 1, start, temp)
merge(nums, start, mid, end, temp)
merge_sort(nums, 0, len(nums)-1, [])
return self.count
Time complexity: O(nlogn) (merge sort). Space complexity: O(n)
sortedcontainers.SortedList
to achieve logN insertion.class Solution:
def solve(self, nums):
prev = []
res = 0
for n in nums:
# the index of first val > n*3
i = bisect.bisect_right(prev, n * 3)
res += len(prev) - i
bisect.insort(prev, n)
return res
Time complexity: O(N^2)
Space complexity: O(N)
import sortedcontainers
class Solution:
def solve(nums):
prev = sortedcontainers.SortedList()
res = 0
for n in nums:
# the index of first val > n*3
i = bisect.bisect_right(prev, n * 3)
res += len(prev) - i
prev.add(n)
return res
Time complexity: O(NlogN)
Space complexity: O(N)
Algo
- Sometimes u can construct a sorted list urself.
from sortedcontainers import SortedList
class Solution:
def solve(self, A):
d = SortedList()
ans = 0
for a in A:
i = d.bisect_right(a * 3)
ans += len(d) - i
d.add(a)
return ans
class Solution {
public:
int reversePairs(vector<int>& nums) {
return mergeSort(nums, 0, nums.size() - 1);
}
int mergeSort(vector<int>& nums, int left, int right) {
if (left >= right) return 0;
int mid = left + (right - left) / 2;
int res = mergeSort(nums, left, mid) + mergeSort(nums, mid + 1, right);
for (int i = left, j = mid + 1; i <= mid; ++i) {
while (j <= right && nums[i] / 2.0 > nums[j]) ++j;
res += j - (mid + 1);
}
sort(nums.begin() + left, nums.begin() + right + 1);
return res;
}
};
int solve(vector<int>& nums) {
map<int, int> mymap;
int res = 0;
for(auto& num: nums){
auto it = mymap.upper_bound(3*num);
if(it != mymap.end()){
for(auto it1 = it; it1!=mymap.end(); it1++){
res += it1->second;
}
}
mymap[num]++;
}
return res;
}
Time:O(n) Space:O(n)
merge sort变种题
java
class Solution {
private int count;
public int solve(int[] nums) {
count = 0;
sort(nums, 0, nums.length - 1);
return count;
}
private void sort(int[] nums, int start, int end) {
if (start >= end) {
return;
}
int mid = start + (end - start) / 2;
sort(nums, start, mid);
sort(nums, mid + 1, end);
merge(nums, start, mid, end);
}
private void merge(int[] nums, int start, int mid, int end) {
int[] temp = new int[nums.length];
int l = start, r = mid + 1, cur = start;
while (l <= mid && r <= end) {
if (nums[l] <= nums[r]) {
temp[cur++] = nums[l++];
} else {
temp[cur++] = nums[r++];
}
}
while (l <= mid) {
temp[cur++] = nums[l++];
}
while (r <= end) {
temp[cur++] = nums[r++];
}
l = start; r = mid + 1;
while (l <= mid && r <= end) {
if (nums[l] <= nums[r] * 3) {
l++;
} else {
count += mid - l + 1;
r++;
}
}
for (int i = start; i <= end; i++) {
nums[i] = temp[i];
}
}
}public int mySqrt(int x) {
if (x==0)return 0;
double curX=x,C=x;
while (true){
double nextX=0.5*(curX+C/curX);
if (Math.abs(curX-nextX)<1e-7)break;
curX=nextX;
}
return (int)curX;
}
binary search
Java Code:
class Solution {
public int solve(int[] nums) {
if(nums == null || nums.length < 2){
return 0;
}
int count = 0;
Map<Integer, Integer> map = new TreeMap<>();
map.put(nums[0], 1);
for(int i = 1; i < nums.length; i++){
List<Integer> keys = new ArrayList<>(map.keySet());
int boundary = binarySearch(keys, 3 * nums[i]);
for(int j = boundary; j >=0 && j < keys.size(); j++){
count += map.get(keys.get(j));
}
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
}
return count;
}
private int binarySearch(List<Integer> list, int target){
int start = 0;
int end = list.size() - 1;
while(start + 1 < end){
int mid = start + (end - start) / 2;
if(list.get(mid) > target){
end = mid;
}else if(list.get(mid) < target){
start = mid;
}else{
start = mid;
}
}
if(list.get(start) > target){
return start;
}
if(list.get(end) > target){
return end;
}
return -1;
}
}
复杂度分析
令 n 为数组长度。
再一次超时打卡。 第一次做只能brute force 暴力查找。 看了discussion 之后知道要用merge sort。 其实就是在merge sort 做好的每一次的基础上查找这一个排序好的格子里有几个符合要求,然后再一次向上recursion back的 时候跟另一个排序好的数组比。
比较方法:因为每一个走到底都会出现两个排序好的数组,想成left.list, right.left, 可以保证的是all the index in the left.list < right.index ( 最下层的时候每一个left.list, right.list 都是单独一个数字)。 那么这样只需要比较 在left.list中,如果有一个index = n (n < len(left.list)) and left.list[n] > 3* right.list[index],那么就可以确保在left.list [n:len(left.list)]后面所有的都满足 大于三倍这个条件。
class Solution:
def solve(self, nums):
if not nums: return 0
self.cnt = 0
def merge_sort(nums,start,end):
if start == end:
return [nums[start]]
mid = start+(end-start)//2
left_arr = merge_sort(nums,start,mid)
right_arr = merge_sort(nums,mid+1,end)
temp,l,r = [],0,0
while (l < len(left_arr)) and (r < len(right_arr)):
if (left_arr[l] <= right_arr[r]):
temp.append(left_arr[l])
l += 1
else:
temp.append(right_arr[r])
r += 1
ti,tj = 0,0
while (ti < len(left_arr)) and (tj < len(right_arr)):
if left_arr[ti] <= 3*right_arr[tj]:
ti += 1
else:
self.cnt += len(left_arr)-ti
tj += 1
temp += left_arr[l:]
temp += right_arr[r:]
return temp
merge_sort(nums,0,len(nums)-1)
return self.cnt
Time complexity: O(logN) Space complexity: O(N) 因为用了排序后temp 保存排序好的数组
思路 从大到小排序后查找到在map中大于当前值*3个数。 代码
struct greater
{
template <typename T>
bool operator() (const T &a, const T &b) { return a > b; }
};
int solve(vector<int>& nums) {
sort(nums.begin(), nums.end(),greater());
std::map<int, int> rMap;
int n = nums.size();
int re = 0;
for (int i = 0; i < n; i++)
{
auto it = rMap.upper_bound(3 * nums[i]);
while (it != rMap.end())
{
re += it->second;
it++;
}
rMap[nums[i]]++;
}
return re;
}
复杂度分析 时间复杂度:O(logN) 空间复杂度:O(N)
int solve(vector<int>& nums)
{
int res = 0;
map<int, int> m;
map<int, int>::iterator it;
for(int i = 0; i < nums.size(); i++)
{
it = m.upper_bound(3 * nums[i]);
while(it!= m.end())
{
res = res + it->second;
it++;
}
if(m.count(nums[i]) > 0)
m[nums[i]]++;
else
m[nums[i]] = 1;
}
return res;
}
int cnt;
void merge(vector<int>& nums, int start, int mid, int end, vector<int>& res)
{
int i = start, j = mid+1;
res.reserve(end - start + 1);
while(i <=mid && j <= end)
{
if(nums[i] > nums[j])
res.push_back(nums[j++]);
else
res.push_back(nums[i++]);
}
int l_flag = start, r_flag = mid + 1;
while(l_flag <= mid && r_flag <= end)
{
if(nums[l_flag] > 3 * nums[r_flag]) {
cnt += (mid - l_flag + 1);
r_flag++;
}
else
l_flag++;
}
while(i <= mid)
res.push_back(nums[i++]);
while(j <= end)
res.push_back(nums[j++]);
for(i=0; i < res.size(); i++)
nums[start + i] = res[i];
res.clear();
}
void mergeSort(vector<int>& nums, int start, int end, vector<int>& res)
{
if (start >= end) return;
int mid = start + (end - start) / 2;
mergeSort(nums, start, mid, res);
mergeSort(nums, mid+1, end, res);
merge(nums, start, mid, end, res);
}
int solve(vector<int>& nums)
{
vector<int> res;
cnt = 0;
mergeSort(nums, 0, nums.size() - 1, res);
return cnt;
}
762.Number Stream to Intervals
入选理由
暂无
题目地址
https://binarysearch.com/problems/Triple-Inversion
前置知识
题目描述
Constraints
n ≤ 100,000 where n is the length of nums Example 1 Input nums = [7, 1, 2] Output 2 Explanation We have the pairs (7, 1) and (7, 2)