Skip to content

Commit 7200400

Browse files
committed
新增5题,LRU Cache, Insertion Sort List, Sort List,Max Points on a Line,Evaluate Reverse Polish Notation
1 parent 6713df9 commit 7200400

File tree

5 files changed

+386
-0
lines changed

5 files changed

+386
-0
lines changed

C++/LeetCodet题解(C++版).pdf

13.3 KB
Binary file not shown.

C++/chapImplement.tex

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,108 @@ \subsubsection{代码}
11361136
\end{Code}
11371137

11381138

1139+
\subsubsection{相关题目}
1140+
\begindot
1141+
\item
1142+
\myenddot
1143+
1144+
1145+
\section{Max Points on a Line} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1146+
\label{sec:Max-Points-on-a-Line}
1147+
1148+
1149+
\subsubsection{描述}
1150+
Given $n$ points on a 2D plane, find the maximum number of points that lie on the same straight line.
1151+
1152+
1153+
\subsubsection{分析}
1154+
暴力枚举法。两点决定一条直线,$n$个点两两组合,可以得到$\dfrac{1}{2}n(n+1)$条直线,对每一条直线,判断$n$个点是否在该直线上,从而可以得到这条直线上的点的个数,选择最大的那条直线返回。复杂度$O(n^3)$
1155+
1156+
上面的暴力枚举法以“边”为中心,再看另一种暴力枚举法,以每个“点”为中心,然后遍历剩余点,找到所有的斜率,如果斜率相同,那么一定共线对每个点,用一个哈希表,key为斜率,value为该直线上的点数,计算出哈希表后,取最大值,并更新全局最大值,最后就是结果。时间复杂度$O(n^2)$,空间复杂度$O(n)$
1157+
1158+
1159+
\subsubsection{以边为中心}
1160+
\begin{Code}
1161+
// LeetCode, Max Points on a Line
1162+
// 暴力枚举法,以边为中心,时间复杂度O(n^3),空间复杂度O(1)
1163+
class Solution {
1164+
public:
1165+
int maxPoints(vector<Point> &points) {
1166+
if (points.size() < 3) return points.size();
1167+
int result = 0;
1168+
1169+
for (int i = 0; i < points.size() - 1; i++) {
1170+
for (int j = i + 1; j < points.size(); j++) {
1171+
int sign = 0;
1172+
int a, b, c;
1173+
if (points[i].x == points[j].x) sign = 1;
1174+
else {
1175+
a = points[j].x - points[i].x;
1176+
b = points[j].y - points[i].y;
1177+
c = a * points[i].y - b * points[i].x;
1178+
}
1179+
int count = 0;
1180+
for (int k = 0; k < points.size(); k++) {
1181+
if ((0 == sign && a * points[k].y == c + b * points[k].x) ||
1182+
(1 == sign&&points[k].x == points[j].x))
1183+
count++;
1184+
}
1185+
if (count > result) result = count;
1186+
}
1187+
}
1188+
return result;
1189+
}
1190+
};
1191+
\end{Code}
1192+
1193+
1194+
\subsubsection{以点为中心}
1195+
\begin{Code}
1196+
// LeetCode, Max Points on a Line
1197+
// 暴力枚举,以点为中心,时间复杂度O(n^2),空间复杂度O(n)
1198+
class Solution {
1199+
public:
1200+
int maxPoints(vector<Point> &points) {
1201+
if (points.size() < 3) return points.size();
1202+
int result = 0;
1203+
1204+
unordered_map<double, int> slope_count;
1205+
for (int i = 0; i < points.size()-1; i++) {
1206+
slope_count.clear();
1207+
int samePointNum = 0; // 与i重合的点
1208+
int point_max = 1; // 和i共线的最大点数
1209+
1210+
for (int j = i + 1; j < points.size(); j++) {
1211+
double slope; // 斜率
1212+
if (points[i].x == points[j].x) {
1213+
slope = std::numeric_limits<double>::infinity();
1214+
if (points[i].y == points[j].y) {
1215+
++ samePointNum;
1216+
continue;
1217+
}
1218+
} else {
1219+
slope = 1.0 * (points[i].y - points[j].y) /
1220+
(points[i].x - points[j].x);
1221+
}
1222+
1223+
int count = 0;
1224+
if (slope_count.find(slope) != slope_count.end())
1225+
count = ++slope_count[slope];
1226+
else {
1227+
count = 2;
1228+
slope_count[slope] = 2;
1229+
}
1230+
1231+
if (point_max < count) point_max = count;
1232+
}
1233+
result = max(result, point_max + samePointNum);
1234+
}
1235+
return result;
1236+
}
1237+
};
1238+
\end{Code}
1239+
1240+
11391241
\subsubsection{相关题目}
11401242
\begindot
11411243
\item

