classSolution { public: vector<int> smallerNumbersThanCurrent(vector<int>& nums){ vector<int> ret; int n = nums.size(); for (int i = 0; i < n; i++) { int cnt = 0; for (int j = 0; j < n; j++) { if (nums[j] < nums[i]) { cnt++; } } ret.push_back(cnt); } return ret; } };
[sol1-Java]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution { publicint[] smallerNumbersThanCurrent(int[] nums) { intn= nums.length; int[] ret = newint[n]; for (inti=0; i < n; i++) { intcnt=0; for (intj=0; j < n; j++) { if (nums[j] < nums[i]) { cnt++; } } ret[i] = cnt; } return ret; } }
[sol1-Golang]
1 2 3 4 5 6 7 8 9 10 11 12
funcsmallerNumbersThanCurrent(nums []int) (ans []int) { for _, v := range nums { cnt := 0 for _, w := range nums { if w < v { cnt++ } } ans = append(ans, cnt) } return }
[sol1-C]
1 2 3 4 5 6 7 8 9 10 11 12 13 14
int* smallerNumbersThanCurrent(int* nums, int numsSize, int* returnSize) { int* ret = malloc(sizeof(int) * numsSize); *returnSize = numsSize; for (int i = 0; i < numsSize; i++) { int cnt = 0; for (int j = 0; j < numsSize; j++) { if (nums[j] < nums[i]) { cnt++; } } ret[i] = cnt; } return ret; }
[sol1-JavaScript]
1 2 3 4 5 6 7 8 9 10 11 12 13 14
var smallerNumbersThanCurrent = function(nums) { const n = nums.length; const ret = []; for (let i = 0; i < n; ++i) { let cnt = 0; for (let j = 0; j < n; ++j) { if (nums[j] < nums[i]) { cnt++; } } ret[i] = cnt; } return ret; };
int[] ret = newint[n]; intprev= -1; for (inti=0; i < n; i++) { if (prev == -1 || data[i][0] != data[i - 1][0]) { prev = i; } ret[data[i][1]] = prev; } return ret; } }
[sol2-Golang]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
type pair struct{ v, pos int }
funcsmallerNumbersThanCurrent(nums []int) []int { n := len(nums) data := make([]pair, n) for i, v := range nums { data[i] = pair{v, i} } sort.Slice(data, func(i, j int)bool { return data[i].v < data[j].v }) ans := make([]int, n) prev := -1 for i, d := range data { if prev == -1 || d.v != data[i-1].v { prev = i } ans[d.pos] = prev } return ans }
intcmp(constvoid* a, constvoid* b) { return ((*(int**)a)[0] - (*(int**)b)[0]); }
int* smallerNumbersThanCurrent(int* nums, int numsSize, int* returnSize) { int* data[numsSize]; for (int i = 0; i < numsSize; i++) { data[i] = malloc(sizeof(int) * 2); data[i][0] = nums[i], data[i][1] = i; } qsort(data, numsSize, sizeof(int*), cmp);
int* ret = malloc(sizeof(int) * numsSize); *returnSize = numsSize; int prev = -1; for (int i = 0; i < numsSize; i++) { if (prev == -1 || data[i][0] != data[i - 1][0]) { prev = i; } ret[data[i][1]] = prev; } return ret; }
[sol2-JavaScript]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
var smallerNumbersThanCurrent = function(nums) { const n = nums.length; const data = newArray(n).fill(0).map(v =>newArray(2).fill(0)); for (let i = 0; i < n; ++i) { data[i][0] = nums[i]; data[i][1] = i; } data.sort((a, b) => a[0] - b[0]);
const ret = newArray(n); let prev = -1; for (let i = 0; i < n; ++i) { if (prev == -1 || data[i][0] !== data[i - 1][0]) { prev = i; } ret[data[i][1]] = prev; } return ret; };
复杂度分析
时间复杂度:O(N\log N),其中 N 为数组的长度。排序需要 O(N\log N) 的时间,随后需要 O(N) 时间来遍历。
空间复杂度:O(N)。因为要额外开辟一个数组。
方法三:计数排序
注意到数组元素的值域为 [0,100],所以可以考虑建立一个频次数组 cnt ,cnt[i] 表示数字 i 出现的次数。那么对于数字 i 而言,小于它的数目就为 cnt[0…i-1] 的总和。
[sol3-C++]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution { public: vector<int> smallerNumbersThanCurrent(vector<int>& nums){ vector<int> cnt(101, 0); int n = nums.size(); for (int i = 0; i < n; i++) { cnt[nums[i]]++; } for (int i = 1; i <= 100; i++) { cnt[i] += cnt[i - 1]; } vector<int> ret; for (int i = 0; i < n; i++) { ret.push_back(nums[i] == 0 ? 0: cnt[nums[i]-1]); } return ret; } };
[sol3-Java]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution { publicint[] smallerNumbersThanCurrent(int[] nums) { int[] cnt = newint[101]; intn= nums.length; for (inti=0; i < n; i++) { cnt[nums[i]]++; } for (inti=1; i <= 100; i++) { cnt[i] += cnt[i - 1]; } int[] ret = newint[n]; for (inti=0; i < n; i++) { ret[i] = nums[i] == 0 ? 0 : cnt[nums[i] - 1]; } return ret; } }
[sol3-Golang]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
funcsmallerNumbersThanCurrent(nums []int) []int { cnt := [101]int{} for _, v := range nums { cnt[v]++ } for i := 0; i < 100; i++ { cnt[i+1] += cnt[i] } ans := make([]int, len(nums)) for i, v := range nums { if v > 0 { ans[i] = cnt[v-1] } } return ans }
[sol3-C]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
int* smallerNumbersThanCurrent(int* nums, int numsSize, int* returnSize) { int cnt[101]; memset(cnt, 0, sizeof(cnt)); for (int i = 0; i < numsSize; i++) { cnt[nums[i]]++; } for (int i = 1; i <= 100; i++) { cnt[i] += cnt[i - 1]; }
int* ret = malloc(sizeof(int) * numsSize); *returnSize = numsSize; for (int i = 0; i < numsSize; i++) { ret[i] = nums[i] == 0 ? 0 : cnt[nums[i] - 1]; } return ret; }
[sol3-JavaScript]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
var smallerNumbersThanCurrent = function(nums) { const cnt = newArray(101).fill(0); const n = nums.length; for (let i = 0; i < n; ++i) { cnt[nums[i]] += 1; } for (let i = 1; i <= 100; ++i) { cnt[i] += cnt[i - 1]; } const ret = []; for (let i = 0; i < n; ++i) { ret.push(nums[i] ? cnt[nums[i] - 1] : 0); } return ret; };
复杂度分析
时间复杂度:O(N + K),其中 K 为值域大小。需要遍历两次原数组,同时遍历一次频次数组 cnt 找出前缀和。