diff --git "a/C++/LeetCodet\351\242\230\350\247\243(C++\347\211\210).pdf" "b/C++/LeetCodet\351\242\230\350\247\243(C++\347\211\210).pdf" index 84108236..68f670b3 100644 Binary files "a/C++/LeetCodet\351\242\230\350\247\243(C++\347\211\210).pdf" and "b/C++/LeetCodet\351\242\230\350\247\243(C++\347\211\210).pdf" differ diff --git a/C++/chapBruteforce.tex b/C++/chapBruteforce.tex index 094ab051..9e8e33b8 100644 --- a/C++/chapBruteforce.tex +++ b/C++/chapBruteforce.tex @@ -539,6 +539,31 @@ \subsubsection{代码} }; \end{Code} +\begin{Code} +// LeetCode, Combinations +// use prev_permutation() +class Solution { +public: + vector > combine(int n, int k) { + vector values(n); + iota(values.begin(), values.end(), 1); + + vector select(n, false); + fill_n(select.begin(), k, true); + + vector > result; + do{ + vector one(k); + for (int i = 0, index = 0; i < n; ++i) + if (select[i]) + one[index++] = values[i]; + result.push_back(one); + } while(prev_permutation(select.begin(), select.end())); + return result; + } +}; +\end{Code} + \subsubsection{相关题目} \begindot diff --git a/C++/chapLinearList.tex b/C++/chapLinearList.tex index 5db8e5e8..d7a31983 100644 --- a/C++/chapLinearList.tex +++ b/C++/chapLinearList.tex @@ -26,6 +26,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Remove Duplicates from Sorted Array +// 时间复杂度O(n),空间复杂度O(1) class Solution { public: int removeDuplicates(int A[], int n) { @@ -41,9 +42,20 @@ \subsubsection{代码} }; \end{Code} +\begin{Code} +// LeetCode, Remove Duplicates from Sorted Array +// 使用STL,时间复杂度O(n),空间复杂度O(1) +class Solution { +public: + int removeDuplicates(int A[], int n) { + return distance(A, unique(A, A + n)); + } +}; +\end{Code} \begin{Code} -// LeetCode, Remove Duplicates from Sorted Array,使用STL +// LeetCode, Remove Duplicates from Sorted Array +// 使用STL,时间复杂度O(n),空间复杂度O(1) class Solution { public: int removeDuplicates(int A[], int n) { @@ -92,6 +104,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Remove Duplicates from Sorted Array II +// 时间复杂度O(n),空间复杂度O(1) class Solution { public: int removeDuplicates(int A[], int n) { @@ -119,6 +132,7 @@ \subsubsection{代码} \begin{Code} // LeetCode, Remove Duplicates from Sorted Array II // @author 虞航仲 (http://weibo.com/u/1666779725) +// 时间复杂度O(n),空间复杂度O(1) class Solution { public: int removeDuplicates(int A[], int n) { @@ -163,6 +177,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Search in Rotated Sorted Array +// 时间复杂度O(log n),空间复杂度O(1) class Solution { public: int search(int A[], int n, int target) { @@ -220,6 +235,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Search in Rotated Sorted Array II +// 时间复杂度O(log n),空间复杂度O(1) class Solution { public: bool search(int A[], int n, int target) { @@ -296,6 +312,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Median of Two Sorted Arrays +// 时间复杂度O(log(m+n)),空间复杂度O(log(m+n)) class Solution { public: double findMedianSortedArrays(int A[], int m, int B[], int n) { @@ -358,6 +375,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // Leet Code, Longest Consecutive Sequence +// 时间复杂度O(n),空间复杂度O(n) class Solution { public: int longestConsecutive(vector const& num) { @@ -428,7 +446,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, 3Sum -// 先排序,然后二分查找 +// 先排序,然后二分查找,时间复杂度O(n^2*logn),空间复杂度O(1) class Solution { public: vector> threeSum(vector& num) { @@ -480,7 +498,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, 3Sum Closest -// 先排序,然后左右夹逼 +// 先排序,然后左右夹逼,时间复杂度O(n^3),空间复杂度O(1) class Solution { public: int threeSumClosest(vector& num, int target) { @@ -554,7 +572,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, 4Sum -// 先排序,然后二分查找,复杂度n^3*logn,会超时 +// 先排序,然后二分查找,复杂度O(n^3*logn),会超时 class Solution { public: vector> fourSum(vector& num, int target) { @@ -585,7 +603,7 @@ \subsubsection{代码} \begin{Code} // LeetCode, 4Sum -// 先缓存两个数的和,复杂度O(n^3) +// 先缓存两个数的和,时间复杂度O(n^3),空间复杂度O(n^2) class Solution { public: vector > fourSum(vector &num, int target) { @@ -643,6 +661,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Remove Element +// 时间复杂度O(n),空间复杂度O(1) class Solution { public: int removeElement(int A[], int n, int elem) { @@ -657,6 +676,17 @@ \subsubsection{代码} }; \end{Code} +\begin{Code} +// LeetCode, Remove Element +// 使用remove(),时间复杂度O(n),空间复杂度O(1) +class Solution { +public: + int removeElement(int A[], int n, int elem) { + return distance(A, remove(A, A+n, elem)); + } +}; +\end{Code} + \subsubsection{相关题目} \begindot @@ -695,6 +725,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Next Permutation +// 时间复杂度O(n),空间复杂度O(1) class Solution { public: void nextPermutation(vector &num) { @@ -813,7 +844,7 @@ \subsubsection{代码} \begin{Code} // LeetCode, Permutation Sequence -// 康托编码 +// 康托编码,时间复杂度O(n),空间复杂度O(1) class Solution { public: string getPermutation(int n, int k) { @@ -885,6 +916,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Valid Sudoku +// 时间复杂度O(n^2),空间复杂度O(1) class Solution { public: bool isValidSudoku(vector>& board) { @@ -971,7 +1003,7 @@ \subsubsection{代码} \begin{Code} // LeetCode, Trapping Rain Water -// 思路1 +// 思路1,时间复杂度O(n),空间复杂度O(n) class Solution { public: int trap(int A[], int n) { @@ -1001,7 +1033,7 @@ \subsubsection{代码} \begin{Code} // LeetCode, Trapping Rain Water -// 思路2 +// 思路2,时间复杂度O(n),空间复杂度O(1) class Solution { public: int trap(int A[], int n) { @@ -1026,6 +1058,7 @@ \subsubsection{代码} // LeetCode, Trapping Rain Water // 用一个栈辅助,小于栈顶的元素压入,大于等于栈顶就把栈里所有小于或 // 等于当前值的元素全部出栈处理掉,计算面积,最后把当前元素入栈 +// 时间复杂度O(n),空间复杂度O(n) class Solution { public: int trap(int a[], int n) { @@ -1093,7 +1126,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Trapping Rain Water -// 思路 1 +// 思路 1,时间复杂度O(n^2),空间复杂度O(1) class Solution { public: void rotate(vector>& matrix) { @@ -1112,7 +1145,7 @@ \subsubsection{代码} \begin{Code} // LeetCode, Trapping Rain Water -// 思路 2 +// 思路 2,时间复杂度O(n^2),空间复杂度O(1) class Solution { public: void rotate(vector>& matrix) { @@ -1151,6 +1184,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Plus One +// 时间复杂度O(n),空间复杂度O(1) class Solution { public: vector plusOne(vector &digits) { @@ -1173,6 +1207,31 @@ \subsubsection{代码} }; \end{Code} +\begin{Code} +// LeetCode, Plus One +// 时间复杂度O(n),空间复杂度O(1) +class Solution { +public: + vector plusOne(vector &digits) { + add(digits, 1); + return digits; + } +private: + // 0 <= digit <= 9 + void add(vector &digits, int digit) { + int carry = digit; + + for_each(digits.rbegin(), digits.rend(), [&carry](int &d){ + d += carry; + carry = d / 10; + d %= 10; + }); + + if (carry > 0) digits.insert(digits.begin(), 1); + } +}; +\end{Code} + \subsubsection{相关题目} \begindot @@ -1204,7 +1263,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Climbing Stairs -// 迭代 +// 迭代,时间复杂度O(n),空间复杂度O(1) class Solution { public: int climbStairs(int n) { @@ -1222,7 +1281,7 @@ \subsubsection{代码} \begin{Code} // LeetCode, Climbing Stairs -// 数学公式 +// 数学公式,时间复杂度O(1),空间复杂度O(1) class Solution { public: int climbStairs(int n) { @@ -1292,7 +1351,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Gray Code -// 数学公式 +// 数学公式,时间复杂度O(2^n),空间复杂度O(1) class Solution { public: vector grayCode(int n) { @@ -1318,6 +1377,7 @@ \subsubsection{代码} \begin{Code} // LeetCode, Gray Code // reflect-and-prefix method +// 时间复杂度O(2^n),空间复杂度O(1) class Solution { public: vector grayCode(int n) { @@ -1366,7 +1426,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Set Matrix Zeroes -// O(m+n)空间 +// 时间复杂度O(m*n),空间复杂度O(m+n) class Solution { public: void setZeroes(vector > &matrix) { @@ -1400,7 +1460,7 @@ \subsubsection{代码} \begin{Code} // LeetCode, Set Matrix Zeroes -// 常数空间 +// 时间复杂度O(m*n),空间复杂度O(1) class Solution { public: void setZeroes(vector > &matrix) { @@ -1472,6 +1532,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Gas Station +// 时间复杂度O(n),空间复杂度O(1) class Solution { public: int canCompleteCircuit(vector &gas, vector &cost) { @@ -1520,6 +1581,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Candy +// 时间复杂度O(n),空间复杂度O(n) class Solution { public: int candy(vector &ratings) { @@ -1573,6 +1635,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Single Number +// 时间复杂度O(n),空间复杂度O(1) class Solution { public: int singleNumber(int A[], int n) { @@ -1612,7 +1675,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Single Number II -// 方法1 +// 方法1,时间复杂度O(n),空间复杂度O(1) class Solution { public: int singleNumber(int A[], int n) { @@ -1636,7 +1699,7 @@ \subsubsection{代码} \begin{Code} // LeetCode, Single Number II -// 方法2 +// 方法2,时间复杂度O(n),空间复杂度O(1) class Solution { public: int singleNumber(int A[], int n) { @@ -1692,8 +1755,9 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} -//LeetCode, Add Two Numbers -//跟Add Binary 很类似 +// LeetCode, Add Two Numbers +// 跟Add Binary 很类似 +// 时间复杂度O(m+n),空间复杂度O(1) class Solution { public: ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) { @@ -1750,41 +1814,29 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Reverse Linked List II +// 迭代版,时间复杂度O(n),空间复杂度O(1) class Solution { public: ListNode *reverseBetween(ListNode *head, int m, int n) { - if(m >= n) return head; - ListNode dummy(0); - ListNode *h = &dummy; - h->next = head; - - int count = 0; - ListNode *p = h, *pm, *pn; - for (; p; p = p->next) { - if (count == m-1) pm = p; - if (count == n) { - pn = p; - break; + ListNode dummy(-1); + dummy.next = head; + + ListNode *prev_m, *prev = &dummy; + for (int i = 1; i <= n; ++i) { + if (i == m) prev_m = prev; + + if (i > m && i <= n) { // prev_m 和 prev 静止不动 + prev->next = head->next; + head->next = prev_m->next; + prev_m->next = head; + head = prev; } - count++; - } - p = pm; - pm = pm->next; - if (m == 1) head = pn; // 若m=1,则pn就变为首节点 - - p->next = pn; - p = pm->next; - pm->next = pn->next; - - ListNode *q = p->next; // pm->p->q - while(pm != pn) { - p->next = pm; - pm = p; - p = q; - if(q) q = q->next; + + prev = head; + head = head->next; } - return head; + return dummy.next; } }; \end{Code} @@ -1817,6 +1869,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Partition List +// 时间复杂度O(n),空间复杂度O(1) class Solution { public: ListNode* partition(ListNode* head, int x) { @@ -1875,22 +1928,46 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Remove Duplicates from Sorted List +// 递归版,时间复杂度O(n),空间复杂度O(1) +class Solution { +public: + ListNode *deleteDuplicates(ListNode *head) { + if (!head) return head; + ListNode dummy(head->val + 1); // 值只要跟head不同即可 + dummy.next = head; + + recur(&dummy, head); + return dummy.next; + } +private: + static void recur(ListNode *prev, ListNode *cur) { + if (cur == nullptr) return; + + if (prev->val == cur->val) { // 删除head + prev->next = cur->next; + delete cur; + recur(prev, prev->next); + } else { + recur(prev->next, cur->next); + } + } +}; +\end{Code} + +\begin{Code} +// LeetCode, Remove Duplicates from Sorted List +// 迭代版,时间复杂度O(n),空间复杂度O(1) class Solution { public: ListNode *deleteDuplicates(ListNode *head) { if (head == nullptr) return nullptr; - ListNode * prev = head; - ListNode *cur = head->next; - while (cur != nullptr) { + + for (ListNode *prev = head, *cur = head->next; cur; cur = cur->next) { if (prev->val == cur->val) { - ListNode* tmp = cur; - cur = cur->next; - prev->next = cur; - delete tmp; - continue; + prev->next = cur->next; + delete cur; } else { - prev = prev->next; - cur = cur->next; + prev = cur; } } return head; @@ -1927,6 +2004,32 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Remove Duplicates from Sorted List II +// 递归版,时间复杂度O(n),空间复杂度O(1) +class Solution { +public: + ListNode *deleteDuplicates(ListNode *head) { + if (!head || !head->next) return head; + + ListNode *p = head->next; + if (head->val == p->val) { + while (p && head->val == p->val) { + ListNode *tmp = p; + p = p->next; + delete tmp; + } + delete head; + return deleteDuplicates(p); + } else { + head->next = deleteDuplicates(head->next); + return head; + } + } +}; +\end{Code} + +\begin{Code} +// LeetCode, Remove Duplicates from Sorted List II +// 迭代版,时间复杂度O(n),空间复杂度O(1) class Solution { public: ListNode *deleteDuplicates(ListNode *head) { @@ -1985,6 +2088,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Remove Rotate List +// 时间复杂度O(n),空间复杂度O(1) class Solution { public: ListNode *rotateRight(ListNode *head, int k) { @@ -2042,6 +2146,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Remove Nth Node From End of List +// 时间复杂度O(n),空间复杂度O(1) class Solution { public: ListNode *removeNthFromEnd(ListNode *head, int n) { @@ -2049,9 +2154,8 @@ \subsubsection{代码} dummy.next = head; ListNode *p = &dummy, *q = &dummy; - for (int i = 0; i < n; i++) { // q先走n步 + for (int i = 0; i < n; i++) // q先走n步 q = q->next; - } while(q->next) { // 一起走 p = p->next; @@ -2093,6 +2197,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Swap Nodes in Pairs +// 时间复杂度O(n),空间复杂度O(1) class Solution { public: ListNode *swapPairs(ListNode *head) { @@ -2115,6 +2220,7 @@ \subsubsection{代码} 下面这种写法更简洁,但题目规定了不准这样做。 \begin{Code} // LeetCode, Swap Nodes in Pairs +// 时间复杂度O(n),空间复杂度O(1) class Solution { public: ListNode* swapPairs(ListNode* head) { @@ -2165,6 +2271,7 @@ \subsubsection{分析} \subsubsection{代码} \begin{Code} // LeetCode, Reverse Nodes in k-Group +// 时间复杂度O(n),空间复杂度O(1) class Solution { public: ListNode *reverseKGroup(ListNode *head, int k) { diff --git a/C++/chapSorting.tex b/C++/chapSorting.tex index bad2df53..5e62f254 100644 --- a/C++/chapSorting.tex +++ b/C++/chapSorting.tex @@ -218,7 +218,6 @@ \subsubsection{分析} \subsubsection{代码} - \begin{Code} // LeetCode, Sort Colors // Counting Sort @@ -261,18 +260,28 @@ \subsubsection{代码} \begin{Code} // LeetCode, Sort Colors -// @author 连城 (http://weibo.com/lianchengzju) -// partition +// use partition() +class Solution { +public: + void sortColors(int A[], int n) { + partition(partition(A, A + n, bind1st(equal_to(), 0)), A + n, + bind1st(equal_to(), 1)); + } +}; +\end{Code} + +\begin{Code} +// LeetCode, Sort Colors +// 重新实现 partition() class Solution { public: - void sortColors(int a[], int n) { - split(split(a, a + n, bind1st(equal_to(), 0)), a + n, + void sortColors(int A[], int n) { + partition(partition(A, A + n, bind1st(equal_to(), 0)), A + n, bind1st(equal_to(), 1)); } private: - //@return pivot 的位置 template - ForwardIterator split(ForwardIterator first, ForwardIterator last, + ForwardIterator partition(ForwardIterator first, ForwardIterator last, UnaryPredicate pred) { auto pos = first; diff --git a/C++/chapTrick.tex b/C++/chapTrick.tex index ebe716d1..c83c26ee 100644 --- a/C++/chapTrick.tex +++ b/C++/chapTrick.tex @@ -2,6 +2,10 @@ \chapter{编程技巧} 在判断两个浮点数a和b是否相等时,不要用\fn{a==b},应该判断二者之差的绝对值\fn{fabs(a-b)}是否小于某个阀值,例如\fn{1e-9}。 +判断一个整数是否是为奇数,用\fn{x \% 2 != 0},不要用\fn{x \% 2 == 1},因为x可能是负数。 + +用\fn{char}的值作为数组下标(例如,统计字符串中每个字符出现的次数),要考虑到\fn{char}可能是负数。有的人考虑到了,先强制转型为\fn{unsigned int}再用作下标,这仍然是错的。正确的做法是,先强制转型为\fn{unsigned char},再用作下标。这涉及C++整型提升的规则,就不详述了。 + 以下是关于STL使用技巧的,很多条款来自《Effective STL》这本书。 \subsubsection{vector和string优先于动态分配的数组} diff --git "a/\345\217\202\350\200\203\350\265\204\346\226\231/leetcode Single Number II - \344\275\215\350\277\220\347\256\227\345\244\204\347\220\206\346\225\260\347\273\204\344\270\255\347\232\204\346\225\260 - \344\273\243\351\207\221\346\241\245 - \345\215\232\345\256\242\345\233\255.pdf" "b/\345\217\202\350\200\203\350\265\204\346\226\231/leetcode Single Number II - \344\275\215\350\277\220\347\256\227\345\244\204\347\220\206\346\225\260\347\273\204\344\270\255\347\232\204\346\225\260 - \344\273\243\351\207\221\346\241\245 - \345\215\232\345\256\242\345\233\255.pdf" new file mode 100644 index 00000000..4e528219 Binary files /dev/null and "b/\345\217\202\350\200\203\350\265\204\346\226\231/leetcode Single Number II - \344\275\215\350\277\220\347\256\227\345\244\204\347\220\206\346\225\260\347\273\204\344\270\255\347\232\204\346\225\260 - \344\273\243\351\207\221\346\241\245 - \345\215\232\345\256\242\345\233\255.pdf" differ