C++/chapLinearList.tex

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2664,3 +2664,86 @@ \subsubsection{相关题目}
26642664
\begindot
26652665
\item
26662666
\myenddot
2667+
2668+
2669+
\subsection{LRU Cache}
2670+
\label{sec:LRU-Cachet}
2671+
2672+
2673+
\subsubsection{描述}
2674+
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.
2675+
2676+
\fn{get(key)} - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
2677+
2678+
\fn{set(key, value)} - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
2679+
2680+
2681+
\subsubsection{分析}
2682+
为了使查找、插入和删除都有较高的性能,我们使用一个双向链表(\fn{std::list})和一个哈希表(\fn{std::unordered_map}),因为:
2683+
\begin{itemize}
2684+
\item{哈希表保存每个节点的地址,可以基本保证在$O(1)$时间内查找节点}
2685+
\item{双向链表插入和删除效率高,单向链表插入和删除时,还要查找节点的前驱节点}
2686+
\end{itemize}
2687+
2688+
具体实现细节:
2689+
\begin{itemize}
2690+
\item{越靠近链表头部,表示节点上次访问距离现在时间最短,尾部的节点表示最近访问最少}
2691+
\item{访问节点时,如果节点存在,把该节点交换到链表头部,同时更新hash表中该节点的地址}
2692+
\item{插入节点时,如果cache的size达到了上限capacity,则删除尾部节点,同时要在hash表中删除对应的项;新节点插入链表头部}
2693+
\end{itemize}
2694+
2695+
2696+
\subsubsection{代码}
2697+
\begin{Code}
2698+
// LeetCode, LRU Cache
2699+
// 时间复杂度O(logn),空间复杂度O(n)
2700+
class LRUCache{
2701+
private:
2702+
struct CacheNode {
2703+
int key;
2704+
int value;
2705+
CacheNode(int k, int v) :key(k), value(v){}
2706+
};
2707+
public:
2708+
LRUCache(int capacity) {
2709+
this->capacity = capacity;
2710+
}
2711+
2712+
int get(int key) {
2713+
if (cacheMap.find(key) == cacheMap.end()) return -1;
2714+
2715+
// 把当前访问的节点移到链表头部,并且更新map中该节点的地址
2716+
cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);
2717+
cacheMap[key] = cacheList.begin();
2718+
return cacheMap[key]->value;
2719+
}
2720+
2721+
void set(int key, int value) {
2722+
if (cacheMap.find(key) == cacheMap.end()) {
2723+
if (cacheList.size() == capacity) { //删除链表尾部节点(最少访问的节点)
2724+
cacheMap.erase(cacheList.back().key);
2725+
cacheList.pop_back();
2726+
}
2727+
// 插入新节点到链表头部, 并且在map中增加该节点
2728+
cacheList.push_front(CacheNode(key, value));
2729+
cacheMap[key] = cacheList.begin();
2730+
} else {
2731+
//更新节点的值,把当前访问的节点移到链表头部,并且更新map中该节点的地址
2732+
cacheMap[key]->value = value;
2733+
cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);
2734+
cacheMap[key] = cacheList.begin();
2735+
}
2736+
}
2737+
private:
2738+
list<CacheNode> cacheList;
2739+
unordered_map<int, list<CacheNode>::iterator> cacheMap;
2740+
int capacity;
2741+
};
2742+
\end{Code}
2743+
2744+
2745+
\subsubsection{相关题目}
2746+
\begindot
2747+
\item
2748+
\myenddot
2749+

