zoukankan      html  css  js  c++  java
  • 327. Count of Range Sum(inplace_marge)

    Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive.
    Range sum S(i, j) is defined as the sum of the elements in nums between indices i and j (i ≤ j), inclusive.

    Note:
    A naive algorithm of O(n2) is trivial. You MUST do better than that.

    Example:

    Input: nums = [2, 5, -1], lower = -2, upper = 2,
    Output: 3 
    Explanation: The three ranges are : [0, 0], [2, 2], [0, 2] and their respective sums are: -2, -1, 2.
    
     

    Approach #1: C++.

    class Solution {
    public:
        int countRangeSum(vector<int>& nums, int lower, int upper) {
            int len = nums.size();
            if (len == 0) return 0;
            vector<long> sum(len+1, 0);
            for (int i = 0; i < len; ++i)
                sum[i+1] += sum[i] + nums[i];
            return mergeSort(sum, lower, upper, 0, len+1);
        }
        
    private:
        int mergeSort(vector<long>& sum, int lower, int upper, int left, int right) {
            if (right - left <= 1) return 0;
            int mid = left + (right - left) / 2;
            int m = mid, n = mid, count = 0;
            count = mergeSort(sum, lower, upper, left, mid) + mergeSort(sum, lower, upper, mid, right);
            for (int i = left; i < mid; ++i) {
                while (m < right && sum[m] - sum[i] < lower) m++;
                while (n < right && sum[n] - sum[i] <= upper) n++;
                count += n - m;
            }
            inplace_merge(sum.begin()+left, sum.begin()+mid, sum.begin()+right);
            return count;
        }
    };
    

      

    Approach #2: Java.

    class Solution {
        public int countRangeSum(int[] nums, int lower, int upper) {
            if (nums == null || nums.length == 0) return 0;
            long[] sums = new long[nums.length];
            long sum = 0;
            for (int i = 0; i < nums.length; ++i) {
                sum += nums[i];
                sums[i] += sum;
            }
            return mergeSort(sums, lower, upper, 0, nums.length-1);
        }
        
        private int mergeSort(long[] sums, int lower, int upper, int left, int right) {
            if (right < left) return 0;
            else if (left == right) {
                if (sums[left] >= lower && sums[right] <= upper) return 1;
                else return 0;
            }
            int mid = left + (right - left) / 2;
            int count = mergeSort(sums, lower, upper, left, mid) + mergeSort(sums, lower, upper, mid+1, right);
            int m = mid+1, n = mid+1;
            for (int i = left; i <= mid; ++i) {
                while (m <= right && sums[m] - sums[i] < lower) m++;
                while (n <= right && sums[n] - sums[i] <= upper) n++;
                count += n - m;
            }
            mergeHelper(sums, left, mid, right);
            return count;
        }
        
        private void mergeHelper(long[] sums, int left, int mid, int right) {
            int i = left;
            int j = mid + 1;
            long[] copy = new long[right-left+1];
            int p = 0;
            while (i <= mid && j <= right) {
                if (sums[i] < sums[j]) {
                    copy[p++] = sums[i++];
                } else {
                    copy[p++] = sums[j++];
                }
            }
            
            while (i <= mid) {
                copy[p++] = sums[i++];
            }
            
            while (j <= right) {
                copy[p++] = sums[j++];
            }
            
            System.arraycopy(copy, 0, sums, left, right-left+1);
        }
    }
    

      

    Approach #3: Python.

    class Solution(object):
        def countRangeSum(self, nums, lower, upper):
            """
            :type nums: List[int]
            :type lower: int
            :type upper: int
            :rtype: int
            """
            first = [0]
            for num in nums:
                first.append(first[-1] + num)
                
            def sort(lo, hi):
                mid = (lo + hi) / 2
                if mid == lo:
                    return 0
                count = sort(lo, mid) + sort(mid, hi)
                i = j = mid
                for left in first[lo:mid]:
                    while i < hi and first[i] - left < lower: i += 1
                    while j < hi and first[j] - left <= upper: j += 1
                    count += j - i
                first[lo:hi] = sorted(first[lo:hi])
                return count
            return sort(0, len(first))
    

      

    Notes:

    C++ -----> inplace_merge

    default (1)
    template <class BidirectionalIterator>
      void inplace_merge (BidirectionalIterator first, BidirectionalIterator middle,
                          BidirectionalIterator last);
    
    custom (2)
    template <class BidirectionalIterator, class Compare>
      void inplace_merge (BidirectionalIterator first, BidirectionalIterator middle,
                          BidirectionalIterator last, Compare comp);
    Merge consecutive sorted ranges

    Merges two consecutive sorted ranges: [first,middle) and [middle,last), putting the result into the combined sorted range [first,last).

    The elements are compared using operator< for the first version, and comp for the second. The elements in both ranges shall already be ordered according to this same criterion (operator< or comp). The resulting range is also sorted according to this.

    The function preserves the relative order of elements with equivalent values, with the elements in the first range preceding those equivalent in the second.

    for example:

    // inplace_merge example
    #include <iostream>     // std::cout
    #include <algorithm>    // std::inplace_merge, std::sort, std::copy
    #include <vector>       // std::vector
    
    int main () {
      int first[] = {5,10,15,20,25};
      int second[] = {50,40,30,20,10};
      std::vector<int> v(10);
      std::vector<int>::iterator it;
    
      std::sort (first,first+5);
      std::sort (second,second+5);
    
      it=std::copy (first, first+5, v.begin());
         std::copy (second,second+5,it);
    
      std::inplace_merge (v.begin(),v.begin()+5,v.end());
    
      std::cout << "The resulting vector contains:";
      for (it=v.begin(); it!=v.end(); ++it)
        std::cout << ' ' << *it;
      std::cout << '
    ';
    
      return 0;
    }
    

      

    output:

    The resulting vector contains: 5 10 10 15 20 20 25 30 40 50
    

      

    永远渴望,大智若愚(stay hungry, stay foolish)
  • 相关阅读:
    opengl画不出直线 线段 坐标轴 却能画出其他图形的坑
    c++多个文件中共用一个全局变量 变量跨文件使用
    关于c# winform 键盘响应右边键盘消息响应事件的上下左右方向键没有反应
    关于c#winform用sharpGL(OpenGL)绘制不出图形,绘制窗口是个黑框的坑
    C# winform用sharpGL(OpenGl)解析读取3D模型obj
    关于C#界面开发winform与SharpGL结合鼠标只在OpenGLControl绘图区域显示坐标移动消息响应(c#鼠标单独在某个控件上的消息响应)
    关于MFC与OpenGL结合绘图区域用鼠标来控制图形的移动的坑
    bullet物理引擎与OpenGL结合 导入3D模型进行碰撞检测 以及画三角网格的坑
    OpenGl 导入读取多个3D模型 并且添加鼠标控制移动旋转
    OpenGl 实现鼠标分别移动多个物体图形 ----------移动一个物体另外一个物体不动--读取多个3d模型操作的前期踏脚石
  • 原文地址:https://www.cnblogs.com/h-hkai/p/10040903.html
Copyright © 2011-2022 走看看