|
34 | 34 |
|
35 | 35 | <!-- 这里可写通用的实现逻辑 -->
|
36 | 36 |
|
| 37 | +树状数组。 |
| 38 | + |
| 39 | +树状数组,也称作“二叉索引树”(Binary Indexed Tree)或 Fenwick 树。 它可以高效地实现如下两个操作: |
| 40 | + |
| 41 | +1. **单点更新** `update(x, delta)`: 把序列 x 位置的数加上一个值 delta; |
| 42 | +1. **前缀和查询** `query(x)`:查询序列 `[1,...x]` 区间的区间和,即位置 x 的前缀和。 |
| 43 | + |
| 44 | +这两个操作的时间复杂度均为 `O(log n)`。 |
| 45 | + |
| 46 | +树状数组最基本的功能就是求比某点 x 小的点的个数(这里的比较是抽象的概念,可以是数的大小、坐标的大小、质量的大小等等)。 |
| 47 | + |
| 48 | +比如给定数组 `a[5] = {2, 5, 3, 4, 1}`,求 `b[i] = 位置 i 左边小于等于 a[i] 的数的个数`。对于此例,`b[5] = {0, 1, 1, 2, 0}`。 |
| 49 | + |
| 50 | +解决方案是直接遍历数组,每个位置先求出 `query(a[i])`,然后再修改树状数组 `update(a[i], 1)` 即可。当数的范围比较大时,需要进行离散化,即先进行去重并排序,然后对每个数字进行编号。 |
| 51 | + |
37 | 52 | <!-- tabs:start -->
|
38 | 53 |
|
39 | 54 | ### **Python3**
|
40 | 55 |
|
41 | 56 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
42 | 57 |
|
43 | 58 | ```python
|
| 59 | +class BinaryIndexedTree: |
| 60 | + def __init__(self, n): |
| 61 | + self.n = n |
| 62 | + self.c = [0] * (n + 1) |
| 63 | + |
| 64 | + @staticmethod |
| 65 | + def lowbit(x): |
| 66 | + return x & -x |
44 | 67 |
|
| 68 | + def update(self, x, delta): |
| 69 | + while x <= self.n: |
| 70 | + self.c[x] += delta |
| 71 | + x += BinaryIndexedTree.lowbit(x) |
| 72 | + |
| 73 | + def query(self, x): |
| 74 | + s = 0 |
| 75 | + while x > 0: |
| 76 | + s += self.c[x] |
| 77 | + x -= BinaryIndexedTree.lowbit(x) |
| 78 | + return s |
| 79 | + |
| 80 | + |
| 81 | +class Solution: |
| 82 | + def countSmaller(self, nums: List[int]) -> List[int]: |
| 83 | + alls = sorted(set(nums)) |
| 84 | + m = {v: i for i, v in enumerate(alls, 1)} |
| 85 | + tree = BinaryIndexedTree(len(m)) |
| 86 | + ans = [] |
| 87 | + for v in nums[::-1]: |
| 88 | + x = m[v] |
| 89 | + tree.update(x, 1) |
| 90 | + ans.append(tree.query(x - 1)) |
| 91 | + return ans[::-1] |
45 | 92 | ```
|
46 | 93 |
|
47 | 94 | ### **Java**
|
48 | 95 |
|
49 | 96 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
50 | 97 |
|
51 | 98 | ```java
|
| 99 | +class Solution { |
| 100 | + public List<Integer> countSmaller(int[] nums) { |
| 101 | + Set<Integer> s = new HashSet<>(); |
| 102 | + for (int v : nums) { |
| 103 | + s.add(v); |
| 104 | + } |
| 105 | + List<Integer> alls = new ArrayList<>(s); |
| 106 | + alls.sort(Comparator.comparingInt(a -> a)); |
| 107 | + int n = alls.size(); |
| 108 | + Map<Integer, Integer> m = new HashMap<>(n); |
| 109 | + for (int i = 0; i < n; ++i) { |
| 110 | + m.put(alls.get(i), i + 1); |
| 111 | + } |
| 112 | + BinaryIndexedTree tree = new BinaryIndexedTree(n); |
| 113 | + LinkedList<Integer> ans = new LinkedList<>(); |
| 114 | + for (int i = nums.length - 1; i >= 0; --i) { |
| 115 | + int x = m.get(nums[i]); |
| 116 | + tree.update(x, 1); |
| 117 | + ans.addFirst(tree.query(x - 1)); |
| 118 | + } |
| 119 | + return ans; |
| 120 | + } |
| 121 | +} |
| 122 | + |
| 123 | +class BinaryIndexedTree { |
| 124 | + private int n; |
| 125 | + private int[] c; |
| 126 | + |
| 127 | + public BinaryIndexedTree(int n) { |
| 128 | + this.n = n; |
| 129 | + c = new int[n + 1]; |
| 130 | + } |
| 131 | + |
| 132 | + public void update(int x, int delta) { |
| 133 | + while (x <= n) { |
| 134 | + c[x] += delta; |
| 135 | + x += lowbit(x); |
| 136 | + } |
| 137 | + } |
| 138 | + |
| 139 | + public int query(int x) { |
| 140 | + int s = 0; |
| 141 | + while (x > 0) { |
| 142 | + s += c[x]; |
| 143 | + x -= lowbit(x); |
| 144 | + } |
| 145 | + return s; |
| 146 | + } |
| 147 | + |
| 148 | + public static int lowbit(int x) { |
| 149 | + return x & -x; |
| 150 | + } |
| 151 | +} |
| 152 | +``` |
| 153 | + |
| 154 | +### **C++** |
| 155 | + |
| 156 | +```cpp |
| 157 | +class BinaryIndexedTree { |
| 158 | +public: |
| 159 | + int n; |
| 160 | + vector<int> c; |
| 161 | + |
| 162 | + BinaryIndexedTree(int _n): n(_n), c(_n + 1){} |
| 163 | + |
| 164 | + void update(int x, int delta) { |
| 165 | + while (x <= n) |
| 166 | + { |
| 167 | + c[x] += delta; |
| 168 | + x += lowbit(x); |
| 169 | + } |
| 170 | + } |
| 171 | + |
| 172 | + int query(int x) { |
| 173 | + int s = 0; |
| 174 | + while (x > 0) |
| 175 | + { |
| 176 | + s += c[x]; |
| 177 | + x -= lowbit(x); |
| 178 | + } |
| 179 | + return s; |
| 180 | + } |
| 181 | + |
| 182 | + int lowbit(int x) { |
| 183 | + return x & -x; |
| 184 | + } |
| 185 | +}; |
| 186 | + |
| 187 | +class Solution { |
| 188 | +public: |
| 189 | + vector<int> countSmaller(vector<int>& nums) { |
| 190 | + unordered_set<int> s(nums.begin(), nums.end()); |
| 191 | + vector<int> alls(s.begin(), s.end()); |
| 192 | + sort(alls.begin(), alls.end()); |
| 193 | + unordered_map<int, int> m; |
| 194 | + int n = alls.size(); |
| 195 | + for (int i = 0; i < n; ++i) m[alls[i]] = i + 1; |
| 196 | + BinaryIndexedTree* tree = new BinaryIndexedTree(n); |
| 197 | + vector<int> ans(nums.size()); |
| 198 | + for (int i = nums.size() - 1; i >= 0; --i) |
| 199 | + { |
| 200 | + int x = m[nums[i]]; |
| 201 | + tree->update(x, 1); |
| 202 | + ans[i] = tree->query(x - 1); |
| 203 | + } |
| 204 | + return ans; |
| 205 | + } |
| 206 | +}; |
| 207 | +``` |
| 208 | +
|
| 209 | +### **Go** |
| 210 | +
|
| 211 | +```go |
| 212 | +type BinaryIndexedTree struct { |
| 213 | + n int |
| 214 | + c []int |
| 215 | +} |
| 216 | +
|
| 217 | +func newBinaryIndexedTree(n int) *BinaryIndexedTree { |
| 218 | + c := make([]int, n+1) |
| 219 | + return &BinaryIndexedTree{n, c} |
| 220 | +} |
| 221 | +
|
| 222 | +func (this *BinaryIndexedTree) lowbit(x int) int { |
| 223 | + return x & -x |
| 224 | +} |
| 225 | +
|
| 226 | +func (this *BinaryIndexedTree) update(x, delta int) { |
| 227 | + for x <= this.n { |
| 228 | + this.c[x] += delta |
| 229 | + x += this.lowbit(x) |
| 230 | + } |
| 231 | +} |
| 232 | +
|
| 233 | +func (this *BinaryIndexedTree) query(x int) int { |
| 234 | + s := 0 |
| 235 | + for x > 0 { |
| 236 | + s += this.c[x] |
| 237 | + x -= this.lowbit(x) |
| 238 | + } |
| 239 | + return s |
| 240 | +} |
52 | 241 |
|
| 242 | +func countSmaller(nums []int) []int { |
| 243 | + s := make(map[int]bool) |
| 244 | + for _, v := range nums { |
| 245 | + s[v] = true |
| 246 | + } |
| 247 | + var alls []int |
| 248 | + for v := range s { |
| 249 | + alls = append(alls, v) |
| 250 | + } |
| 251 | + sort.Ints(alls) |
| 252 | + m := make(map[int]int) |
| 253 | + for i, v := range alls { |
| 254 | + m[v] = i + 1 |
| 255 | + } |
| 256 | + ans := make([]int, len(nums)) |
| 257 | + tree := newBinaryIndexedTree(len(alls)) |
| 258 | + for i := len(nums) - 1; i >= 0; i-- { |
| 259 | + x := m[nums[i]] |
| 260 | + tree.update(x, 1) |
| 261 | + ans[i] = tree.query(x - 1) |
| 262 | + } |
| 263 | + return ans |
| 264 | +} |
53 | 265 | ```
|
54 | 266 |
|
55 | 267 | ### **...**
|
|
0 commit comments