C++/chapSorting.tex

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,118 @@ \subsubsection{相关题目}
140140
\myenddot
141141

142142

143+
\section{Insertion Sort List} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
144+
\label{sec:Insertion-Sort-List}
145+
146+
147+
\subsubsection{描述}
148+
Sort a linked list using insertion sort.
149+
150+
151+
\subsubsection{分析}
152+
153+
154+
155+
\subsubsection{代码}
156+
\begin{Code}
157+
// LeetCode, Insertion Sort List
158+
// 时间复杂度O(n^2),空间复杂度O(1)
159+
class Solution {
160+
public:
161+
ListNode *insertionSortList(ListNode *head) {
162+
ListNode dummy(INT_MIN);
163+
//dummy.next = head;
164+
165+
for (ListNode *cur = head; cur != nullptr;) {
166+
auto pos = findInsertPos(&dummy, cur->val);
167+
ListNode *tmp = cur->next;
168+
cur->next = pos->next;
169+
pos->next = cur;
170+
cur = tmp;
171+
}
172+
return dummy.next;
173+
}
174+
175+
ListNode* findInsertPos(ListNode *head, int x) {
176+
ListNode *pre = nullptr;
177+
for (ListNode *cur = head; cur != nullptr && cur->val <= x;
178+
pre = cur, cur = cur->next)
179+
;
180+
return pre;
181+
}
182+
};
183+
\end{Code}
184+
185+
186+
\subsubsection{相关题目}
187+
\begindot
188+
\item Sort List, 见 \S \ref{sec:Sort-List}
189+
\myenddot
190+
191+
192+
\section{Sort List} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
193+
\label{sec:Sort-List}
194+
195+
196+
\subsubsection{描述}
197+
Sort a linked list in $O(n log n)$ time using constant space complexity.
198+
199+
200+
\subsubsection{分析}
201+
常数空间且$O(nlogn)$,单链表适合用归并排序,双向链表适合用快速排序。本题可以复用 "Merge Two Sorted Lists" 的代码。
202+
203+
204+
\subsubsection{代码}
205+
\begin{Code}
206+
// LeetCode, Sort List
207+
// 归并排序,时间复杂度O(nlogn),空间复杂度O(1)
208+
class Solution {
209+
public:
210+
ListNode *sortList(ListNode *head) {
211+
if (head == NULL || head->next == NULL)return head;
212+
213+
// 快慢指针找到中间节点
214+
ListNode *fast = head, *slow = head;
215+
while (fast->next != NULL && fast->next->next != NULL) {
216+
fast = fast->next->next;
217+
slow = slow->next;
218+
}
219+
// 断开
220+
fast = slow;
221+
slow = slow->next;
222+
fast->next = NULL;
223+
224+
ListNode *l1 = sortList(head); // 前半段排序
225+
ListNode *l2 = sortList(slow); // 后半段排序
226+
return mergeTwoLists(l1, l2);
227+
}
228+
229+
// Merge Two Sorted Lists
230+
ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
231+
ListNode dummy(-1);
232+
for (ListNode* p = &dummy; l1 != nullptr || l2 != nullptr; p = p->next) {
233+
int val1 = l1 == nullptr ? INT_MAX : l1->val;
234+
int val2 = l2 == nullptr ? INT_MAX : l2->val;
235+
if (val1 <= val2) {
236+
p->next = l1;
237+
l1 = l1->next;
238+
} else {
239+
p->next = l2;
240+
l2 = l2->next;
241+
}
242+
}
243+
return dummy.next;
244+
}
245+
};
246+
\end{Code}
247+
248+
249+
\subsubsection{相关题目}
250+
\begindot
251+
\item Insertion Sort List,见 \S \ref{sec:Insertion-Sort-List}
252+
\myenddot
253+
254+
143255
\section{First Missing Positive} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
144256
\label{sec:first-missing-positive}
145257

0 commit comments

Comments
 (0)