LeetCode 315. Count of Smaller Numbers After Self
2017-09-10 23:10
495 查看
分治算法练习
本周选择LeetCode第315题Count of Smaller Numbers After Self,难度为hard。题目描述如下:
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.
Return the array [2, 1, 1, 0].
使用分治算法进行解题。
1. 考虑对于第i个元素,所求的counts[i]的值仅与nums[i]右侧的值有关,若nums[i]右侧的值已排序,则求大于nums[i]的值的数目将变得十分容易。因此可以从排序的的角度思考解题方法。
2. 归并排序是将一个大的数组,不断拆分成小数组,对小数组进行排序,并将有序的小数组合并成大的数组。对于此题,将nums[]拆分成不断左右两子数组,最终使得子数组有序,将有序子数组合并时,将右边数组中小于左边数组的元素数目加到counts[]中,最终得到counts[]。
3. 上述解法近似于对数组进行归并排序,时间复杂度为O(nlogn),需要记录counts,nums,和排序后的index,空间复杂度为O(n)。
具体代码如下:
Solution类有3个私有变量vector分别储存传入的nums,结果的counts,和排序后元素的index。
公有函数countSmaller传入nums并返回结果counts。
divide将数组其中一段分成左右两部分,并调用sort进行合并及排序。
class Solution { public: vector<int> countSmaller(vector<int>& nums); void divide(int head, int length); void sort(int head1, int head2, int length); private: vector<int> counts; vector<int> index; vector<int> nums; };
各个函数的实现:
vector<int> countSmaller(vector<int>& nums) { this->nums = nums; for (int i = 0; i < nums.size(); i++) { index.push_back(i); counts.push_back(0); } if (nums.size() != 0) divide(0, nums.size()); return counts; } void divide(int head, int length) { if (length == 1) return; divide(head, length/2); divide(head + length/2, length-length/2); sort(head, head+length/2, length); return; } void sort(int head1, int head2, int length) { int length1 = head2-head1; int length2 = length-length1; int i = 0, j = 0; // copies of indexes int* left = new int[length1]; int* right = new int[length2]; for (int k = 0 ; k < length1; k++) { left[k] = index[head1+k]; } for (int k = 0 ; k < length2; k++) { right[k] = index[head2+k]; } // record the count of current max num of right[] int maxCount = 0; // merge sort while (i != length1 && j != length2) { if (nums[left[i]] <= nums[right[j]]) { index[i+j+head1] = left[i]; counts[left[i]] += maxCount; i++; } else { index[i+j+head1] = right[j]; maxCount += 1; j++; } } for (i; i < length1; i++) { index[i+j+head1] = left[i]; counts[left[i]] += maxCount; } for (j; j < length2; j++) { index[i+j+head1] = right[j]; } delete [] left; delete [] right; }
运行结果:
16 / 16 test cases passed.
Status: Accepted
Runtime: 33 ms
Your runtime beats 61.10 % of cpp submissions.
这说明还有更优的方法解决此问题,有待进一步探究。
相关文章推荐
- [LeetCode]315. Count of Smaller Numbers After Self
- [LeetCode]--315. Count of Smaller Numbers After Self(Binary Search Tree && Merge Sort)
- LeetCode 题解:315. Count of Smaller Numbers After Self
- [LeetCode] 315. Count of Smaller Numbers After Self (Hard)
- Leetcode 315. Count of Smaller Numbers After Self
- leetcode 315. Count of Smaller Numbers After Self
- leetcode 315. Count of Smaller Numbers After Self 两种思路(欢迎探讨更优解法)
- LeetCode 315. Count of Smaller Numbers After Self
- leetcode-315. Count of Smaller Numbers After Self
- leetcode :315. Count of Smaller Numbers After Self :归并排序应用
- Leetcode 315. Count of Smaller Numbers After Self[hard]
- 【Leetcode】315. Count of Smaller Numbers After Self
- [leetcode]315. Count of Smaller Numbers After Self
- leetcode 315. Count of Smaller Numbers After Self
- [LeetCode]315. Count of Smaller Numbers After Self
- [leetcode] 315. Count of Smaller Numbers After Self 解题报告
- 再从萌新开始-Leetcode每日题解-315. Count of Smaller Numbers After Self
- leetcode 315. Count of Smaller Numbers After Self
- LeetCode 315. Count of Smaller Numbers After Self
- [leetcode]315. Count of Smaller Numbers After Self