05 2016 档案
摘要:中序遍历二叉搜索树,得到的是一个有序的结果,找出其中逆序的地方就可以了。如果逆序的地方相邻,只需把逆序的相换即可;如果不相邻,则需要找到第二个逆序对的 第二个元素再做交换。 定义两个指针p和q来指定需要交换的元素,指针pre记录当前结点的前驱结点,用来判断是否逆序。 void recoverTree
阅读全文
摘要:采用广度优先遍历,一个变量记录层数,一个变量记录方向. void traverse(TreeNode *root, vector<vector<int>> result, int level, bool left_to_right) { if (!root)return; //如果进入下一层了,则r
阅读全文
摘要:层序遍历,使用队列将每层压入,定义两个队列来区分不同的层。 vector<vector<int>> levelorderTraversal(TreeNode *root) { vector<vector<int>> result; vector<int>tmp; //通过两个queue来区分不同的层
阅读全文
摘要:后序遍历,比先序和中序都要复杂。访问一个结点前,需要先判断其右孩子是否被访问过。如果是,则可以访问该结点;否则,需要先处理右子树。 vector<int> postorderTraversal(TreeNode *root) { vector<int> result; stack<TreeNode
阅读全文
摘要:树的中序遍历。先不断压入左结点至末尾,再访问,再压入右结点。注意和先序遍历的比较 vector<int> inorderTraversal(TreeNode *root) { vector<int> result; stack<TreeNode *>s; TreeNode *p = root; wh
阅读全文
摘要:树的先序遍历。定义一个栈,先压入中间结点并访问,然后依次压入右、左结点并访问。 vector<int> preorderTraversal(TreeNode *root) { vector<int> result; stack<TreeNode *>s; TreeNode *p; p = root;
阅读全文
摘要:很简单的一道题,定义一个栈保留操作数,遇操作符则弹出运算即可。 bool isOperator(string &op) { //注意用法 return op.size() == 1 && string("+-*/").find(op) != string::npos; } int evalRPN(v
阅读全文
摘要:又是一道构思巧妙的题,暴力求解复杂度太高,通过构造一个递增栈来解决:如果当前元素小于栈顶元素,则说明栈内已经构成一个 递增栈,则分别计算以每个元素为最低值的面积;反之,则入栈。 int largestRect(vector<int> &height) { stack<int> s;//定义一个单调递
阅读全文
摘要:有一定的难度。用堆栈记录下所有左符的位置,用变量记录下孤立右符的位置。 int longestValidParentheses(const string& s) { stack<int>lefts;//将左符对应的位置保留 int last;//记录孤立的右符位置 int max_len = 0;/
阅读全文
摘要:做法很巧妙。分成左右两个对应的部分,遇到左半部分则入栈,遇到右半部分则判断对应的左半部分是否在栈顶。注意最后要判断堆栈是否为空。 bool isValid(const string& s) { string left = "([{"; string right = ")]}"; stack<char
阅读全文
摘要:扫描每个WORD的长度并记录即可。 int lengthOfLast(const char *s) { //扫描统计每个word的长度 int len = 0; while (*s) { if (*s++ != ' ')//注意不管是否满足s都要++ len++; else if (*s && *s
阅读全文
摘要:主要看//之间的内容:如果是仍是/,或者是.,则忽略;如果是..,则弹出;否则压入堆栈。最后根据堆栈的内容进行输出。 string simplifyPath(string const& path) { vector<string> dirs; for (auto i = path.begin();
阅读全文
摘要:回文构词法,将字母顺序打乱。可将字母重新排序,若它们相等,则属于同一组anagrams。 可通过hashmap来做,将排序后的字母作为key。注意后面取hashmap值时的做法。 vector<string> anagrams(vector<string> &strs) { unordered_ma
阅读全文
摘要:很有意思的一道题,不好想啊。 string getNext(string &s) { char start = s[0]; int count = 0; stringstream ss; for (int i = 0; i < s.size(); i++) { if (start == s[i])
阅读全文
摘要:这题实现起来还是挺麻烦的,就偷懒使用下库函数strtod()。第二个参数表示字符中不是数字的地方,如果后面是空格,则认为其仍是数字,否则不是。 bool isNumber(char *s) { char *endptr; strtod(s, &endptr); if (endptr == s)ret
阅读全文
摘要:在一组字符串中找到最长的子串。采用纵向匹配,遇到第一个不匹配的停止。 string longestComPrefix(vector<string> &strs) { if (strs.empty())return " "; //纵向比较 for (int idx = 0; idx < strs[0]
阅读全文
摘要:跟上题类似,主要考虑‘*’的匹配问题。如果遇到‘*’,则跳过继续匹配,如果不匹配,则s++,重新扫描。 bool isMatch2(const char *s, const char *p) { if (*p == '*') { while (*p == '*')p++; if (*p == '\0
阅读全文
摘要:正则表达式的匹配,还是挺难的。可根据下一个字符是不是*分为两种情况处理,需要考虑多种情况。 bool isMatch(const char *s, const char *p) { if (*p == '\0')return *s == '\0'; //如果下一个不是*(*可表示前一个字符的数量)
阅读全文
摘要:很经典的一道题,最长回文子串,有多种方法。 首先介绍的一种方法是从中间向两边展开。注意区分aba和abba型的回文串;如果当前最长的子串已经当于两边中最长的子串了,则无需再去判断。 //从中间向两边展开 string expandAroundCenter(string s, int c1, int
阅读全文
摘要:比较简单,细节:先将字符串翻转,注意进位。 string addBinary(string a, string b) { string result; int len = a.size() > b.size() ? a.size() : b.size(); reverse(a.begin(), a.
阅读全文
摘要:字符串转为数字,细节题。要考虑空格、正负号,当转化的数字超过最大或最小是怎么办。 int atoi(char *str) { int len = strlen(str); int sign = 1; int num = 0; int i = 0; while (str[i] == ' '&& i <
阅读全文
摘要:字符串的匹配,返回匹配开始的位置,直接用暴力方式求解。为了更快的匹配,定义一个指针表示待匹配的字符串的长度,当长度不足时,可 直接停止匹配。 char *strStr(char *haystack, char*needle) { char* p1; char* p2; char* p1_advanc
阅读全文
摘要:现在开始进入字符串系列。 判断回文串的。首尾各定义一个指针,然后相比较。难点在于如何提出非字母数字的字符。 bool isValidPalind(string s) { //转为小写,注意这个函数的用法 transform(s.begin(), s.end(), s.begin(), ::towlo
阅读全文
摘要:很实际的一道题。定义一个双向链表list,方便插入和删除;定义一个哈希表,方便查找。 具体的,哈希表存放每个结点的key和它对应的结点的地址;访问结点时,如果结点存在,则将其交换到头部,同是更新哈希表中的地址; 插入结点时,首先判断capacity是否达到了上限,如果是则在链表和哈希表中删除该结点;
阅读全文
摘要:找到中间结点,将后半部分反转接入即可。 ListNode *reoderList(ListNode* head) { if (head == nullptr || head->next == nullptr)return head; //找到中间结点的方法很巧妙 ListNode *slow = h
阅读全文
摘要:两个思路,一是用哈希表记录每个结点是还被访问过;二是定义两个快、慢指针,如果存在环的话,两个指针必定会在某位结点相遇。 bool linkListNode(ListNode *head) { ListNode *fast=head, *slow=head; while (fast && fast->
阅读全文
摘要:深拷贝一个链表,不同的是这个链表有个额外的随机指针。参考:http://blog.csdn.net/ljiabin/article/details/39054999 做法非常的巧妙,分成三步,一是新建结点,并放在旧结点之后;二是修改新结点的random指针;三是将新旧链表断开。 RandomList
阅读全文
摘要:这题有点繁琐,在更新指针时很容易出错。 ListNode *reverseKGroup(ListNode *head, int k) { if (head == nullptr || head->next == nullptr || k < 2)return head; ListNode dummy
阅读全文
摘要:不允许通过值来交换,在更新指针时需要小心。 ListNode *swapNodes(ListNode* head) { ListNode dummy(-1); dummy.next = head; for (ListNode *prev = &dummy, *cur = prev->next, *p
阅读全文
摘要:这题比较简单,方法有很多。其中一种比较有意思的做法是设置两个指针,一个先走n步,然后再一起走。一个到了末尾,另一个也就确定了要删除元素的位置。 ListNode *removeNthFromEnd(ListNode *head, int n) { ListNode dummy{-1, head};
阅读全文
摘要:这题我的第一想法是用头插法,但实际上并不好做,因为每次都需要遍历最后一个。更简单的做法是将其连成环,找到相应的位置重新设头结点和尾结点。这过 有很多细节需要注意,比如K有可能是大于链表长度的,如何重新设置K等都要注意。 ListNode *rotateList(ListNode *head, int
阅读全文
摘要:很简单的一题,需要注意的是如果某结点重复了记得将其删除。 ListNode *deleteDuplicates(ListNode *head) { if (head == nullptr) return nullptr; ListNode *prev = head; for (ListNode *c
阅读全文
摘要:思路就是定义两个链表,一个放大的,一个放小的,最后将两个连起来,注意细节问题。 ListNode *partionList(ListNode *head, int value) { ListNode left_dummy(-1); ListNode right_dummy(-1); auto lef
阅读全文
摘要:这题用需要非常细心,用头插法移动需要考虑先移动哪个,只需三个指针即可。 ListNode *reverseList(ListNode *head, int m, int n) { ListNode dummy(-1); dummy.next = head; ListNode *prev = &dum
阅读全文
摘要:这题并不难,但需要注意细节。 ListNode* addTwo(ListNode *l1, ListNode *l2) { ListNode dummy(-1); int carry = 0; ListNode *prev = &dummy; for (ListNode *pa = l1, *pb
阅读全文
摘要:看见这题我的第一反应是用哈希来做,不过更简洁的做法是用异或来处理,只要是偶数个都为0(0和任意数异或仍为数本身)。 int singleNumber(int A[], int n) { int x = 0; for (int i = 0; i < n; i++) x ^= A[i]; return
阅读全文
摘要:这题的思路很巧妙,分两遍扫描,将元素分别和左右元素相比较。 int candy(vector<int> &rattings) { int n = rattings.size(); vector<int> incrment(n); int inc = 1; //和左边比较 for (int i = 1
阅读全文
摘要:这题的思路很巧妙,用两个变量,一个变量衡量当前指针是否有效,一个衡量整个数组是否有解,需要好好体会。 int gasStation(vector<int> &gas, vector<int> &cost) { int total = 0; int j; int sum = 0; for (int i
阅读全文
摘要:设置两个布尔数组,记录行和列是否存在0。需要注意的是如何将行或列设为0. void setZeros(vector<vector<int>> &matrix) { int m = matrix.size(); int n = matrix[0].size(); vector<bool>row(m,
阅读全文
摘要:这题需要注意的是最后的进位 vector<int> plusOne(vector<int>& nums,int num) { add(nums, num); } void add(vector<int> &nums, int num) { int c = num; for (auto it = nu
阅读全文
摘要:这题需要搞清楚矩阵元素的位置关系,尤其是副对角线元素,沿着副对角线元素 void rotateImage(vector<vector<int>> &matrix) { int n = matrix.size(); //沿着副对角线翻转 for (int i = 0; i < n;i++) for (
阅读全文
摘要:这题不太好想。可以先扫描找到最高的柱子,然后分别处理两边:记录下当前的局部最高点,如果当前点小于局部最高点,加上, 反则,替换当前点为局部最高点。 int trapWater(int A[], int n) { int peak = 0; int max = 0; int water = 0; fo
阅读全文
摘要:判断行、列、九宫格内数字是否重复。 按照行、列、九宫格进行检查即可。 bool validSudoku(const vector<vector<char>>& board) { bool used[9]; for (int i = 0; i < 9; i++) { fill(used, used +
阅读全文
摘要:首先是next permutation的算法的描述和分析如下: 这题一是要知道思路,编程中注意STL的用法 void nextPermutaion(vector<int> &num) { next_permutation(num.begin(), num.end()); } private: tem
阅读全文
摘要:第一题是Two Sum 同样是用哈希表来做,需要注意的是在查打gap是要排除本身。比如target为4,有一个值为2,gap同样为2。 vector<int> twoSum(vector<int> &num, int target) { unordered_map<int, int> mapping
阅读全文
摘要:这题要仔细体会下哈希表的用法,要注意的是数组本身是无序的,因此需要向左右进行扩张。 另外这个思路可以进行聚类,把连续的标记为一类。 int longestConsecutive(const vector<int> &num) { unordered_map<int, bool> used; for
阅读全文
摘要:找两个排好序的数组的中间值,实际上可以扩展为寻找第k大的数组值。 参考下面的思路,非常的清晰: 代码: double findMedianofTwoSortArrays(int A[], int B[], int m, int n) { int total = m + n; //判断序列长度的奇偶,
阅读全文
摘要:描述 Follow up for ”Search in Rotated Sorted Array”: What if duplicates are allowed? Would this affect the run-time complexity? How and why? Write a fun
阅读全文
摘要:描述 Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). You are given a target
阅读全文
摘要:描述 Follow up for ”Remove Duplicates”: What if duplicates are allowed at most twice? For example, Given sorted array A = [1,1,1,2,2,3], Your function s
阅读全文
摘要:删除数组中的重复元素并返回新数组的个数 思路:保留不同的元素即可。
阅读全文