Skip to content

Commit a08bbc5

Browse files
committed
327-629-1310-1395-1578-1653 & 面试题 17.05 (7)
1 parent 1bd2e42 commit a08bbc5

File tree

35 files changed

+1076
-320
lines changed

35 files changed

+1076
-320
lines changed

leetcode-01/src/main/java/Solution64.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ public int minPathSum(int[][] grid) {
33
int m = grid.length;
44
int n = grid[0].length;
55

6-
// f[i][j] 表示 i*j 矩阵的最小路径和
6+
// f[i][j] 表示到达 grid[i][j] 矩阵的最小路径和
77
int[][] f = new int[m][n];
8-
// 初始状态
8+
9+
// 初始状态 第一行 + 第一列
910
f[0][0] = grid[0][0];
10-
// 往下移
1111
for (int i = 1; i < m; i++) {
1212
f[i][0] = f[i - 1][0] + grid[i][0];
1313
}
14-
// 往右移
1514
for (int j = 1; j < n; j++) {
1615
f[0][j] = f[0][j - 1] + grid[0][j];
1716
}
17+
1818
// 状态转移
1919
for (int i = 1; i < m; i++) {
2020
for (int j = 1; j < n; j++) {
@@ -38,4 +38,6 @@ public int minPathSum(int[][] grid) {
3838
3939
动态规划。
4040
定义 dp[i][j] 为 i x j 矩阵中,路径上的数字总和为最小的值。
41+
相似题目: 剑指 Offer 47. 礼物的最大价值
42+
https://leetcode.cn/problems/li-wu-de-zui-da-jie-zhi-lcof/
4143
*/

leetcode-04/src/main/java/Solution307.java

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,67 @@
11
public class Solution307 {
22
static class NumArray {
3-
private final BIT bit;
3+
private final Fenwick fenwick;
44

55
public NumArray(int[] nums) {
6-
bit = new BIT(nums);
6+
fenwick = new Fenwick(nums);
77
}
88

99
public void update(int index, int val) {
10-
int add = val - bit.getsum(index, index);
11-
bit.add(index + 1, add);
10+
int add = val - fenwick.getSum(index, index);
11+
fenwick.add(index + 1, add);
1212
}
1313

1414
public int sumRange(int left, int right) {
15-
return bit.getsum(left, right);
15+
return fenwick.getSum(left, right);
1616
}
1717

18-
private static class BIT {
19-
private final int N;
18+
private static class Fenwick {
19+
private final int n;
2020
private final int[] tree;
2121

22-
// O(n) 建树
23-
public BIT(int[] nums) {
24-
this.N = nums.length;
25-
this.tree = new int[N + 1];
22+
public Fenwick(int n) {
23+
this.n = n;
24+
this.tree = new int[n + 1];
25+
}
2626

27-
for (int i = 1; i <= N; i++) {
27+
// O(n) 建树
28+
public Fenwick(int[] nums) {
29+
this.n = nums.length;
30+
this.tree = new int[n + 1];
31+
for (int i = 1; i <= n; i++) {
2832
tree[i] += nums[i - 1];
2933
int j = i + lowbit(i);
30-
if (j <= N) {
34+
if (j <= n) {
3135
tree[j] += tree[i];
3236
}
3337
}
3438
}
3539

36-
public int lowbit(int x) {
37-
return x & (-x);
40+
int lowbit(int x) {
41+
return x & -x;
3842
}
3943

4044
// nums[x] add k
41-
public void add(int x, int k) {
42-
while (x <= N) {
45+
void add(int x, int k) {
46+
while (x <= n) {
4347
tree[x] += k;
4448
x += lowbit(x);
4549
}
4650
}
4751

4852
// nums [1,x] 的和
49-
public int getsum(int x) {
53+
int getSum(int x) {
5054
int ans = 0;
51-
while (x >= 1) {
55+
while (x > 0) {
5256
ans += tree[x];
5357
x -= lowbit(x);
5458
}
5559
return ans;
5660
}
5761

5862
// nums [l,r] 的和
59-
public int getsum(int l, int r) {
60-
return getsum(r + 1) - getsum(l);
63+
int getSum(int l, int r) {
64+
return getSum(r + 1) - getSum(l);
6165
}
6266
}
6367
}

leetcode-04/src/main/java/Solution315.java

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,69 @@
1-
import java.util.LinkedList;
1+
import java.util.ArrayList;
2+
import java.util.Arrays;
3+
import java.util.Collections;
4+
import java.util.HashSet;
25
import java.util.List;
6+
import java.util.Set;
37

48
public class Solution315 {
5-
// -10^4 <= nums[i] <= 10^4
6-
private static final int OFFSET = 10001;
7-
89
public List<Integer> countSmaller(int[] nums) {
9-
int max = 0;
10-
for (int num : nums) {
11-
max = Math.max(max, num);
12-
}
10+
int n = nums.length;
11+
// 离散化
12+
int[] yArr = getDiscrete(nums);
1313

14-
int len = nums.length;
15-
LinkedList<Integer> resList = new LinkedList<>();
16-
BinaryIndexedTree bit = new BinaryIndexedTree(max + OFFSET);
17-
for (int i = len - 1; i >= 0; i--) {
18-
bit.update(nums[i] + OFFSET);
19-
// 头插法
20-
resList.offerFirst(bit.query(nums[i] - 1 + OFFSET));
14+
Fenwick fenwick = new Fenwick(yArr.length);
15+
List<Integer> resList = new ArrayList<>();
16+
for (int i = n - 1; i >= 0; i--) {
17+
int yId = getId(yArr, nums[i]);
18+
fenwick.add(yId, 1);
19+
resList.add(fenwick.getSum(yId - 1));
2120
}
21+
Collections.reverse(resList);
2222
return resList;
2323
}
2424

25-
private static class BinaryIndexedTree {
25+
private int[] getDiscrete(int[] xArr) {
26+
Set<Integer> set = new HashSet<>();
27+
for (int x : xArr) {
28+
set.add(x);
29+
}
30+
int sz = set.size();
31+
int[] yArr = new int[sz];
32+
int id = 0;
33+
for (Integer x : set) {
34+
yArr[id++] = x;
35+
}
36+
Arrays.sort(yArr);
37+
return yArr;
38+
}
39+
40+
private int getId(int[] yArr, int x) {
41+
return Arrays.binarySearch(yArr, x) + 1;
42+
}
43+
44+
private static class Fenwick {
2645
private final int n;
2746
private final int[] tree;
2847

29-
public BinaryIndexedTree(int n) {
48+
public Fenwick(int n) {
3049
this.n = n;
3150
this.tree = new int[n + 1];
3251
}
3352

34-
public static int lowbit(int x) {
35-
return x & (-x);
53+
public int lowbit(int x) {
54+
return x & -x;
3655
}
3756

38-
public void update(int x) {
57+
public void add(int x, int k) {
3958
while (x <= n) {
40-
++tree[x];
59+
tree[x] += k;
4160
x += lowbit(x);
4261
}
4362
}
4463

45-
public int query(int x) {
64+
public int getSum(int x) {
4665
int ans = 0;
47-
while (x > 0) {
66+
while (x >= 1) {
4867
ans += tree[x];
4968
x -= lowbit(x);
5069
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import java.util.HashMap;
2+
import java.util.Map;
3+
import java.util.TreeSet;
4+
5+
public class Solution327 {
6+
public int countRangeSum(int[] nums, int lower, int upper) {
7+
int n = nums.length;
8+
long[] preSum = new long[n + 1];
9+
for (int i = 0; i < n; i++) {
10+
preSum[i + 1] = preSum[i] + nums[i];
11+
}
12+
13+
// 离散化
14+
TreeSet<Long> set = new TreeSet<>();
15+
for (long x : preSum) {
16+
set.add(x);
17+
set.add(x - lower);
18+
set.add(x - upper);
19+
}
20+
Map<Long, Integer> map = new HashMap<>();
21+
int id = 0;
22+
for (Long x : set) {
23+
map.put(x, id++);
24+
}
25+
26+
int res = 0;
27+
Fenwick fenwick = new Fenwick(map.size());
28+
for (long x : preSum) {
29+
int l = map.get(x - upper);
30+
int r = map.get(x - lower);
31+
res += fenwick.getSum(r + 1) - fenwick.getSum(l);
32+
fenwick.add(map.get(x) + 1, 1);
33+
}
34+
return res;
35+
}
36+
37+
private static class Fenwick {
38+
private final int n;
39+
private final int[] tree;
40+
41+
public Fenwick(int n) {
42+
this.n = n;
43+
this.tree = new int[n + 1];
44+
}
45+
46+
int lowbit(int x) {
47+
return x & -x;
48+
}
49+
50+
void add(int x, int k) {
51+
while (x <= n) {
52+
tree[x] += k;
53+
x += lowbit(x);
54+
}
55+
}
56+
57+
int getSum(int x) {
58+
int ans = 0;
59+
while (x > 0) {
60+
ans += tree[x];
61+
x -= lowbit(x);
62+
}
63+
return ans;
64+
}
65+
}
66+
}
67+
/*
68+
327. 区间和的个数
69+
https://leetcode.cn/problems/count-of-range-sum/
70+
71+
给你一个整数数组 nums 以及两个整数 lower 和 upper 。求数组中,值位于范围 [lower, upper] (包含 lower 和 upper)之内的 区间和的个数 。
72+
区间和 S(i, j) 表示在 nums 中,位置从 i 到 j 的元素之和,包含 i 和 j (i ≤ j)。
73+
提示:
74+
1 <= nums.length <= 10^5
75+
-2^31 <= nums[i] <= 2^31 - 1
76+
-10^5 <= lower <= upper <= 10^5
77+
题目数据保证答案是一个 32 位 的整数
78+
79+
离散化树状数组
80+
时间复杂度 O(nlogn)
81+
空间复杂度 O(n)
82+
*/
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution327Tests {
5+
private final Solution327 solution327 = new Solution327();
6+
7+
@Test
8+
public void example1() {
9+
int[] nums = {-2, 5, -1};
10+
int lower = -2;
11+
int upper = 2;
12+
int expected = 3;
13+
Assertions.assertEquals(expected, solution327.countRangeSum(nums, lower, upper));
14+
}
15+
16+
@Test
17+
public void example2() {
18+
int[] nums = {0};
19+
int lower = 0;
20+
int upper = 0;
21+
int expected = 1;
22+
Assertions.assertEquals(expected, solution327.countRangeSum(nums, lower, upper));
23+
}
24+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
public class Solution629 {
2+
private static final int MOD = (int) (1e9 + 7);
3+
private static final int MAX_N = 1005;
4+
5+
public int kInversePairs(int n, int k) {
6+
// f[i][j] 表示我们使用数字 [1,i] 的排列构成长度为 i 的数组,并且恰好包含 j 个逆序对的方案数
7+
// f[i][j] = f[i][j−1] − f[i−1][j−i] + f[i−1][j]
8+
int[] f = new int[MAX_N];
9+
int[] pre = new int[MAX_N];
10+
for (int i = 1; i <= n; i++) {
11+
f[1] = 1;
12+
for (int j = 2; j <= k + 1; j++) {
13+
f[j] = (pre[j] - pre[Math.max(0, j - i)] + MOD) % MOD;
14+
}
15+
for (int j = 1; j <= k + 1; j++) {
16+
pre[j] = (pre[j - 1] + f[j]) % MOD;
17+
}
18+
}
19+
return f[k + 1];
20+
}
21+
}
22+
/*
23+
629. K个逆序对数组
24+
https://leetcode.cn/problems/k-inverse-pairs-array/
25+
26+
给出两个整数 n 和 k,找出所有包含从 1 到 n 的数字,且恰好拥有 k 个逆序对的不同的数组的个数。
27+
逆序对的定义如下:对于数组的第i个和第 j个元素,如果满i < j且 a[i] > a[j],则其为一个逆序对;否则不是。
28+
由于答案可能很大,只需要返回 答案 mod 10^9 + 7 的值。
29+
说明:
30+
1. n 的范围是 [1, 1000] 并且 k 的范围是 [0, 1000]。
31+
32+
动态规划。
33+
https://leetcode.cn/problems/k-inverse-pairs-array/solution/dong-tai-gui-hua-qian-zhui-he-you-hua-by-28eb/
34+
时间复杂度 O(nk)
35+
空间复杂度 O(k)
36+
*/
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution629Tests {
5+
private final Solution629 solution629 = new Solution629();
6+
7+
@Test
8+
public void example1() {
9+
int n = 3;
10+
int k = 0;
11+
int expected = 1;
12+
Assertions.assertEquals(expected, solution629.kInversePairs(n, k));
13+
}
14+
15+
@Test
16+
public void example2() {
17+
int n = 3;
18+
int k = 1;
19+
int expected = 2;
20+
Assertions.assertEquals(expected, solution629.kInversePairs(n, k));
21+
}
22+
}

0 commit comments

Comments
 (0)