LeetCode #327 Count of Range Sum 區間和的個數

Description:
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.

Constraints:

0 <= nums.length <= 10^4

題目描述:
給定一個整數數組 nums,返回區間和在 [lower, upper] 之間的個數,包含 lower 和 upper。
區間和 S(i, j) 表示在 nums 中,位置從 i 到 j 的元素之和,包含 i 和 j (i ≤ j)。

說明:
最直觀的算法複雜度是 O(n2) ,請在此基礎上優化你的算法。

示例 :

輸入: nums = [-2,5,-1], lower = -2, upper = 2,
輸出: 3
解釋: 3個區間分別是: [0,0], [2,2], [0,2],它們表示的和分別爲: -2, -1, 2。

思路:

  1. 排序再交叉插入原數組
    比如 [1, 2, 3], [4, 5], 插入之後就可以得到 [1, 4, 2, 5, 3]
    時間複雜度O(nlgn), 空間複雜度O(1)
  2. 利用快速排序的思想, 找到數組的中位數
    然後將數組按中位數分開, 那麼中位數左邊都比中位數小, 右邊都比中位數大
    然後將中位數兩邊的數組反向, 再依次插入就能得到擺動數組
    比如 [1, 2, 5, 5, 5, 5, 6, 7] -> [5, 5, 2, 1], [7, 6, 5, 5] -> [5, 7, 5, 6, 2, 5, 1, 5]
    時間複雜度O(nlgn), 空間複雜度O(1)

代碼:
C++:

#define a(i) nums[(((i) << 1) + 1) % (n | 1)]
class Solution 
{
public:
    void wiggleSort(vector<int>& nums) 
    {
        nth_element(nums.begin(), nums.begin() + (nums.size() >> 1), nums.end());
        int n = nums.size(), mid = nums[nums.size() >> 1], i = 0, j = 0, k = nums.size() - 1;
        while (j <= k) 
        {
            if (a(j) > mid) 
            {
                swap(a(i), a(j));
                ++i;
                ++j;
            } 
            else if (a(j) < mid) 
            {
                swap(a(j), a(k));
                --k;
            } 
            else ++j;
        }
    }
};

Java:

class Solution {
    private void swap(int[] nums, int p, int q) {
        int temp = nums[p];
        nums[p] = nums[q];
        nums[q] = temp;
    }
    
    private int getIndex(int n, int i) {
        return i <= (n - 1) / 2 ? i * 2 : (i - (n + 1) / 2) * 2 + 1;
    }
    
    private int getKth(int[] nums, int k) {
        int n = nums.length, start = 0, end = n - 1;
        while (true) {
            int pivot = nums[getIndex(n, end)], p = start, q = p;
            for (int i = start; i < end; i++)
                if (nums[getIndex(n, i)] <= pivot) {
                    swap(nums, getIndex(n, q++), getIndex(n, i));
                    if (nums[getIndex(n, q - 1)] < pivot) swap(nums, getIndex(n, p++), getIndex(n, q - 1));
                }
            swap(nums, getIndex(n, q++), getIndex(n, end));
            if (k < p - start) end = p - 1;
            else if (k < q - start) return pivot;
            else {
                k -= q - start;
                start = q;
            }
        }
    }
    
    public void wiggleSort(int[] nums) {
        int n = nums.length, mid = (n - 1) / 2;
        getKth(nums, mid);
        for (int p = 0, q = mid; p < q; p++, q--) swap(nums, getIndex(n, p), getIndex(n, q));
        for (int p = mid + 1, q = n - 1; p < q; p++, q--) swap(nums, getIndex(n, p), getIndex(n, q));
    }
}

Python:

class Solution:
    def wiggleSort(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        nums[0::2], nums[1::2] = sorted(nums)[:len(nums) - (len(nums) >> 1)][::-1], sorted(nums)[len(nums) - (len(nums) >> 1):][::-1]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章