数状数组理解:
1,为了解决什么问题
频繁查询数组前缀和+数组元素动态更新时
2,原理
本质上利用数字的二进制思想来存储前缀和
举个例子:
原数组arry[1...n]
数状数组bit_tree[1...n]
bit_tree[1] = arry[1]
bit_tree[2] = arry[1] + arry[2]
....
bit_tree[i]本质上存储sum = arry[i - lowbit(i) + 1] +... arry[i]
3,这样的好处是什么呢?
正常数组比如arry[1] += 1时,后面所有的idx都得做+1操作;用数组数组只需要更新几个节点即可,降低了时间复杂度~
来做题消化一下~
https://leetcode.cn/problems/minimum-inversion-count-in-subarrays-of-fixed-length
思路:
1,滑动窗口来计算当前当前逆序值~
2,使用树状数组来降低时间复杂度~
objectivec
typedef struct {
int* tree;
int size;
} FenwickTree;
FenwickTree* createFenwickTree(int size) {
FenwickTree* ft = (FenwickTree*)malloc(sizeof(FenwickTree));
ft->size = size + 2;
ft->tree = (int*)calloc(ft->size, sizeof(int));
return ft;
}
void update(FenwickTree* ft, int idx, int delta) {
idx++;
while (idx < ft->size) {
ft->tree[idx] += delta;
idx += idx & -idx;
}
}
int query(FenwickTree* ft, int idx) {
idx++;
int sum = 0;
while (idx > 0) {
sum += ft->tree[idx];
idx -= idx & -idx;
}
return sum;
}
int cmp(const void* a, const void* b)
{ return *(int*)a - *(int*)b; }
void process_data_qsort_Deduplicate(int* nums, int n, int* processed_index, int* qsorted_data) {
int* sorted = (int*)malloc(n * sizeof(int));
memcpy(sorted, nums, n * sizeof(int));
qsort(sorted, n, sizeof(int), cmp);
int m = 0;
for (int i = 0; i < n; i++) {
if (i == 0 || sorted[i] != sorted[i - 1]) {
qsorted_data[m++] = sorted[i];
}
}
for (int i = 0; i < n; i++) {
int left = 0, right = m - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (qsorted_data[mid] == nums[i]) {
processed_index[i] = mid;
break;
} else if (qsorted_data[mid] < nums[i]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
free(sorted);
}
long long minInversionCount(int* nums, int numsSize, int k) {
if (k == 1) return 0; // 单个元素没有逆序对
int n = numsSize;
int* processed_index = (int*)malloc(n * sizeof(int));
int* qsorted_data = (int*)malloc(n * sizeof(int));
process_data_qsort_Deduplicate(nums, n, processed_index, qsorted_data);
int* timberavos = (int*)malloc(n * sizeof(int));
memcpy(timberavos, processed_index, n * sizeof(int));
FenwickTree* ft = createFenwickTree(n);
long long current_Inversion = 0;
for (int i = 0; i < k; i++) {
int greater_count = query(ft, n - 1) - query(ft, timberavos[i]);
current_Inversion += greater_count;
update(ft, timberavos[i], 1);
}
long long min_Inversion = current_Inversion;
for (int i = k; i < n; i++) {
int left_val = timberavos[i - k];
update(ft, timberavos[i-k], -1);
int left_greater = query(ft, timberavos[i-k]-1);
current_Inversion -= left_greater;
// printf("current_Inversion00:%d %d\n", i, current_Inversion);
int right_val = timberavos[i];
update(ft, timberavos[i], 1);
int right_greater = query(ft, n - 1) - query(ft, timberavos[i]);
current_Inversion += right_greater;
// printf("current_Inversion11:%d %d\n", i, current_Inversion);
if (current_Inversion < min_Inversion) {
min_Inversion = current_Inversion;
}
}
free(processed_index);
free(qsorted_data);
free(timberavos);
free(ft->tree);
free(ft);
return min_Inversion;
}