Count of Smaller Numbers After Self
来源:互联网 发布:易语言源码怎么用 编辑:程序博客网 时间:2024/05/30 21:58
You are given an integer array nums and you have to return a new counts array. The counts array has the property where counts[i] is the number of smaller elements to the right of nums[i].
Example:
Given nums = [5, 2, 6, 1]
To the right of 5 there are 2 smaller elements (2 and 1).
To the right of 2 there is only 1 smaller element (1).
To the right of 6 there is 1 smaller element (1).
To the right of 1 there is 0 smaller element.
Example:
Given nums = [5, 2, 6, 1]
To the right of 5 there are 2 smaller elements (2 and 1).
To the right of 2 there is only 1 smaller element (1).
To the right of 6 there is 1 smaller element (1).
To the right of 1 there is 0 smaller element.
Return the array [2, 1, 1, 0].
tags:Divide and Conquer / Binary Indexed Tree / Segment Tree / Binary Search Tree
1)最开始想到二分搜索(binary search)。思想是,维持一个vector<int> arr,初始为空。从nums的尾部向前遍历,对于每个元素,都在arr中进行binary search,返回该元素应该插入的位置i,i就是比该元素小的元素的个数。然后将该元素插入arr中。
开始以为这样的复杂度为O(lgn!)。但是我忘了vector的insert操作不是O(1),因为每次插入都要向后移动一部分元素,所以很费时间。虽然vector在binary search 中 的访问时间为O(1)。代码如下:
<span style="font-size:18px;">class Solution { //二分搜索O(lg(n!)) 1700ms左右public: vector<int> countSmaller(vector<int>& nums) { vector<int> arr, res; int size = nums.size(), pos; for(int i = size-1; i >= 0; --i){ pos = biSearch(arr, nums[i]); cout<<pos<<" "; arr.insert(arr.begin()+pos, nums[i]); res.insert(res.begin(), pos); } return res; } int biSearch(vector<int>& arr, int n){ int s = 0, e = arr.size()-1, mid; float tmp = n - 0.5; while(s<=e){ mid = (s+e)/2; if(arr[mid]<tmp) s++;//因为是整数,不会出现相等的情况。 else e--; } return s; }};</span>2)由1)中遇到的问题,可以想到用binary search tree,因为BST的搜索和插入时间都为lgN。这样时间复杂度就变成了N*O(lgN)。下面的代码是discuss中的,写的很好,40ms,值得学习。
<span style="font-size:18px;">class Solution {//BSTpublic: struct Node { int val, smaller; //smaller统计该节点左子树中节点的个数。 Node *left, *right; Node(int value, int small) { left=right=NULL, val=value, smaller=small; } }; int insert(Node *&root, int value) {//将一个元素插入到bst中,并返回树中比该元素小的元素的个数。 if (root==NULL) return (root=new Node(value, 0)), 0; if (value < root->val){ root->smaller++; return insert(root->left, value); } else return insert(root->right, value) + root->smaller + (value>root->val ? 1 : 0); } vector<int> countSmaller(vector<int>& nums) { Node *root = NULL; deque<int> ans; //deque可以从头开始插入元素,只需O(1),而vector需要O(n) for (int i=nums.size()-1; i>=0; i--) ans.push_front(insert(root, nums[i])); return vector<int> (ans.begin(), ans.end()); }};</span>3)然后就是分治方法了。这个方法大体也想出来了。但是在merge时候,要维持一个index数组,用来保存某个数最原始的位置。代码如下,时间100ms,可能因为常数项大了点。
<span style="font-size:18px;">class Solution { //分治O(nlgn) public:vector<int> countSmaller(vector<int>& nums) {int size = nums.size();vector<int> res(size, 0);vector<int> ind(size, 0);for (int i = 0; i < size; ++i) ind[i] = i;mergeSort(nums, 0, size - 1, res, ind);return res;}void mergeSort(vector<int>& nums, int s, int e, vector<int>& res, vector<int>& ind){if (s < e){int mid = (s + e) / 2;mergeSort(nums, s, mid, res, ind);mergeSort(nums, mid + 1, e, res, ind);merge(nums, s, mid, e, res, ind);}}void merge(vector<int>& nums, int s, int mid, int e, vector<int>& res, vector<int>& ind){vector<int> l, r, ind_l, ind_r;l.push_back(INT_MAX);r.push_back(INT_MAX);for (int k = s; k <= mid; ++k){l.push_back(nums[k]);ind_l.push_back(ind[k]);r.push_back(nums[k - s + mid + 1]);ind_r.push_back(ind[k - s + mid + 1]);}int i = mid - s + 1, j = e - mid, cnt = 0;for (int k = e; k >= s; --k){if (l[i] > r[j]){cnt++;nums[k] = r[j];ind[k] = ind_r[j - 1];j--;}else{nums[k] = l[i];ind[k] = ind_l[i - 1];res[ind_l[i - 1]] += cnt;i--;}}}};</span>4)至于binary indexed tree/segment tree。有空再补上。
0 0
- leetcode Count of Smaller Numbers After Self
- leetcode Count of Smaller Numbers After Self
- [LeetCode315]Count of Smaller Numbers After Self
- leetcode Count of Smaller Numbers After Self
- Count of Smaller Numbers After Self | LeetCode
- leetcode Count of Smaller Numbers After Self
- 315Count of Smaller Numbers After Self
- LeetCode Count of Smaller Numbers After Self
- [Leetcode]Count of Smaller Numbers After Self
- leetcode - Count of Smaller Numbers After Self
- leetcode:Count of Smaller Numbers After Self
- Count of Smaller Numbers After Self
- Count of Smaller Numbers After Self
- Count of Smaller Numbers After Self
- 315. Count of Smaller Numbers After Self
- 315. Count of Smaller Numbers After Self
- 【Leetcode】Count of Smaller Numbers After Self
- 315. Count of Smaller Numbers After Self
- n个元素进栈,共有多少种出栈顺序?
- annotation-config, annotation-driven, compont-scan 区别
- 字符串的排列
- iOS 小知识-设置UISwitch的颜色
- Java的练习3
- Count of Smaller Numbers After Self
- XX-net
- python scrapy 向parse传递参数、标识
- 堆和栈的区别
- Android 网络框架 Volley 源码解析
- C/C++学习建议
- Mysql基本语句复习
- clock程序
- 围圈报数