leetcode-pp / 91alg-5-daily-check

91 天学算法第五期打卡
55 stars 14 forks source link

【Day 39 】2021-10-18 - 762.Number Stream to Intervals #56

Open azl397985856 opened 3 years ago

azl397985856 commented 3 years ago

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)

naomiwufzz commented 3 years ago

思路1:归并排序

这类的题目,都可以用归并做,归并天然有顺序的概念,只要在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

复杂度分析

思路2:二分

从左到右扫一遍,借助一个新的序列,每次相当于在新的序列里面用最右二分查找数值(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

复杂度分析

naomiwufzz commented 3 years ago

思路1:归并排序

这类的题目,都可以用归并做,归并天然有顺序的概念,只要在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

复杂度分析

思路2:二分

从左到右扫一遍,借助一个新的序列,每次相当于在新的序列里面用最右二分查找数值(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

复杂度分析

chakochako commented 3 years ago
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
jaysonss commented 3 years ago

思路

代码

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;
    }
}

复杂度分析

xj-yan commented 3 years ago
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)

flagyk5 commented 3 years ago
时间 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) 
heyqz commented 3 years ago
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
Yufanzh commented 3 years ago

Intuition

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.

Algorithm in python3

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

Complexity Analysis

machuangmr commented 3 years ago

题目762.Number Stream to Intervals

思路: 先打个卡,不是特别明白,可以使用Map来做

代码

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;
    }
}

复杂度

JAYWX commented 3 years ago
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
ymkymk commented 3 years ago

思路

二分法(参考官网,双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)

joeytor commented 3 years ago

思路

使用 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)

yibenxiao commented 3 years ago

【Day 39】762.Number Stream to Intervals

思路

  1. 平衡二叉树存储
  2. 二分法查找

代码

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)

Shinnost commented 3 years ago
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
Toms-BigData commented 3 years ago

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

CruiseYuGH commented 3 years ago

''' 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 '''

ymwang-2020 commented 3 years ago

 代码

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
xingkong1994 commented 3 years ago
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;
}
winterdogdog commented 3 years ago
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;
};

复杂度

mokrs commented 3 years ago
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;
}

这一题算二分么,实在想不到,所以在没思路的情况下又一次看了题解

brainlds commented 3 years ago

class Solution { public int solve(int[] nums) { if(nums.length<2)return 0; ArrayList list = new ArrayList<>(); list.add(nums[0]); int ans = 0; for(int i = 1;i<nums.length;i++){ int b = indexofright(list,nums[i]*3); ans = ans +(list.size() - b); int c = indexofright(list,nums[i]); list.add(c,nums[i]); } return ans;

}
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;
}

}

ChenJingjing85 commented 3 years ago

思路

先写一个暴力解

代码

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

复杂度分析

qibao1112 commented 3 years ago

思路

先将队列进行排序之后再进行二分法查找

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
vincentLW commented 3 years ago
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)
dahuang257 commented 3 years ago

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
shanrufu commented 3 years ago

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; } }

SunStrongChina commented 3 years ago

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)

解法,二叉平衡树还是过于优秀了,插入节点的时间复杂度只有logn

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)

lihanchenyuhua commented 3 years ago

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; } }

liangsen-zju commented 3 years ago

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

ff1234-debug commented 3 years ago

思路

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);
}

复杂度分析

guangsizhongbin commented 3 years ago

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;
}

}

leo173701 commented 3 years ago

class Solution: def init(self): self.cnt = 0 def reversePairs(self, nums): """ :type nums: List[int] :rtype: int """ def msort(A):

merge sort body

        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
BreezePython commented 3 years ago

思路

二分查找与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

复杂度

yj9676 commented 3 years ago
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;
  }
}
comst007 commented 3 years ago

762. Triple Inversion


思路

分治思想 基于归并排序

代码

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数组长度

xinhaoyi commented 3 years ago

import java.util.*;

class Solution { public int solve(int[] nums) { List list = new ArrayList<>(); int length = nums.length; int count = 0; for(int i = 0; i < length; i++){ int where = find(list,3*nums[i]); count += list.size() - where; list.add(find(list,nums[i]),nums[i]); } return count; }

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;
}

}

Zhang6260 commented 3 years ago

JAVA版本

思路:第一反应是使用暴力,时间复杂度要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;
   }

时间复杂度:O(nlogn)

空间复杂度:O(n)

lihuiwen commented 3 years ago

代码

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;
};
joriscai commented 3 years ago

思路

代码

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
}

复杂度分析

moxiaopao278 commented 3 years ago

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; } }

LareinaWei commented 3 years ago

Thinking

Using merge sort to solve this problem. Increase the count of pairs during each merge operation.

Code

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

Complexity

Time complexity: O(nlogn) (merge sort). Space complexity: O(n)

skinnyh commented 3 years ago

Note

Solution 1 - Native list

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)

Solution 2 - SortedList

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)

MonkofEast commented 3 years ago

000. Number Stream to Intervals

Click Me

Algo

  1. Sometimes u can construct a sorted list urself.

Code

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

Comp

T: O(nlogN)

S: O(N)

itsjacob commented 3 years ago

Intuition

Implementation

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;
    }
};

Complexity

V-Enzo commented 3 years ago

思路

  1. 转换为统计在这之前出现的元素的大小能否满足大于3倍后面插入的数字
  2. hash map能够自动对输入的数据进行从小到大的排序。
    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;
    }

    Complexity

    Time:O(n) Space:O(n)

ZETAVI commented 3 years ago

思路

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;
    }

复杂度分析

mixtureve commented 3 years ago

思路

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 为数组长度。

Venchyluo commented 3 years ago

再一次超时打卡。 第一次做只能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 保存排序好的数组

lizzy-123 commented 3 years ago

思路 从大到小排序后查找到在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)

ccslience commented 3 years ago
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;
}