Skip to content

Commit e358a55

Browse files
committed
feat: 149. 直线上最多的点数
1 parent fcc4bb1 commit e358a55

6 files changed

+517
-2
lines changed

Diff for: README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@
146146
- [x] [645.错误的集合](./basic/hashmap/ext-set-mismatch.md)
147147
- [x] [面试题 04.01.节点间通路](./basic/hashmap/ext-route-between-nodes-lcci.md)
148148
- [ ] [36.有效的数独](https://leetcode-cn.com/problems/valid-sudoku)
149-
- [ ] [149.直线上最多的点数](https://leetcode-cn.com/problems/max-points-on-a-line)
149+
- [x] [149.直线上最多的点数](./basic/hashmap/ext-max-points-on-a-line.md)
150150

151151
### 双指针
152152

@@ -188,6 +188,7 @@
188188
**动态规划系列**
189189

190190
- [x] [【day-37】62.不同路径](./medium/hot/37.unique-paths.md)
191+
- [x] [673. 最长递增子序列的个数](./medium/dp/number-of-longest-increasing-subsequence.md)
191192
- [ ] [70. 爬楼梯](./)
192193
- [ ] [121. 买卖股票的最佳时机](./)
193194
- [ ] [122. 买卖股票的最佳时机 II](./)

Diff for: basic/array-stack-queue/04.decode-string.md

+39-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
https://leetcode-cn.com/problems/decode-string/
44

5-
- [394.字符串解码](#394dot字符串解码)
5+
- [394.字符串解码](#394字符串解码)
66
- [题目描述](#题目描述)
77
- [方法 1: 递归](#方法-1-递归)
88
- [思路](#思路)
@@ -104,6 +104,44 @@ var decodeString = function (s, i = 0) {
104104
};
105105
```
106106

107+
C++ Code
108+
```cpp
109+
class Solution {
110+
private:
111+
int ptr_ = 0;
112+
public:
113+
string decodeString(string s) {
114+
string decoded_str = "";
115+
string repeat_times = "";
116+
117+
int i = ptr_;
118+
while (i < s.length()) {
119+
if (isalpha(s[i])) {
120+
decoded_str += s[i];
121+
i++;
122+
} else if (isdigit(s[i])) {
123+
repeat_times += s[i];
124+
i++;
125+
} else if (s.compare(i, 1, "[") == 0) {
126+
ptr_ = i + 1;
127+
string pattern = decodeString(s);
128+
i = ptr_;
129+
130+
int times = stoi(repeat_times);
131+
for (int t = 0; t < times; t++) {
132+
decoded_str += pattern;
133+
}
134+
repeat_times = "";
135+
} else if (s.compare(i, 1, "]") == 0) {
136+
ptr_ = i + 1;
137+
return decoded_str;
138+
}
139+
}
140+
return decoded_str;
141+
}
142+
};
143+
```
144+
107145
## 方法 2: 循环 + 栈
108146

109147
可以用递归解决的问题,也可以用循环来解决。

Diff for: basic/hashmap/23.substring-with-concatenation-of-all-words.md

+35
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,39 @@ naive 的想法是,将 words 里面的单词组合成字符串,然后到 s
6767

6868
JavaScript Code
6969

70+
```js
71+
/**
72+
* @param {string} s
73+
* @param {string[]} words
74+
* @return {number[]}
75+
*/
76+
var findSubstring = function(s, words) {
77+
const wordLen = words[0].length;
78+
const substrLen = wordLen * words.length;
79+
const initialWordsMap = words.reduce((map, w) => {
80+
map[w] = (map[w] || 0) + 1;
81+
return map;
82+
}, {})
83+
const res = [];
84+
85+
for (let i = 0; i <= s.length - substrLen; i++) {
86+
const wordsMap = {...initialWordsMap};
87+
for (let j = i; j < i + substrLen; j += wordLen) {
88+
const word = s.slice(j, j + wordLen);
89+
if (!(word in wordsMap) || wordsMap[word] == 0) break;
90+
wordsMap[word]--;
91+
}
92+
if (usedUpWords(wordsMap)) res.push(i);
93+
}
94+
return res;
95+
96+
// ******************************************
97+
function usedUpWords(map) {
98+
return Object.values(map).every(n => n == 0);
99+
}
100+
};
101+
```
102+
70103
```js
71104
/**
72105
* @param {string} s
@@ -99,3 +132,5 @@ var findSubstring = function (s, words) {
99132
return res;
100133
};
101134
```
135+
136+
更多题解可以访问:[https://github.com/suukii/91-days-algorithm](https://github.com/suukii/91-days-algorithm)

Diff for: basic/hashmap/ext-max-points-on-a-line.md

+149
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# 149. 直线上最多的点数
2+
3+
https://leetcode-cn.com/problems/max-points-on-a-line/
4+
5+
## 题目描述
6+
7+
```
8+
给你一个数组 points ,其中 points[i] = [xi, yi] 表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。
9+
10+
 
11+
12+
示例 1:
13+
```
14+
![](https://assets.leetcode.com/uploads/2021/02/25/plane1.jpg)
15+
```
16+
输入:points = [[1,1],[2,2],[3,3]]
17+
输出:3
18+
示例 2:
19+
```
20+
![](https://assets.leetcode.com/uploads/2021/02/25/plane2.jpg)
21+
```
22+
输入:points = [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
23+
输出:4
24+
 
25+
26+
提示:
27+
28+
1 <= points.length <= 300
29+
points[i].length == 2
30+
-104 <= xi, yi <= 104
31+
points 中的所有点 互不相同
32+
33+
来源:力扣(LeetCode)
34+
链接:https://leetcode-cn.com/problems/max-points-on-a-line
35+
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
36+
```
37+
38+
## 方法 1:枚举
39+
40+
### 思路
41+
42+
这题其实不难,只需要知道两个朴素的数学知识:
43+
44+
- 两点确定一条直线
45+
- 用斜率方程来判断某点是否在一条直线上
46+
47+
暴力点的思路就是,枚举所有两个点的组合:
48+
49+
- 先用两个点确定一条直线
50+
- 枚举其他点,判断点是否在这条直线上
51+
52+
### 复杂度分析
53+
54+
- 时间复杂度:$O(N^3)$,枚举直线的时间是 $O(N^2)$,计算在直线上的点的时间是 $O(N)$。
55+
- 空间复杂度:$O(1)$。
56+
57+
### 代码
58+
59+
JavaScript Code
60+
61+
```js
62+
/**
63+
* @param {number[][]} points
64+
* @return {number}
65+
*/
66+
var maxPoints = function(points) {
67+
let max = 1;
68+
// 点两两组合,枚举所有组合
69+
for (let i = 0; i < points.length; i++) {
70+
for (let j = i + 1; j < points.length; j++) {
71+
// points[i] 和 points[j] 确定了一条直线
72+
// 计算在这条直线上的点
73+
const count = countPointsOnLine(points[i], points[j]);
74+
max = Math.max(max, count);
75+
}
76+
}
77+
return max;
78+
79+
// *********************************************
80+
81+
function countPointsOnLine([x1, y1], [x2, y2]) {
82+
const slopeOfLine = (y1 - y2) / (x1 - x2);
83+
let count = 2;
84+
points.forEach(([x, y]) => {
85+
if (x === x1 && y === y1) return
86+
if (x === x2 && y === y2) return
87+
// 斜率一样则说明点在线上
88+
const slope = (y1 - y) / (x1 - x);
89+
if (slope === slopeOfLine) count++
90+
})
91+
return count;
92+
}
93+
};
94+
```
95+
96+
## 方法 2: 哈希表
97+
98+
### 思路
99+
100+
枚举直线无法避免,但是计算直线上的点这一步可以优化,思路如下:
101+
102+
- 先确定一个点,计算当前点与剩余其他点的斜率
103+
- 用哈希表记录这个过程中所有出现过的斜率以及出现次数
104+
- 因为斜率一样的点就在同一条直线上,所以统计斜率出现次数就能知道该直线上有多少个点了
105+
- 难点在于斜率的记录方式,直接计算会出现精度问题,所以采取分子分母元祖的记录方式,如,`slope = y / x` 记录为字符串 `'y/x'`,记录前还需要对分式进行约分。
106+
107+
### 复杂度分析
108+
109+
- 时间复杂度:$O(N^2*logm)$,枚举直线的时间是 $O(N^2)$,计算gcd的时间是 $O(logm)$,m 是点的最大差值。
110+
- 空间复杂度:$O(N)$。
111+
112+
### 代码
113+
114+
JavaScript Code
115+
116+
```js
117+
/**
118+
* @param {number[][]} points
119+
* @return {number}
120+
*/
121+
var maxPoints = function (points) {
122+
let max = 1;
123+
for (let i = 0; i < points.length; i++) {
124+
// 先确定一个点 points[i]
125+
const map = {};
126+
for (let j = i + 1; j < points.length; j++) {
127+
// 枚举剩余的点,计算两点的斜率
128+
// 用哈希表记录所有出现过的斜率的次数
129+
const key = getSlopeKey(points[i], points[j]);
130+
map[key] = (map[key] || 0) + 1;
131+
}
132+
const count = Math.max(...Object.values(map)) + 1;
133+
max = Math.max(count, max);
134+
}
135+
return max
136+
137+
// ***********************************
138+
function getSlopeKey([x1, y1], [x2, y2]) {
139+
const [x, y] = [x1 - x2, y1 - y2];
140+
const k = gcd(x, y);
141+
return `${y / k}/${x / k}`;
142+
}
143+
function gcd(a, b) {
144+
return b != 0 ? gcd(b, a % b) : a;
145+
}
146+
};
147+
```
148+
149+
更多题解可以访问:[https://github.com/suukii/91-days-algorithm](https://github.com/suukii/91-days-algorithm)

0 commit comments

Comments
 (0)