IT评测·应用市场-qidao123.com

标题: 代码随想录-基础篇 [打印本页]

作者: 王柳    时间: 2025-3-14 01:02
标题: 代码随想录-基础篇
数组

二分法


移除元素


有序数组的平方


长度最小的子数组



链表

反转链表

头插法

  1. #include <stdlib.h>
  2. struct ListNode
  3. {
  4.     int val;
  5.     struct ListNode *next;
  6. };
  7. struct ListNode *reverseList(struct ListNode *head)
  8. {
  9.     struct ListNode *head1 = (struct ListNode *)malloc(sizeof(struct ListNode));
  10.     head1->next = NULL;
  11.     struct ListNode *p1 = head;
  12.     if (head == NULL) // 空链表
  13.         return head;
  14.     struct ListNode *p2;
  15.     while (p1)
  16.     {
  17.         // 拿到一个新元素p1   使用头插法
  18.         p2 = p1->next;
  19.         p1->next = head1->next;
  20.         head1->next = p1;
  21.         p1 = p2;
  22.     }
  23. }
复制代码
双指针法


  1. struct ListNode *reverseList(struct ListNode *head)
  2. {
  3.     if (head == NULL)
  4.         return head;
  5.     // 双指针法
  6.     struct ListNode *pre = NULL, *cur =head , *tmp;
  7.     while (cur)
  8.     {
  9.         tmp = cur->next;
  10.         cur->next = pre;
  11.         pre = cur;
  12.         cur = tmp;
  13.     }
  14.     head = pre;
  15.     return head;
  16. }
复制代码
递归法

由双指针->递归
  1. struct ListNode *reverse(struct ListNode *pre, struct ListNode *cur)
  2. {
  3.     if (cur == NULL)
  4.         return pre;
  5.     struct ListNode *tmp = cur->next;
  6.     cur->next = pre;
  7.     return reverse(cur, tmp); // 这里为什么return
  8. }
  9. struct ListNode *reverseList(struct ListNode *head)
  10. {
  11.     return reverse(NULL, head);
  12. }
复制代码
两两交换链表中的结点


双指针法

直接交换数值(测试可以通过,但是交换的是值,应该交换物理节点)
  1. #include <stdio.h>
  2. struct ListNode *swapPairs(struct ListNode *head)
  3. {
  4.     // 遇到空结点
  5.     if (!head)
  6.         return head;
  7.     // 遇到只有一个结点
  8.     if (!head->next)
  9.         return head;
  10.     // 双指针法
  11.     struct ListNode *pre = head, *cur = head->next;
  12.     int tmp;
  13.     while (cur != NULL)
  14.     {
  15.         // 交换两个头结点的值
  16.         tmp = pre->val;
  17.         pre->val = cur->val;
  18.         cur->val = tmp;
  19.         // 两个指针向后移动
  20.         pre = cur->next;
  21.         if (pre)
  22.             cur = pre->next;
  23.         else
  24.             cur = NULL;
  25.     }
  26.     return head;
  27. }
复制代码
真正交换物理节点:
必要仔细考虑,两两交换之后,这前后两个组合如何保存的题目

  1. #include <stdio.h>
  2. // #include <stdlib.h>
  3. struct ListNode *swapPairs(struct ListNode *head)
  4. {
  5.     // 遇到空结点
  6.     if (!head)
  7.         return head;
  8.     // 遇到只有一个结点
  9.     if (!head->next)
  10.         return head;
  11.     // 双指针法
  12.     struct ListNode *pre = head, *cur = head->next, *tmp;
  13.     int flag = 0;
  14.     head = head->next; // head指向第二个节点
  15.     struct ListNode *p1 = NULL;
  16.     while (cur != NULL)
  17.     {
  18.         // 交换两个头结点的值
  19.         tmp = cur->next;
  20.         cur->next = pre;
  21.         pre->next = tmp;
  22.         // 两个指针向后移动
  23.         if (p1 != NULL)
  24.         {
  25.             p1->next = cur;
  26.             p1 = pre;
  27.         }
  28.         else
  29.         {
  30.             p1 = pre;
  31.         }
  32.         pre = pre->next;
  33.         if (pre)
  34.             cur = pre->next;
  35.         else
  36.             cur = NULL;
  37.     }
  38.     return head;
  39. }
复制代码
通过引入头结点

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. typedef struct ListNode LL;
  4. struct ListNode *swapPairs(struct ListNode *head)
  5. {
  6.     // 遇到空结点
  7.     if (!head)
  8.         return head;
  9.     // 遇到只有一个结点
  10.     if (!head->next)
  11.         return head;
  12.     // 双指针法
  13.     struct ListNode *pre = head, *cur = head->next, *dumpHead = (struct ListNode *)malloc(sizeof(LL));
  14.     dumpHead->next = head;
  15.     struct ListNode *p1 = dumpHead, *tmp = NULL;
  16.     while (cur != NULL)
  17.     {
  18.         p1->next = cur;
  19.         tmp = cur->next;
  20.         cur->next = pre;
  21.         pre->next = tmp;
  22.         p1 = pre;
  23.         pre = pre->next;
  24.         if (pre)
  25.             cur = pre->next;
  26.         else
  27.             cur = NULL;
  28.     }
  29.     head = dumpHead->next;
  30.     free(dumpHead);
  31.     return head;
  32. }
复制代码
删除第n个元素


快慢指针


判断链表中是否有环而且环的位置


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. struct ListNode
  4. {
  5.     int val;
  6.     struct ListNode *next;
  7. };
  8. bool hasCycle(struct ListNode *head)
  9. {
  10.     struct ListNode *fast = head;   // 每次走两步
  11.     struct ListNode *slow = head;   // 每次走一步
  12.     while (fast != NULL && fast->next != NULL)
  13.     {
  14.         fast = fast->next->next;
  15.         slow = slow->next;
  16.         if (fast == slow)
  17.         {
  18.             // 此时说明链表中有环
  19.             struct ListNode *index1 = fast;
  20.             struct ListNode *index2 = slow;
  21.             while (index1 != index2)
  22.             {
  23.                 index1 = index1->next;
  24.                 index2 = index2->next;
  25.             }
  26.             return index1; // 返回环开始的位置
  27.         }
  28.     }
  29.     return false;
  30. }
复制代码
哈希表

哈希题目的三个结构

想到哈希解法的条件反射

有效的字母异位词



两个数组的交集



两数之和



哈希法

将已经遍历的元素全部存入unordered_multimap中,每遍历一个元素,就查找target-元素是否存在于已经遍历的元素中。如存在则返回
  1. #include<iostream>
  2. #include<vector>
  3. #include <unordered_map>
  4. using namespace std;
  5. /*
  6.     1. 三个map之间的区别
  7.     2. map类的find的原理
  8.     3. map类的迭代器
  9.     4. map类的插入方法
  10. */
  11. class Solution {
  12. public:
  13.     vector<int> twoSum(vector<int>& nums, int target) {
  14.         /*
  15.         key:元素
  16.         value: 下标
  17.             遍历每个元素并存入map中,以元素值作为key,以下标作为value
  18.             然后在遍历的同时看map中的key是否存在target-当前元素
  19.         */
  20.         unordered_multimap<int, int> res;
  21.         unordered_multimap<int, int>::iterator it;
  22.         vector<int> result;
  23.         for (int i = 0; i < nums.size();i++)
  24.         {
  25.             // unordered_multimap的find方法,是根据key查找的,如果找不到就返回end()
  26.             if((it=res.find(target-nums[i]))!=res.end()) // 已经遍历的元素中存在target-nums[i]
  27.             {
  28.                 result.push_back(it->second); // map类型的迭代器的方法  key:first()   value:second()
  29.                 result.push_back(i);
  30.                 break;
  31.             }
  32.             res.insert({nums[i], i});  // unordered_multimap没有下标操作。  需要{}
  33.         }
  34.         return result;
  35.     }
  36. };
复制代码
四数相加

暴力解法



哈希解法


三数之和


暴力解法

  1. #include<iostream>
  2. #include<vector>
  3. #include<algorithm>
  4. #include<set>
  5. using namespace std;
  6. class Solution {
  7. public:
  8.     vector<vector<int>> threeSum(vector<int>& nums) {
  9.         multiset<multiset<int>> res;
  10.         for (int i = 0; i < nums.size();i++)
  11.             for (int j = 0; j < nums.size();j++)
  12.                 for (int k = 0; k < nums.size();k++)
  13.                 {
  14.                     multiset<int> tmp{};
  15.                      tmp.insert(nums[i]);
  16.                      tmp.insert(nums[j]);
  17.                      tmp.insert(nums[k]);
  18.                      if(nums[i]+nums[j]+nums[k]==0 && i!=j&&i!=k&&j!=k&&find(res.begin(),res.end(),tmp)==res.end())
  19.                         res.insert(tmp);
  20.                     
  21.                 }
  22.                 vector<vector<int>> ve;
  23.                 for (const auto& innerSet : res) {  
  24.                     std::vector<int> tempVec(innerSet.begin(), innerSet.end());  
  25.                     ve.push_back(tempVec);  
  26.                 }
  27.         
  28.         return ve;
  29.     }
  30. };
复制代码
哈希法

可以排序的原因是,只必要返回元素值即可,不消返回下标
  1. class Solution {
  2. public:
  3.     vector<vector<int>> threeSum(vector<int>& nums) {
  4.         vector<vector<int>> result;
  5.         sort(nums.begin(), nums.end());
  6.         // 找出a + b + c = 0
  7.         // a = nums[i], b = nums[j], c = -(a + b)
  8.         for (int i = 0; i < nums.size(); i++) {
  9.             // 排序之后如果第一个元素已经大于零,那么不可能凑成三元组
  10.             if (nums[i] > 0) {
  11.                 break;
  12.             }
  13.             if (i > 0 && nums[i] == nums[i - 1]) { //三元组元素a去重
  14.                 continue;
  15.             }
  16.             unordered_set<int> set;
  17.             for (int j = i + 1; j < nums.size(); j++) {
  18.                 if (j > i + 2
  19.                         && nums[j] == nums[j-1]
  20.                         && nums[j-1] == nums[j-2]) { // 三元组元素b去重
  21.                     continue;
  22.                 }
  23.                 int c = 0 - (nums[i] + nums[j]);
  24.                 if (set.find(c) != set.end()) {
  25.                     result.push_back({nums[i], nums[j], c});
  26.                     set.erase(c);// 三元组元素c去重
  27.                 } else {
  28.                     set.insert(nums[j]);
  29.                 }
  30.             }
  31.         }
  32.         return result;
  33.     }
  34. };
复制代码
双指针法

  1. class Solution {
  2. public:
  3.     vector<vector<int>> threeSum(vector<int>& nums) {
  4.         vector<vector<int>> result;
  5.         sort(nums.begin(), nums.end());
  6.         // 找出a + b + c = 0
  7.         // a = nums[i], b = nums[left], c = nums[right]
  8.         for (int i = 0; i < nums.size(); i++) {
  9.             // 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了
  10.             if (nums[i] > 0) {
  11.                 return result;
  12.             }
  13.             // 错误去重a方法,将会漏掉-1,-1,2 这种情况
  14.             /*
  15.             if (nums[i] == nums[i + 1]) {
  16.                 continue;
  17.             }
  18.             */
  19.             // 正确去重a方法
  20.             if (i > 0 && nums[i] == nums[i - 1]) {
  21.                 continue;
  22.             }
  23.             int left = i + 1;
  24.             int right = nums.size() - 1;
  25.             while (right > left) {
  26.                 // 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right<=left 了,从而漏掉了 0,0,0 这种三元组
  27.                 /*
  28.                 while (right > left && nums[right] == nums[right - 1]) right--;
  29.                 while (right > left && nums[left] == nums[left + 1]) left++;
  30.                 */
  31.                 if (nums[i] + nums[left] + nums[right] > 0) right--; // 和有点大
  32.                 else if (nums[i] + nums[left] + nums[right] < 0) left++;// 和有点小
  33.                 else {
  34.                     result.push_back(vector<int>{nums[i], nums[left], nums[right]});
  35.                     // 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
  36.                     while (right > left && nums[right] == nums[right - 1]) right--;
  37.                     while (right > left && nums[left] == nums[left + 1]) left++;
  38.                     // 找到答案时,双指针同时收缩
  39.                     right--;
  40.                     left++;
  41.                 }
  42.             }
  43.         }
  44.         return result;
  45.     }
  46. };
复制代码
四数之和

暴力法

  1. #include<iostream>
  2. #include<vector>
  3. #include<algorithm>
  4. #include<set>
  5. using namespace std;
  6. class Solution {
  7. public:
  8.     vector<vector<int>> fourSum(vector<int>& nums, int target)  {
  9.         multiset<multiset<int>> res;
  10.         for (int i = 0; i < nums.size();i++)
  11.             for (int j = 0; j < nums.size();j++)
  12.                 for (int k = 0; k < nums.size();k++)
  13.                     for (int v = 0; v < nums.size();v++)
  14.                     {
  15.                         multiset<int> tmp{};
  16.                         tmp.insert(nums[i]);
  17.                         tmp.insert(nums[j]);
  18.                         tmp.insert(nums[k]);
  19.                         tmp.insert(nums[v]);
  20.                         if(nums[i]+nums[j]+nums[k]+nums[v]==target&&i!=j&&i!=k&&j!=k&&k!=v &&j!=v&&i!=v&&find(res.begin(),res.end(),tmp)==res.end())
  21.                             res.insert(tmp);
  22.                         }   
  23.         vector<vector<int>> ve;
  24.         for (const auto& innerSet : res) {  
  25.             std::vector<int> tempVec(innerSet.begin(), innerSet.end());  
  26.             ve.push_back(tempVec);  
  27.         }
  28.         return ve;
  29.     }
  30. };
复制代码
哈希法


字符串


反转字符串1

双指针法

  1. #include<vector>
  2. #include<iostream>
  3. using namespace std;
  4. #include<algorithm>
  5. class Solution {
  6. public:
  7.     void reverseString(vector<char>& s) {
  8.         vector<char>::iterator t1 = s.begin();
  9.         vector<char>::iterator t2 = s.end()-1;
  10.         
  11.         while(t1!=t2)
  12.         {
  13.             char tmp;
  14.             tmp = *t1;
  15.             *t1 = *t2;
  16.             *t2 = tmp;
  17.             t1++;
  18.             t2--;
  19.         }
  20.     }
  21. };
复制代码

不知道上面这道题有题目,本地测试没题目,在Leecode测试报错

  1. class Solution {
  2. public:
  3.     void reverseString(vector<char>& s) {
  4.         int begin = 0, end = s.size() - 1;
  5.         while(begin<end)
  6.         {
  7.             char tmp = s[begin];
  8.             s[begin] = s[end];
  9.             s[end] = tmp;
  10.             begin++;
  11.             end--;
  12.         }
  13.     }
  14. };
复制代码
反转字符串2


思路:i += 2*k;
  1. #include<iostream>
  2. #include<string>
  3. using namespace std;
  4. class Solution {
  5. public:
  6.     void reverseBetween(string &s,int left,int right)
  7.     {
  8.         while(left<right)
  9.         {
  10.             int tmp = s[left];
  11.             s[left] = s[right];
  12.             s[right] = tmp;
  13.             right--;
  14.             left++;
  15.         }
  16.     }
  17.     string reverseStr(string s, int k) {
  18.         int i = 0;
  19.         while(i<s.size())
  20.         {
  21.             reverseBetween(s, i, i + k - 1);
  22.             i += 2*k;
  23.             if(s.size()-i < k) //如果剩余字符少于 k 个,则将剩余字符全部反转。
  24.             {
  25.                 reverseBetween(s, i, s.size() - 1);
  26.                 break;
  27.             }
  28.             else if(s.size()-i>=k && s.size()-i <2*k) // 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
  29.             {
  30.                 reverseBetween(s, i, i+k-1);
  31.                 break;
  32.             }
  33.         }
  34.         return s;
  35.     }
  36. };
复制代码
反转字符串中的单词



KMP

BP算法

  1. #include<iostream>
  2. using namespace std;
  3. int BP(char str[], char pattern[])
  4. {
  5.         int i = 0, j = 0,tmp=0;
  6.         for (; str[i] != '\0'; i++)
  7.         {
  8.                 tmp = i;
  9.                 for (j=0; pattern[j]!='\0' &&str[i] != '\0'; j++)
  10.                 {
  11.                         if (pattern[j] != str[i])
  12.                         {
  13.                                 i = tmp;
  14.                                 break;
  15.                         }
  16.                         else if (pattern[j+1] == '\0')
  17.                         {
  18.                                 return i-j;
  19.                         }
  20.                         i++;
  21.                 }
  22.         }
  23.         return -1;
  24. }
  25. int main()
  26. {
  27.         char str[] = "123456", pattern[] = "34";
  28.         int pos = BP(str,pattern);
  29.         return 0;
  30. }
复制代码
KMP


只直到一个即可

  1. #include <stdio.h>
  2. #include <string.h>
  3. // 构建next数组
  4. void getNext(char *pattern, int *next)
  5. {
  6.     int lenStr = strlen(pattern);
  7.     int j = -1, i = 0;
  8.     next[0] = -1;
  9.     while (i < lenStr)
  10.     {
  11.         if (j == -1 || pattern[i] == pattern[j])
  12.         {
  13.             i++;
  14.             j++;
  15.             next[i] = j;
  16.         }
  17.         else
  18.         {
  19.             j = next[j];
  20.         }
  21.     }
  22. }
  23. // 使用KMP算法进行字符串匹配
  24. int kmpMatch(char *text, char *pattern)
  25. {
  26.     int textLength = strlen(text);
  27.     int patternLength = strlen(pattern);
  28.     int next[patternLength];
  29.     getNext(pattern, next);
  30.     int i = 0, j = 0;
  31.     while (i < textLength && j < patternLength)
  32.     {
  33.         if (j == -1 || text[i] == pattern[j])
  34.         {
  35.             i++;
  36.             j++;
  37.             // if (j == patternLength)
  38.             // {
  39.             //     printf("position  %d find\n", i - j);
  40.             //     j = next[j];
  41.             // }
  42.         }
  43.         else
  44.         {
  45.             j = next[j];
  46.         }
  47.     }
  48.     if (j == patternLength)
  49.         return i - j;
  50.     else
  51.         return -1;
  52. }
  53. int main()
  54. {
  55.     char text[] = "ABABDABACDABABCABAB";
  56.     char pattern[] = "ABABCABAB";      // -1
  57.     int pos = kmpMatch(text, pattern); // 使用KMP算法进行字符串匹配
  58.     printf("%d\n", pos);
  59.     return 0;
  60. }
复制代码
找到全部匹配的字串的位置

  1. // 构建next数组
  2. void getNext(char *pattern, int *next)
  3. {
  4.     int lenStr = strlen(pattern);
  5.     int j = -1, i = 0;
  6.     next[0] = -1;
  7.     while (i < lenStr)
  8.     {
  9.         if (j == -1 || pattern[i] == pattern[j])
  10.         {
  11.             i++;
  12.             j++;
  13.             next[i] = j;
  14.         }
  15.         else
  16.         {
  17.             j = next[j];
  18.         }
  19.     }
  20. }
  21. // 使用KMP算法进行字符串匹配
  22. int kmpMatch(char *text, char *pattern, int *allSonStr)
  23. {
  24.     int textLength = strlen(text);
  25.     int patternLength = strlen(pattern);
  26.     int next[patternLength];
  27.     getNext(pattern, next);
  28.     int k = 0;
  29.     int i = 0, j = 0;
  30.     while (i < textLength && j < patternLength)
  31.     {
  32.         if (j == -1 || text[i] == pattern[j])
  33.         {
  34.             i++;
  35.             j++;
  36.             if (j == patternLength)
  37.             {
  38.                 allSonStr[k++] = i - j;
  39.                 j = next[j];
  40.             }
  41.         }
  42.         else
  43.         {
  44.             j = next[j];
  45.         }
  46.     }
  47.     if (k != 0)
  48.         return k;
  49.     else
  50.         return 0;
  51. }
复制代码
重复的子字符串


暴力法

  1. ```cpp
  2. class Solution {
  3. public:
  4.         string repeadString(string s, int count)
  5.         {
  6.                 string tmp(s);
  7.                 for (int i = 0; i < count-1; i++)
  8.                         s.append(tmp);
  9.                 return s;
  10.         }
  11.         bool repeatedSubstringPattern(string s) {
  12.                 string res;
  13.                 for (int i = 0; i < s.size(); i++)
  14.                 {
  15.                         string tmp(s, 0, i+1);
  16.                         if (s.size() / tmp.size() > 1)
  17.                         {
  18.                                 res = repeadString(tmp, s.size() / tmp.size());
  19.                                 if (s == res)
  20.                                         return true;
  21.                         }
  22.                        
  23.                 }
  24.                 return false;
  25.         }
  26. };
  27. ```
复制代码
移动匹配

   思路:

  1. class Solution {
  2. public:
  3.     bool repeatedSubstringPattern(string s) {
  4.         string tmp(s);
  5.         s += s;
  6.         s.erase(s.begin());
  7.         s.erase(s.end()-1);
  8.         if (s.find(tmp) != std::string::npos)
  9.             return true;
  10.         return false;
  11.     }
  12. };
复制代码
栈与队列

用栈实现队列


  1. #include<iostream>
  2. #include<stack>
  3. using namespace std;
  4. /*
  5. 两个栈实现一个队列的算法: in,out
  6.     进队时: 将out中的都出栈,并入栈到in中,然后将入栈元素入栈到in中
  7.     出队时: 将in中的都出栈,并入栈到out中,然后将out中元素出栈
  8. */
  9. class MyQueue {
  10. public:
  11.     MyQueue() {
  12.     }
  13.     void push(int x) {   //进入队列
  14.         while (!out.empty())  // 首先将out的
  15.         {
  16.             in.push(out.top());
  17.             out.pop();
  18.         }
  19.         in.push(x);
  20.     }
  21.     int pop() {// 出队
  22.         while (!in.empty())
  23.         {
  24.             out.push(in.top());
  25.             in.pop();
  26.         }
  27.         int tmp = out.top();
  28.         out.pop();
  29.         return tmp;
  30.     }
  31.     int peek() {
  32.         while (!in.empty())
  33.         {
  34.             out.push(in.top());
  35.             in.pop();
  36.         }
  37.         return out.top();
  38.     }
  39.     bool empty() {
  40.         return in.empty() && out.empty();
  41.     }
  42. private:
  43.     stack<int> in;
  44.     stack<int> out;
  45. };
  46. /**
  47. * Your MyQueue object will be instantiated and called as such:
  48. * MyQueue* obj = new MyQueue();
  49. * obj->push(x);
  50. * int param_2 = obj->pop();
  51. * int param_3 = obj->peek();
  52. * bool param_4 = obj->empty();
  53. */
复制代码
用队列实现栈



  1. #include<iostream>
  2. #include<queue>
  3. using namespace std;
  4. /*
  5.     实现思路:只用一个队列实现栈
  6.         出栈:处队size-1个并将这size-1个元素入队
  7.         进栈:直接入队即可
  8. */
  9. class MyStack {
  10. public:
  11.     MyStack() {
  12.     }
  13.     void push(int x) {
  14.         q.push(x);
  15.     }
  16.     int pop() {
  17.         int size = q.size() - 1;
  18.         while (size > 0)
  19.         {
  20.             q.push(q.front());
  21.             q.pop();
  22.             size--;
  23.         }
  24.         int tmp = q.front();
  25.         q.pop();
  26.         return tmp;
  27.     }
  28.     int top() {
  29.         int size = q.size() - 1;
  30.         while (size > 0)
  31.         {
  32.             q.push(q.front());
  33.             q.pop();
  34.             size--;
  35.         }
  36.         int tmp = q.front();
  37.         q.push(q.front());
  38.         q.pop();
  39.         return tmp;
  40.     }
  41.     bool empty() {
  42.         return q.empty();
  43.     }
  44. private:
  45.     queue<int> q;
  46. };
  47. /**
  48. * Your MyStack object will be instantiated and called as such:
  49. * MyStack* obj = new MyStack();
  50. * obj->push(x);
  51. * int param_2 = obj->pop();
  52. * int param_3 = obj->top();
  53. * bool param_4 = obj->empty();
  54. */
复制代码
有效的括号


  1. #include<iostream>
  2. #include<stack>
  3. using namespace std;
  4. class Solution {
  5. public:
  6.     bool isValid(string s) {
  7.         stack<char> sa;
  8.         for (char ch : s)
  9.         {
  10.             if (ch == '[' || ch == '{' || ch == '(')
  11.                 sa.push(ch);
  12.             else if (ch == ']' )
  13.             {
  14.                 char tmp = sa.top();
  15.                 sa.pop();
  16.                 if (tmp != '[')
  17.                     return false;
  18.             }
  19.             else if ( ch == '}' )
  20.             {
  21.                 char tmp = sa.top();
  22.                 sa.pop();
  23.                 if (tmp != '{')
  24.                     return false;
  25.             }
  26.             else if ( ch == ')')
  27.             {
  28.                 char tmp = sa.top();
  29.                 sa.pop();
  30.                 if (tmp != '(')
  31.                     return false;
  32.             }
  33.         }
  34.         return true;
  35.     }
  36. };
复制代码
删除字符串中的全部相邻重复项


暴力匹配

  1. class Solution {
  2. public:
  3.     string removeDuplicates(string s) {
  4.         for (int i = 0; i < s.size()-1; i++)
  5.         {
  6.             if (s[i] == s[i + 1])
  7.             {
  8.                 s.erase(i, 2);
  9.                 i = -1;
  10.             }
  11.         }
  12.         return s;
  13.     }
  14. };
复制代码
使用栈


  1. #include<iostream>
  2. #include<stack>
  3. using namespace std;
  4. class Solution {
  5. public:
  6.     string removeDuplicates(string s) {
  7.         stack<char> sa;
  8.         for (char ch : s)
  9.         {
  10.             if (sa.empty() || sa.top() != ch)  // 栈为空或者顶部元素与ch不相等
  11.                 sa.push(ch);
  12.             else if(sa.top() == ch)
  13.                 sa.pop();
  14.         }
  15.         string res = "";
  16.         while (!sa.empty())
  17.         {
  18.             res.insert(res.begin(), sa.top());
  19.             sa.pop();
  20.         }
  21.         return res;
  22.     }
  23. };
复制代码
逆波兰式表达式求值


  1. #include<iostream>
  2. #include<stack>
  3. #include<vector>
  4. #include<string>
  5. using namespace std;
  6. class Solution {
  7. public:
  8.     int evalRPN(vector<string>& tokens) {
  9.         stack<string> sa;
  10.         int result = 0;
  11.         int num1 = 0, num2 = 0;
  12.         /*
  13.            思路分析: 依次扫描字符串,
  14.                 只要不是算术符号就入栈
  15.                 如果是算术符号就出栈两个数字,进行运算
  16.         */
  17.         for (string ch : tokens)
  18.         {
  19.             if (ch == "/")
  20.             {
  21.                 num1 = stoi(sa.top());
  22.                 sa.pop();
  23.                 num2 = stoi(sa.top());
  24.                 sa.pop();
  25.                 result = (num2 / num1);
  26.                 sa.push(to_string(result));
  27.             }
  28.             else if (ch == "*")
  29.             {
  30.                 num1 = stoi(sa.top());
  31.                 sa.pop();
  32.                 num2 = stoi(sa.top());
  33.                 sa.pop();
  34.                 result = (num1 * num2);
  35.                 sa.push(to_string(result));
  36.             }
  37.             else if (ch == "+")
  38.             {
  39.                 num1 = stoi(sa.top());
  40.                 sa.pop();
  41.                 num2 = stoi(sa.top());
  42.                 sa.pop();
  43.                 result = (num1 + num2);
  44.                 sa.push(to_string(result));
  45.             }
  46.             else if (ch == "-")
  47.             {
  48.                 num1 = stoi(sa.top());
  49.                 sa.pop();
  50.                 num2 = stoi(sa.top());
  51.                 sa.pop();
  52.                 result = (num2 - num1);
  53.                 sa.push(to_string(result));
  54.             }
  55.             else
  56.                 sa.push(ch);
  57.         }
  58.         cout << "result= " << result << endl;
  59.         return result;
  60.     }
  61. };
  62. void main()
  63. {
  64.     Solution s1;
  65.     //vector<string> tokens = { "2","1","+","3","*" };
  66.     vector<string> tokens = { "10","6","9","3","+","-11","*","/","*","17","+","5","+" };
  67.     s1.evalRPN(tokens);
  68. }
复制代码
滑动窗口最大值


暴力法

  1. #include<iostream>
  2. #include<stack>
  3. #include<vector>
  4. #include<string>
  5. #include<algorithm>
  6. using namespace std;
  7. class Solution {
  8. public:
  9.     vector<int> maxSlidingWindow(vector<int>& nums, int k) {
  10.         vector<int> res;
  11.         vector<int>::iterator iter;
  12.         for (iter=nums.begin();(iter+k)<nums.end();iter++)
  13.         {
  14.             vector<int>::iterator max = max_element(iter,iter+k);
  15.             res.push_back(*max);
  16.         }
  17.         vector<int>::iterator max = max_element(iter, iter + k);
  18.         res.push_back(*max);
  19.         return res;
  20.     }
  21. };
复制代码
单调队列


  1. #include<iostream>
  2. #include<queue>
  3. #include<vector>
  4. #include<string>
  5. #include<algorithm>
  6. using namespace std;
  7. class MyQueue { //单调队列(从大到小)
  8. public:
  9.     deque<int> que; // 使用deque来实现单调队列
  10. // 这样就保持了队列里的数值是单调从大到小的了。
  11.     void push(int value)
  12.     {
  13.         while (!que.empty() && value > que.back()) // 队列前面的元素必须比即将加入的元素要打
  14.             que.pop_back();
  15.         que.push_back(value);
  16.     }
  17.     // 每次弹出的时候,比较当前要弹出的数值是否等于队列出口元素的数值,如果相等则弹出。
  18.     // 同时pop之前判断队列当前是否为空。
  19.     void pop(int value) {
  20.         if (!que.empty() && value == que.front())
  21.             que.pop_front();
  22.     }
  23.     // 查询当前队列里的最大值 直接返回队列前端也就是front就可以了。
  24.     int get_max() {
  25.         return que.front();
  26.     }
  27. };
  28. class Solution {
  29. public:
  30.     vector<int> maxSlidingWindow(vector<int>& nums, int k) {
  31.         MyQueue que;
  32.         vector<int> result;
  33.         for (int i = 0; i < k; i++) { // 先将前k的元素放进队列
  34.             que.push(nums[i]);
  35.         }
  36.         result.push_back(que.get_max()); // result 记录前k的元素的最大值
  37.         for (int i = k; i < nums.size(); i++) {
  38.             que.pop(nums[i - k]); // 滑动窗口移除最前面元素
  39.             que.push(nums[i]); // 滑动窗口前加入最后面的元素
  40.             result.push_back(que.get_max()); // 记录对应的最大值
  41.         }
  42.         return result;
  43.     }
  44. };
复制代码
前k个高频元素



二叉树

理论基础


遍历

前序遍历


递归版本

  1. class Solution {
  2. private:
  3.     std::vector<int> res;
  4. public:
  5.     std::vector<int> preorderTraversal(TreeNode* root) {
  6.         if (root)
  7.         {
  8.             res.push_back(root->val);
  9.             preorderTraversal(root->left);
  10.             preorderTraversal(root->right);
  11.         }
  12.         return res;
  13.     }
  14. };
复制代码

非递归版本


  1.    #include<iostream>
  2. #include<vector>
  3. #include<stack>
  4.     class Solution {
  5.     private:
  6.         std::vector<int> res;
  7.     public:
  8.         std::vector<int> preorderTraversal(TreeNode* root) {
  9.            /*
  10.                 每次遍历之前先把其右孩子压栈,然后将其左孩子压栈
  11.             */
  12.             std::stack<TreeNode*> sta;
  13.             sta.push(root);
  14.             while (!sta.empty())
  15.             {
  16.                 TreeNode* node = sta.top();
  17.                 sta.pop();
  18.                 if(node)
  19.                     res.push_back(node->val);
  20.                 else
  21.                     continue;
  22.                 sta.push(node->right);
  23.                 sta.push(node->left);
  24.             }
  25.             return res;
  26.         }
  27.     };
  28. ``
  29. ## 中序遍历
  30. ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/69d8e0541b71448dbb0056509e1b4828.png)
  31. ```cpp
  32. class Solution {
  33. private:
  34.     std::vector<int> res;
  35. public:
  36.     std::vector<int> inorderTraversal(TreeNode* root) {
  37.         if (root)
  38.         {
  39.             inorderTraversal(root->left);
  40.             res.push_back(root->val);
  41.             inorderTraversal(root->right);
  42.         }
  43.         return res;
  44.     }
  45. };
复制代码
中序遍历

递归版本

  1. class Solution {
  2. private:
  3.     std::vector<int> res;
  4. public:
  5.     std::vector<int> inorderTraversal(TreeNode* root) {
  6.         if (root)
  7.         {
  8.             inorderTraversal(root->left);
  9.             res.push_back(root->val);
  10.             inorderTraversal(root->right);
  11.         }
  12.         return res;
  13.     }
  14. };
复制代码
非递归版本


  1. #include<iostream>
  2. #include<vector>
  3. #include<stack>
  4. #include<algorithm>
  5. struct TreeNode {
  6.      int val;
  7.      TreeNode *left;
  8.      TreeNode *right;
  9. };
  10. class Solution {
  11. private:
  12.     std::vector<int> res;
  13. public:
  14.     std::vector<int> inorderTraversal(TreeNode* root) {
  15.         std::stack<TreeNode*> sta;
  16.         TreeNode* p = root;
  17.         while (p!=NULL || !sta.empty())
  18.         {
  19.             if (p)
  20.             {
  21.                 sta.push(p);
  22.                 p = p->left;
  23.             }
  24.             else
  25.             {
  26.                 p = sta.top();
  27.                 sta.pop();
  28.                 res.push_back(p->val);
  29.                 p = p->right;
  30.             }
  31.         }
  32.         return res;
  33.     }
  34. };
复制代码
后序遍历

递归版本


  1. class Solution {
  2. private:
  3.     std::vector<int> res;
  4. public:
  5.     std::vector<int> postorderTraversal(TreeNode* root) {
  6.         if (root)
  7.         {
  8.             postorderTraversal(root->left);
  9.             postorderTraversal(root->right);
  10.             res.push_back(root->val);
  11.         }
  12.         return res;
  13.     }
  14. };
复制代码
非递归版本(前序->后序)


  1. #include<iostream>
  2. #include<vector>
  3. #include<stack>
  4. #include<algorithm>
  5. class Solution {
  6. private:
  7.     std::vector<int> res;
  8. public:
  9.     std::vector<int> postorderTraversal(TreeNode* root) {
  10.         /*
  11.              每次遍历之前先把其右孩子压栈,然后将其左孩子压栈
  12.          */
  13.         std::stack<TreeNode*> sta;
  14.         sta.push(root);
  15.         while (!sta.empty())
  16.         {
  17.             TreeNode* node = sta.top();
  18.             sta.pop();
  19.             if (node)
  20.                 res.push_back(node->val);
  21.             else
  22.                 continue;
  23.             sta.push(node->left);
  24.             sta.push(node->right);
  25.         }
  26.         std::reverse(res.begin(),res.end());
  27.         return res;
  28.     }
  29. };
复制代码
层序遍历


  1. #include<iostream>
  2. #include<vector>
  3. #include<queue>
  4. #include<algorithm>
  5. using namespace std;
  6. struct TreeNode {
  7.      int val;
  8.      TreeNode *left;
  9.      TreeNode *right;
  10. };
  11. class Solution {
  12. public:
  13.     vector<vector<int>> res;
  14. public:
  15.     vector<vector<int>> levelOrder(TreeNode* root) {
  16.         queue<TreeNode*> que;
  17.         vector<int> tmp;
  18.         int size = 0;
  19.         if (root != NULL)
  20.             tmp.push_back(root->val);
  21.         else
  22.             return res;
  23.         res.push_back(tmp);
  24.         tmp.clear();
  25.         if (root->left != NULL)
  26.             que.push(root->left);
  27.         if (root->right != NULL)
  28.             que.push(root->right);
  29.         size = que.size();
  30.         while (!que.empty())
  31.         {
  32.             TreeNode* p = que.front();
  33.             que.pop();
  34.             tmp.push_back(p->val);
  35.             size--;
  36.             if (p->left != NULL)
  37.                 que.push(p->left);
  38.             if (p->right != NULL)
  39.                 que.push(p->right);
  40.             if (size == 0)
  41.             {
  42.                 res.push_back(tmp);
  43.                 tmp.clear();
  44.                 size = que.size();
  45.             }
  46.         }
  47.         return res;
  48.     }
  49. };
  50. int main()
  51. {}
复制代码
翻转二叉树



  1. class Solution {
  2. public:
  3.     TreeNode* invertTree(TreeNode* root) {
  4.         if (root != NULL)
  5.         {
  6.             if (root->left != NULL || root->right != NULL)
  7.             {
  8.                 TreeNode* tmp = root->left;
  9.                 root->left = root->right;
  10.                 root->right = tmp;
  11.             }
  12.             invertTree(root->left);
  13.             invertTree(root->right);
  14.         }
  15.         return root;
  16.     }
  17. };
复制代码
对称二叉树



  1. class Solution {
  2. public:
  3.     bool compare(TreeNode* left, TreeNode* right) {
  4.         // 首先排除空节点的情况
  5.         if (left == NULL && right != NULL) return false;
  6.         else if (left != NULL && right == NULL) return false;
  7.         else if (left == NULL && right == NULL) return true;
  8.         // 排除了空节点,再排除数值不相同的情况
  9.         else if (left->val != right->val) return false;
  10.         // 此时就是:左右节点都不为空,且数值相同的情况
  11.         // 此时才做递归,做下一层的判断
  12.         bool outside = compare(left->left, right->right);   // 左子树:左、 右子树:右
  13.         bool inside = compare(left->right, right->left);    // 左子树:右、 右子树:左
  14.         bool isSame = outside && inside;                    // 左子树:中、 右子树:中 (逻辑处理)
  15.         return isSame;
  16.     }
  17.     bool isSymmetric(TreeNode* root) {
  18.         if (root == NULL) return true;
  19.         return compare(root->left, root->right);
  20.     }
  21. };
复制代码
二叉树的最大深度


递归版本


  1. class Solution {
  2. public:
  3. // 这是一个求高度的代码:利用后序遍历
  4.     int maxDepth(TreeNode* root) {
  5.         if(root==NULL)
  6.             return 0;
  7.         int left = maxDepth(root->left); // 左子树的高度
  8.         int right = maxDepth(root->right);//右子树的高度
  9.         return 1+(left > right ? left : right );
  10.     }
  11. };
复制代码
求二叉树的最小深度



  1. class Solution {
  2. public:
  3.     int minDepth(TreeNode* root) {
  4.         if (root == NULL)
  5.             return 0;
  6.         int Left = minDepth(root->left) ; // 左子树的高度
  7.         int Right = minDepth(root->right);//右子树的高度
  8.            
  9.            // NULL不算叶子节点
  10.         if (root->right != NULL && root->left == NULL)
  11.             return 1 + Right;
  12.         if (root->right == NULL && root->left != NULL)
  13.             return 1 + Left;
  14.         // 都不为空
  15.         int res = 1 + (Left > Right ? Right : Left);
  16.         return res;
  17.     }
  18. };
复制代码
完全二叉树节点的个数


使用层序遍历盘算节点数量

  1. class Solution {
  2. public:
  3.     int countNodes(TreeNode* root) {
  4.         stack<TreeNode*> sta;
  5.         int size = 0;
  6.         TreeNode* tmp = NULL;
  7.         if (root != NULL)
  8.         {
  9.             size++;
  10.             // cout << root->val << endl;
  11.         }
  12.         else
  13.             return 0;
  14.         if (root->left != NULL)
  15.             sta.push(root->left);
  16.         if (root->right != NULL)
  17.             sta.push(root->right);
  18.         while (!sta.empty())
  19.         {
  20.             tmp = sta.top();
  21.             sta.pop();
  22.             // cout << tmp->val << endl;
  23.             size++;
  24.             if (tmp->left != NULL)
  25.                 sta.push(tmp->left);
  26.             if (tmp->right != NULL)
  27.                 sta.push(tmp->right);
  28.         }
  29.         return size;
  30.     }
  31. };
复制代码
使用前序遍历盘算节点数量

  1. class Solution {
  2. public:
  3.     Solution() :len(0) {}
  4.     int countNodes(TreeNode* root) {
  5.         if (root != nullptr)
  6.         {
  7.             std::cout << root->val << std::endl;
  8.             this->len++;
  9.             countNodes(root->right);
  10.             countNodes(root->left);
  11.         }
  12.         return this->len;
  13.     }
  14. private:
  15.     int len;
  16. };
复制代码
使用中序遍历盘算节点数量

使用后序遍历盘算节点数量

  1. class Solution {
  2. public:
  3.     int countNodes(TreeNode* root) {
  4.         if (root != nullptr)
  5.         {
  6.             int lenRight = countNodes(root->right);
  7.             int lenLeft = countNodes(root->left);
  8.             return lenRight+ lenLeft+1;
  9.         }else
  10.         return 0;
  11.     }
  12. };
复制代码
使用满二叉树的节点盘算公式

  1. class Solution {
  2. public:
  3.     int countNodes(TreeNode* root)
  4.     {
  5.         // 终止条件1
  6.         if (root == nullptr) return 0;
  7.         TreeNode* left = root->left;
  8.         TreeNode* right = root->right;
  9.         int leftDepth = 0, rightDepth = 0;
  10.         while (left)
  11.         {
  12.             left = left->left;
  13.             leftDepth++;
  14.         }
  15.         while (right)
  16.         {
  17.             right = right->right;
  18.             rightDepth++;
  19.         }
  20.         // 终止条件2
  21.         if (leftDepth == rightDepth) // 此子树是一个完全二叉树:2^n-1这是完全二叉树的节点总数计算公式
  22.             return pow(2, rightDepth+1) - 1;
  23.         // 计算总的节点数量
  24.         return countNodes(root->left) + countNodes(root->right) +1;
  25.     }
  26. };
复制代码
平衡二叉树的判断

  1. class Solution {
  2. public:
  3.     int  getHeight(TreeNode* root)
  4.     {
  5.         if (root == nullptr) return 0;
  6.         int left = getHeight(root->left);
  7.         if (left == -1)  // 左子树不是一个平衡二叉树
  8.             return -1;
  9.        int right = getHeight(root->right);
  10.        if (right == -1)  // 右子树不是一个平衡二叉树
  11.            return -1;
  12.        int result;
  13.        if (abs(left - right > 1)) // 本节点所在的子树不是一棵平衡二叉树
  14.            result = -1;
  15.        else
  16.            result = (left > right ? left : right) + 1;  // 求出本节点的高度
  17.        return result;
  18.     }
  19.     bool isBalanced(TreeNode* root)
  20.     {
  21.         return getHeight(root)==-1?false:true;
  22.     }
  23. };
复制代码
二叉树的全部路径


  1. #include<iostream>
  2. #include<vector>
  3. #include<string>
  4. #include<cmath>
  5. struct TreeNode {
  6.     int val;
  7.     TreeNode* left;
  8.     TreeNode* right;
  9.     TreeNode() : val(0), left(nullptr), right(nullptr) {}
  10.     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
  11.     TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
  12. };
  13. class Solution {
  14. public:
  15.     // 前序遍历
  16.     std::vector<std::string> vec;
  17.     std::vector<int> path; // 经过的路径
  18.     std::vector<std::string> binaryTreePaths(TreeNode* root) {
  19.         /*
  20.             思路:此道题用到回溯的思想,回溯一般会和递归挂钩即栈
  21.             明显使用前序遍历
  22.             从上往下,
  23.                 1. 遇到叶子时,此条路径结束,需要将其加入到容器中
  24.                 2. 然后,需要把此叶子节点弹出,这里就是回溯。
  25.         */
  26.         path.push_back(root->val);
  27.         if (root->left == nullptr && root->right == nullptr) // 到达叶子节点
  28.         {
  29.             std::string str;
  30.             for (std::vector<int>::iterator  it = path.begin(); it != path.end(); it++)
  31.             {
  32.                 if ((it + 1) == path.end())
  33.                     str += std::to_string(*it);
  34.                 else
  35.                     str += std::to_string(*it) + "->";
  36.             }
  37.             vec.push_back(str);
  38.             return vec;
  39.         }
  40.         if (root->left != nullptr)
  41.         {
  42.             binaryTreePaths(root->left);
  43.             path.pop_back();// 左子树遍历完成,弹栈,回溯
  44.         }
  45.         if (root->right != nullptr)
  46.         {
  47.             binaryTreePaths(root->right);
  48.             path.pop_back();  // 回溯
  49.         }
  50.     }
  51. };
复制代码
左叶子之和


  1. class Solution {
  2. private:
  3.     int sumLeftLeaces;
  4. public:
  5.     Solution() :sumLeftLeaces(0) {}
  6.     int sumOfLeftLeaves(TreeNode* root) {
  7.         if (root != nullptr)
  8.         {
  9.             //前序遍历
  10.             if (root->left != nullptr)
  11.                 this->sumLeftLeaces += root->left->val;
  12.             sumOfLeftLeaves(root->left);
  13.             sumOfLeftLeaves(root->right);
  14.         }
  15.         return this->sumLeftLeaces;
  16.     }
  17. };
复制代码
找树的左下角的值



使用递归法

  1. class Solution {
  2. public:
  3.     int maxDepth = INT_MIN;
  4.     int result;
  5.     void traversal(TreeNode* root, int depth) {
  6.         if (root->left == NULL && root->right == NULL) {
  7.             if (depth > maxDepth) {
  8.                 maxDepth = depth;
  9.                 result = root->val;
  10.             }
  11.             return;
  12.         }
  13.         if (root->left) {
  14.             depth++;
  15.             traversal(root->left, depth);
  16.             depth--; // 回溯
  17.         }
  18.         if (root->right) {
  19.             depth++;
  20.             traversal(root->right, depth);
  21.             depth--; // 回溯
  22.         }
  23.         return;
  24.     }
  25.     int findBottomLeftValue(TreeNode* root) {
  26.         traversal(root, 0);
  27.         return result;
  28.     }
  29. };
复制代码
层序遍历

  1. class Solution {
  2. public:
  3.     std::queue<TreeNode*> qu;
  4.     int findBottomLeftValue(TreeNode* root) {
  5.         if (root == nullptr)
  6.             return -1;
  7.         qu.push(root);
  8.         TreeNode* tmp;
  9.         while (!qu.empty())
  10.         {
  11.             tmp = qu.front();
  12.             if (qu.size() == 1 && tmp->right == nullptr && tmp->left== nullptr)
  13.                 return tmp->val;
  14.             qu.pop();
  15.             if (tmp->right != nullptr)
  16.                 qu.push(tmp->right);
  17.             if (tmp->left != nullptr)
  18.                 qu.push(tmp->left);  
  19.         }
  20.         return -1;
  21.     }
  22. };
复制代码
  利用层序遍历,每次先将右孩子入队,再将左孩子入队。
  路径之和





  1. // 注意有返回值,应该返回每一次递归调用的返回值
  2. class Solution {
  3. public:
  4.     // 前序遍历
  5.     std::vector<int> path; // 经过的路径
  6.     bool hasPathSum(TreeNode* root, int targetSum) {
  7.         /*
  8.             思路:此道题用到回溯的思想,回溯一般会和递归挂钩即栈
  9.             明显使用前序遍历
  10.             从上往下,
  11.                 1. 遇到叶子时,此条路径结束,需要将其加入到容器中
  12.                 2. 然后,需要把此叶子节点弹出,这里就是回溯。
  13.         */
  14.         if (root == nullptr)
  15.             return false;
  16.         path.push_back(root->val);
  17.         if (root->left == nullptr && root->right == nullptr) // 到达叶子节点
  18.         {
  19.             int sum = 0;
  20.             for (std::vector<int>::iterator it = path.begin(); it != path.end(); it++)
  21.                 sum += *it;
  22.             if (sum == targetSum)
  23.                 return true;
  24.         }
  25.         if (root->left != nullptr)
  26.         {
  27.             bool ret  = hasPathSum(root->left, targetSum);
  28.             if (ret)   // 注意这里。不要忘记
  29.                 return true;
  30.             path.pop_back();// 左子树遍历完成,弹栈,回溯
  31.         }
  32.         if (root->right != nullptr)
  33.         {
  34.             bool ret = hasPathSum(root->right, targetSum);
  35.             if (ret) // 注意这里。不要忘记
  36.                 return true;
  37.             path.pop_back();  // 回溯
  38.         }
  39.         return false;
  40.     }
  41. };
复制代码

  1. class Solution {
  2. public:
  3.     bool hasPathSum(TreeNode* root, int targetSum) {
  4.         if (root == NULL)
  5.             return false;
  6.         if (root->left == NULL && root->right == NULL && targetSum == 0)
  7.             return true;
  8.         if (root->left == NULL && root->right == NULL && targetSum != 0)
  9.             return false;
  10.         if (root->left != NULL) {
  11.             targetSum -= root->left->val;
  12.             bool ret = hasPathSum(root->left, targetSum);
  13.             if (ret) {
  14.                 return true;
  15.             }
  16.             else { // 回溯
  17.                 targetSum += root->left->val;
  18.             }
  19.         }
  20.         if (root->right != NULL) {
  21.             targetSum -= root->right->val;
  22.             bool ret = hasPathSum(root->right, targetSum);
  23.             if (ret) {
  24.                 return true;
  25.             }
  26.             else { // 回溯
  27.                 targetSum += root->right->val;
  28.             }
  29.         }
  30.         return false;
  31.     }
  32. };
复制代码
从中序和后序序列中构造二叉树

构造二叉树的题目的遍历方式就是前序遍历


  1. class Solution {
  2. public:
  3.     TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
  4.         /*
  5.              1. 后序数组为空,空节点
  6.              2. 后序数组最后一个元素为根节点
  7.              3. 在中序数组中找到根节点的位置作为切割点
  8.              4. 切中序数组
  9.              5. 切后序数组
  10.              6. 递归处理左区间和右区间
  11.         */
  12.         //1. 后序数组为空,空节点
  13.         if (postorder.size() == 0)
  14.             return 0;
  15.         //2. 后序数组最后一个元素为根节点
  16.         int rootValue = postorder[postorder.size()-1];
  17.         TreeNode* root = new TreeNode();
  18.         root->val = rootValue;
  19.         // 到达叶子节点
  20.         if (postorder.size() == 1)
  21.             return root;
  22.         //3. 在中序数组中找到根节点的位置作为切割点
  23.         int index = 0 ;
  24.         while (index < inorder.size())
  25.         {
  26.             if (inorder[index] == rootValue)
  27.                 break;
  28.             index++;
  29.         }
  30.         // 4. 切中序数组  遵从左闭右开
  31.         vector<int> leftInorder(inorder.begin(), inorder.begin()+index);
  32.         vector<int> rightInorder(inorder.begin() + index+1, inorder.end());
  33.         // postorder 舍弃末尾元素,因为这个元素就是中间节点,已经用过了
  34.        // 5. 切后序数组  遵从左闭右开
  35.        // 5. 切后序数组  遵从左闭右开
  36.         postorder.resize(postorder.size() - 1);
  37.         vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());
  38.         //vector<int> rightPostorder(postorder.begin() + leftInorder.size(), postorder.end());
  39.         vector<int> rightPostorder(postorder.begin() + leftInorder.size(), postorder.begin() + leftInorder.size()+ rightInorder.size());
  40.         
  41.         /*for (int i = 0; i < index; i++)
  42.             leftInorder.push_back(inorder[i]);
  43.         for (int i = index+1; i < postorder.size(); i++)
  44.             rightInorder.push_back(inorder[i]);*/
  45.         //
  46.         //for (int i = 0; i < leftInorder.size(); i++)
  47.         //    leftPostorder.push_back(postorder[i]);
  48.         //for (int i = leftInorder.size(); i < rightInorder.size(); i++)
  49.         //    rightPostorder.push_back(postorder[i]);
  50.         ///6. 递归处理左区间和右区间
  51.         root->left = buildTree(leftInorder, leftPostorder);
  52.         root->right = buildTree(rightInorder, rightPostorder);
  53.         return root;
  54.     }
  55. };
复制代码
最大二叉树



  1. int max(vector<int>& nums)
  2. {
  3.     int maxi = 0;
  4.     for (int i = 0; i < nums.size(); i++) {
  5.         if (nums[maxi] < nums[i])
  6.             maxi = i;
  7.     }
  8.     return maxi;
  9. }
  10. TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
  11.     /*思路:
  12.         1.  nums == NULL  return NULL;
  13.         2. 找到最大值,构造根节点
  14.         3. 根据最大值点,分割左数组和右数组
  15.         4. 递归构造左子树和右子树
  16.     */
  17.     // nums.size = 0
  18.     if (nums.size() == 0)
  19.         return NULL;
  20.     //2. 找到最大值,构造根节点
  21.     int maxi = max(nums);
  22.     TreeNode* root = new TreeNode();
  23.     root->val = nums[maxi];
  24.     if (nums.size() == 1)
  25.         return root;
  26.     //3. 根据最大值点,分割左数组和右数组
  27.     vector<int> leftNums(nums.begin(), nums.begin() + maxi);
  28.     vector<int> rightNums(nums.begin() + maxi+1, nums.end());
  29.     //4. 递归构造左子树和右子树
  30.     root->left = constructMaximumBinaryTree(leftNums);
  31.     root->right = constructMaximumBinaryTree(rightNums);
  32.     return root;
  33. }
复制代码
合并二叉树


  1. class Solution {
  2. public:
  3.     TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
  4.         // 两个都采用前序遍历
  5.         if (root1 != NULL && root2 != NULL)
  6.         {
  7.             root1->val += root2->val;
  8.             if (root1->left == NULL && root2->left != NULL)
  9.             {
  10.                 TreeNode* tmp = new TreeNode(0);
  11.                 tmp->left = NULL;
  12.                 tmp->right = NULL;
  13.                 root1->left = tmp;
  14.             }
  15.             else if (root1->left != NULL && root2->left == NULL)
  16.             {
  17.                 TreeNode* tmp = new TreeNode(0);
  18.                 tmp->left = NULL;
  19.                 tmp->right = NULL;
  20.                 root2->left = tmp;
  21.             }
  22.             mergeTrees(root1->left, root2->left);
  23.             
  24.             if (root1->right == NULL && root2->right != NULL)
  25.             {
  26.                 TreeNode* tmp = new TreeNode(0);
  27.                 tmp->left = NULL;
  28.                 tmp->right = NULL;
  29.                 root1->right = tmp;
  30.             }
  31.             else if (root1->right != NULL && root2->right == NULL)
  32.             {
  33.                 TreeNode* tmp = new TreeNode(0);
  34.                 tmp->left = NULL;
  35.                 tmp->right = NULL;
  36.                 root2->right = tmp;
  37.             }
  38.             mergeTrees(root1->right, root2->right);
  39.         }
  40.         return root1;
  41.         
  42.     }
  43. };
复制代码

  1. class Solution {
  2. public:
  3.     TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
  4.         // 两个都采用前序遍历
  5.         if (root1 == NULL) return root2;
  6.         if (root2 == NULL) return root1;
  7.         root1->val += root2->val;
  8.         root1->left = mergeTrees(root1->left, root2->left);
  9.         root1->right = mergeTrees(root1->right, root2->right);
  10.         return root1;
  11.     }
  12. };
复制代码
二叉搜刮树中的搜刮


  1. class Solution {
  2. public:
  3.     TreeNode* searchBST(TreeNode* root, int val) {
  4.         // 这个为什么不行
  5.         /*if (root != NULL)
  6.         {
  7.             if (root->val == val)
  8.                 return root;
  9.             searchBST(root->left, val);
  10.             searchBST(root->right, val);
  11.         }
  12.         return NULL;*/
  13.         if (root == NULL || root->val == val)
  14.             return root;
  15.         TreeNode* res = NULL;
  16.         if (val < root->val)
  17.             res = searchBST(root->left, val);
  18.         if (val > root->val)
  19.             res = searchBST(root->left, val);
  20.         return res;
  21.     }
  22. };
复制代码
验证二叉搜刮树



  1. class Solution {
  2. public:
  3.     long long maxVal = LLONG_MIN;
  4.     bool isValidBST(TreeNode* root) {
  5.         if (root == NULL)
  6.             return true; // 注意空树也是BTS
  7.         // 判断左子树
  8.         bool left = isValidBST(root->left);
  9.         if (root->val > maxVal)
  10.             maxVal = root->val; // 如果是BTS则一定每次都会更换
  11.         else
  12.             return false;
  13.         // 判断右子树         
  14.         bool right = isValidBST(root->right);
  15.         return left && right;
  16.         
  17.     }
  18. };
复制代码

双指针优化


   利用中序遍历BTS,得到的是一个递增序列的特点.
  1. class Solution {
  2. public:
  3.     TreeNode* prev = nullptr; // 记录上一个访问的节点
  4.     bool isValidBST(TreeNode* root) {
  5.         if (root == NULL)
  6.             return true;
  7.         // 递归检查左子树
  8.         if (!isValidBST(root->left))
  9.             return false;
  10.         // 检查当前节点是否满足递增
  11.         if (prev != nullptr && root->val <= prev->val)
  12.             return false;
  13.         
  14.         prev = root; // 更新上一个访问的节点
  15.         // 递归检查右子树
  16.         return isValidBST(root->right);
  17.     }
  18. };
复制代码
二叉搜刮树中的最小绝对差



中序序列


  1. // 得到其中序遍历序列,然后在序列中寻找,相邻元素的最小差值
  2. class Solution {
  3. public:
  4.     vector<int> vec;
  5.     void preVist(TreeNode* root)
  6.     {
  7.         if (root != NULL)
  8.         {
  9.             preVist(root->left);
  10.             vec.push_back(root->val);
  11.             preVist(root->right);
  12.         }
  13.     }
  14.     int getMinimumDifference(TreeNode* root)
  15.     {
  16.         preVist(root);
  17.         int min = std::numeric_limits<int>::max();
  18.         for (int i = 0; i + 1 < vec.size(); i++)
  19.         {
  20.             if (abs(vec[i] - vec[i + 1]) < min)
  21.                 min = abs(vec[i] - vec[i + 1]);
  22.         }
  23.         return min;
  24.     }
  25. };
复制代码
双指针优化


  1. class Solution {
  2. public:
  3.     int min = numeric_limits<int>::max();
  4.     TreeNode* prev = nullptr;
  5.     int getMinimumDifference(TreeNode* root)
  6.     {
  7.         if (root != NULL)
  8.         {
  9.             getMinimumDifference(root->left);
  10.             if (prev != nullptr)   // 注意这里的如何保存上一个节点的值
  11.             {
  12.                 if (abs(prev->val - root->val) < min)
  13.                 {
  14.                     min = abs(prev->val - root->val);
  15.                 }
  16.             }
  17.             prev = root;
  18.             getMinimumDifference(root->right);
  19.         }
  20.         return min;
  21.     }
  22. };
复制代码
二叉搜素树种的众数


   //如果一棵普通的二叉树的思路
// 使用map,分别统计各个元素出现的次数
  两阶段法

  1. // 首先找到众数的个数
  2. //然后依次计算每个元素出现的次数,次数等于众数个数的就是众数
  3. class Solution {
  4. public:
  5.     vector<int> res = {0};
  6.     TreeNode* pre = nullptr;
  7.     int count = 0;
  8.     int max = 0;
  9.     void findMax(TreeNode* root)
  10.     {//确定总数的最大值
  11.         if (root == nullptr)
  12.             return ;
  13.         findMode(root->left);
  14.         if (pre != nullptr)
  15.         {
  16.             if (pre->val == root->val)
  17.             {
  18.                 count++;
  19.             }
  20.             else {
  21.                 if (max < count)
  22.                     max = count;
  23.                 //count = 0;
  24.                 count = 1; // 注意:这里是1 ,已经指向一个新的元素了
  25.             }
  26.         }
  27.         else {
  28.             count = 1; //注意:这里当pre为空时,root已经指向左下角的元素了。
  29.         }
  30.         pre = root;
  31.         findMode(root->right);
  32.     }
  33.     vector<int> findNum(TreeNode* root) {
  34.         if (root == nullptr)
  35.             return res;
  36.         findNum(root->left);
  37.         if (pre != nullptr)
  38.         {
  39.             if (pre->val == root->val)
  40.             {
  41.                 count++;
  42.             }
  43.             else {
  44.                 if (max = count)
  45.                 {
  46.                     if(res[0] == 0)
  47.                         res.clear();
  48.                     res.push_back(pre->val);
  49.                 }
  50.             }
  51.         }
  52.       
  53.         pre = root;
  54.         findNum(root->right);
  55.         return res;
  56.     }
  57.     vector<int> findMode(TreeNode* root)
  58.     {
  59.         findMax(root);
  60.         findNum(root);
  61.         return res;
  62.     }
  63. };
复制代码
遍历1次

  1. // 首先找到众数的个数
  2. //然后依次计算每个元素出现的次数,次数等于众数个数的就是众数
  3. class Solution {
  4. public:
  5.     vector<int> res = {0};
  6.     TreeNode* pre = nullptr;
  7.     int count = 0;
  8.     int max = 0;
  9.     vector<int> findMode(TreeNode* root)
  10.     {
  11.         if (root == nullptr)
  12.             return res;
  13.         findMode(root->left);
  14.         if (pre != nullptr)
  15.         {
  16.             if (pre->val == root->val)
  17.             {
  18.                 count++;
  19.             }
  20.             else {
  21.                 //count = 0;
  22.                 count = 1; // 注意:这里是1 ,已经指向一个新的元素了
  23.             }
  24.         }
  25.         else {
  26.             count = 1; //注意:这里当pre为空时,root已经指向左下角的元素了。
  27.         }
  28.         pre = root;
  29.         //-----------------------------只需要依次遍历--------------------------------------
  30.         if (count == max)
  31.             res.push_back(pre->val);
  32.         if (count > max)
  33.         {
  34.             res.clear();
  35.             max = count;
  36.             res.push_back(pre->val);
  37.         }
  38.         //-------------------------------------------------------------------
  39.         findMode(root->right);
  40.         return res;
  41.     }
  42. };
复制代码
二叉树的最近公共先人


暴力法

  1. #include<iostream>
  2. #include<vector>
  3. #include<map>
  4. #include<string>
  5. #include<cmath>
  6. using namespace std;
  7. struct TreeNode {
  8.     int val;
  9.     TreeNode* left;
  10.     TreeNode* right;
  11.     TreeNode() : val(0), left(nullptr), right(nullptr) {}
  12.     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
  13.     TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
  14. };
  15. class Solution {
  16. public:
  17.     // 如何得到所有叶子节点的从根到叶子的路径
  18.     /*
  19.         从上往下,
  20.                 1. 遇到叶子时,此条路径结束,需要将其加入到容器中
  21.                 2. 然后,需要把此叶子节点弹出,这里就是回溯。
  22.     */
  23.     std::vector<TreeNode*> path; // 目前正在经过的路径。
  24.     std::map<TreeNode*, std::vector<TreeNode*>> leafPaths; //所有叶子节点路径
  25.     // 使用前向遍历
  26.     void getLeafsPath(TreeNode* root)
  27.     {
  28.         path.push_back(root);
  29.         if (root->left == nullptr && root->right == nullptr) // 到达叶子节点
  30.         { // 将所在的路径添加到leafPaths中
  31.             leafPaths[root] = path;
  32.         }
  33.         // 左遍历
  34.         if (root->left != nullptr)
  35.         {
  36.             getLeafsPath(root->left);
  37.             path.pop_back();// 左子树遍历完成,弹栈,回溯
  38.         }
  39.         //右遍历
  40.         if (root->right != nullptr)
  41.         {
  42.             getLeafsPath(root->right);
  43.             path.pop_back();  // 回溯
  44.         }
  45.     }
  46.     TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
  47.         getLeafsPath(root);
  48.         bool s1, s2;
  49.         int i1  = numeric_limits<int>::max(), i2 = numeric_limits<int>::max();
  50.         TreeNode* p1 = nullptr;
  51.         TreeNode* q1 = nullptr;
  52.         for (const auto pair : leafPaths)
  53.         {
  54.            //遍历每一天路径
  55.             // 当在同一条路径上时
  56.             s1 = false;
  57.             s2 = false;
  58.             for (int i = 0; i < pair.second.size(); i++)
  59.             {
  60.                 if (pair.second[i]->val == p->val)
  61.                 {
  62.                     s1 = true;
  63.                     i1 = i;
  64.                     p1 = pair.first;
  65.                 }
  66.                 if (pair.second[i]->val == q->val)
  67.                 {
  68.                     s2 = true;
  69.                     i2 = i;
  70.                     q1 = pair.first;
  71.                 }
  72.                 if (s1 && s2)
  73.                 {// 这里是为什么。。。。。。。。。。。。。
  74.                     return i1 < i2 ? pair.second[i1] : pair.second[i2];
  75.                 }
  76.                     
  77.             }
  78.             
  79.             //当在不同路径上时
  80.             if (i1 != numeric_limits<int>::max() && i2 != numeric_limits<int>::max()) // 找到p和q所在的序列
  81.             {
  82.                 std::vector<TreeNode*> v1 = leafPaths[p1];
  83.                 std::vector<TreeNode*> v2 = leafPaths[q1];
  84.                 for (; i1 >= 0 && i2 >= 0; i1--, i2--)
  85.                 {
  86.                     if (v1[i1]->val == v2[i2]->val)
  87.                         return v1[i1];
  88.                 }
  89.             }
  90.         }
  91.         return nullptr;
  92.     }
  93. };
复制代码
后序遍历+回溯

  1. class Solution {
  2. public:
  3.     // 要将找到的q或者p节点依次向上返回:所以需要采用后序遍历
  4.     TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
  5.         if (root == nullptr) return root;
  6.         if (root == q || root == p) return root; // 向上返回
  7.         TreeNode* left = lowestCommonAncestor(root->left,p,q);
  8.         TreeNode* right = lowestCommonAncestor(root->right, p, q);
  9.         if (left != nullptr && right != nullptr)
  10.             return root;
  11.         else if (left != nullptr && right == nullptr)
  12.             return left;
  13.         else if ((left == nullptr && right != nullptr))
  14.             return right;
  15.         else
  16.             return nullptr;
  17.     }
  18. };
复制代码
二叉搜刮树的最近公共先人


普通二叉树的方法

  1. if (root == nullptr) return root;
  2. if (root == q || root == p) return root; // 向上返回
  3. TreeNode* left = lowestCommonAncestor(root->left,p,q);
  4. TreeNode* right = lowestCommonAncestor(root->right, p, q);
  5. if (left != nullptr && right != nullptr)
  6.      return root;
  7. else if (left != nullptr && right == nullptr)
  8.      return left;
  9. else if ((left == nullptr && right != nullptr))
  10.      return right;
  11. else
  12.      return nullptr;
复制代码
前序遍历:利用搜刮树的性质

  1. class Solution {
  2. public:
  3.     // 前序遍历:
  4.     /*
  5.         1. 若两个节点比root都小,则在左子树
  6.         2. 若两个节点比root都大,则在右子树
  7.         3. 若两个节点在root分叉,则是root
  8.     */
  9.     TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
  10.         if (root)
  11.         {
  12.             if (root->val > p->val && root->val > q->val)
  13.                 root = lowestCommonAncestor(root->left,p,q);
  14.             if (root->val < p->val && root->val < q->val)
  15.                 root = lowestCommonAncestor(root->right, p, q);
  16.             if ((root->val < p->val && root->val > q->val) || (root->val > p->val && root->val < q->val))
  17.                 return root;
  18.         }
  19.         return root;
  20.     }
  21. };
复制代码
二叉搜素树插入

差的

  1. #include<iostream>
  2. #include<vector>
  3. #include<map>
  4. #include<string>
  5. #include<cmath>
  6. using namespace std;
  7. struct TreeNode {
  8.     int val;
  9.     TreeNode* left;
  10.     TreeNode* right;
  11.     TreeNode() : val(0), left(nullptr), right(nullptr) {}
  12.     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
  13.     TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
  14. };
  15. class Solution {
  16. public:
  17.     TreeNode* _root;
  18.     void insertNode(TreeNode* root,int val)
  19.     {
  20.         if (root)
  21.         {
  22.             if (root->val > val && root->left == nullptr)
  23.             {
  24.                 TreeNode* tmp = new TreeNode(val);
  25.                 tmp->left = nullptr;
  26.                 tmp->right = nullptr;
  27.                 root->left = tmp;
  28.                 return ;
  29.             }
  30.             if (root->val > val && root->left != nullptr)
  31.                 insertNode(root->left, val);
  32.             if (root->val < val && root->right == nullptr)
  33.             {
  34.                 TreeNode* tmp = new TreeNode(val);
  35.                 tmp->left = nullptr;
  36.                 tmp->right = nullptr;
  37.                 root->right = tmp;
  38.                 return;
  39.             }
  40.             if (root->val < val && root->right != nullptr)
  41.                 insertNode(root->right, val);
  42.         }
  43.     }
  44.     TreeNode* insertIntoBST(TreeNode* root, int val) {
  45.         _root = root;
  46.         insertNode(root,val);
  47.         return _root;
  48.     }
  49. };
复制代码
标准

  1. class Solution {
  2. public:
  3.     // 插入节点的递归函数
  4.     void insertNode(TreeNode*& root, int val) {
  5.         if (!root) {
  6.             // 如果当前节点为空,则在此位置创建新节点
  7.             root = new TreeNode(val);
  8.             return;
  9.         }
  10.         
  11.         if (val < root->val) {
  12.             // 如果插入值小于当前节点值,递归插入到左子树
  13.             insertNode(root->left, val);
  14.         } else if (val > root->val) {
  15.             // 如果插入值大于当前节点值,递归插入到右子树
  16.             insertNode(root->right, val);
  17.         }
  18.         // 如果相等则不做任何操作(假设不允许重复值)
  19.     }
  20.     // 插入节点的入口函数
  21.     TreeNode* insertIntoBST(TreeNode* root, int val) {
  22.         insertNode(root, val);
  23.         return root;
  24.     }
  25. };
复制代码
简便写法

  1. class Solution {
  2. public:
  3.     TreeNode* insertIntoBST(TreeNode* root, int val) {
  4.         if (root == nullptr)
  5.         {
  6.             TreeNode* node = new TreeNode(val);
  7.             return node;
  8.         }
  9.         if (root->val < val)
  10.         {
  11.             root->left = insertIntoBST(root->left,val);
  12.         }
  13.         else if (root->val > val) {
  14.             root->right = insertIntoBST(root->right, val);
  15.         }
  16.     }
  17. };
复制代码
删除二叉搜刮树的节点


风俗思路

  1. class Solution {
  2. public:
  3.     TreeNode* deleteNode(TreeNode* root, int key) {
  4.         /* 利用后序遍历
  5.             1. 空树时
  6.             2. 叶子节点时
  7.                 直接删除
  8.             3. 左子树为空
  9.                 右子树直接替换本节点
  10.             4. 右子树为空
  11.                 左子树直接替换本节点
  12.             5. 左右子树都不为空
  13.                 左子树直接替换本节点,右子树查到左子树的最右下方
  14.         */
  15.         if (root != nullptr)
  16.         {
  17.             root->left = deleteNode(root->left,key);
  18.             root->right = deleteNode(root->right,key);
  19.             if(root->val == key)
  20.             {
  21.                 if (root->left == nullptr && root->right == nullptr) // 待删除节点为叶子
  22.                 {
  23.                     
  24.                     delete root;
  25.                     root = nullptr;
  26.                     return root;
  27.                 }
  28.                 else if (root->left == nullptr && root->right != nullptr)
  29.                 {
  30.                     TreeNode* ptmp = root->right;
  31.                     delete root;
  32.                     root = nullptr;
  33.                     return ptmp;
  34.                 }else if (root->left != nullptr && root->right == nullptr)
  35.                 {
  36.                     TreeNode* ptmp = root->left;
  37.                     delete root;
  38.                     root = nullptr;
  39.                     return ptmp;
  40.                 }
  41.                 else { // 左右子树都存在:左子树直接替换本节点,右子树插到左子树的最右下方
  42.                     TreeNode* pleft = root->left;
  43.                     TreeNode* pright = root->right;
  44.                     delete root;
  45.                     root = nullptr;
  46.                     // 找到左子树的最右下方
  47.                     TreeNode* pre = pleft;
  48.                     for (TreeNode* tmp = pleft->right; tmp != nullptr;)
  49.                     {
  50.                         pre = tmp;
  51.                         tmp = tmp->right;
  52.                     }
  53.                     pre->right = pright;
  54.                     return pleft;
  55.                 }
  56.             }
  57.         }
  58.        return root;
  59.     }
  60. };
复制代码
修建二叉搜刮树


  1. class Solution {
  2. public:
  3.     /*
  4.         本质上还是二叉搜索树指定节点的删除
  5.     */
  6.     TreeNode* trimBST(TreeNode* root, int low, int high) {
  7.         if (root != nullptr)
  8.         {
  9.             root->left = trimBST(root->left,low,high);
  10.             root->right = trimBST(root->right, low, high);
  11.             if(root->val < low || root->val>high)
  12.             {
  13.                 if (root->left == nullptr && root->right == nullptr) // 待删除节点为叶子
  14.                 {
  15.                     
  16.                     delete root;
  17.                     root = nullptr;
  18.                     return root;
  19.                 }
  20.                 else if (root->left == nullptr && root->right != nullptr)
  21.                 {
  22.                     TreeNode* ptmp = root->right;
  23.                     delete root;
  24.                     root = nullptr;
  25.                     return ptmp;
  26.                 }else if (root->left != nullptr && root->right == nullptr)
  27.                 {
  28.                     TreeNode* ptmp = root->left;
  29.                     delete root;
  30.                     root = nullptr;
  31.                     return ptmp;
  32.                 }
  33.                 else { // 左右子树都存在:左子树直接替换本节点,右子树插到左子树的最右下方
  34.                     TreeNode* pleft = root->left;
  35.                     TreeNode* pright = root->right;
  36.                     delete root;
  37.                     root = nullptr;
  38.                     // 找到左子树的最右下方
  39.                     TreeNode* pre = pleft;
  40.                     for (TreeNode* tmp = pleft->right; tmp != nullptr;)
  41.                     {
  42.                         pre = tmp;
  43.                         tmp = tmp->right;
  44.                     }
  45.                     pre->right = pright;
  46.                     return pleft;
  47.                 }
  48.             }
  49.         }
  50.        return root;
  51.     }
  52. };
复制代码
将有序数组转换为二叉搜刮树


风俗思路

  1. class Solution {
  2. public:
  3.      /*
  4.      本质上还是二叉搜索树指定节点的删除
  5. */
  6.     TreeNode* sortedArrayToBST(vector<int>& nums) {
  7.         TreeNode* root = nullptr;
  8.      if (nums.size()>0)
  9.      {
  10.          int mid = nums.size() / 2;
  11.          root = new TreeNode(nums[mid]);
  12.          root->left = nullptr;
  13.          root->right = nullptr;
  14.          vector<int> left(nums.begin(), nums.begin() + mid);
  15.          vector<int> right(nums.begin() + mid + 1, nums.end());
  16.          root->left = sortedArrayToBST(left);
  17.          root->right = sortedArrayToBST(right);
  18.      }
  19.      return root;
  20.      
  21.      
  22. }
  23. };
复制代码
把二叉搜刮树转换为累加树

右中左遍历

  1. class Solution {
  2. public:
  3.     TreeNode* prev = nullptr;
  4.     TreeNode* convertBST(TreeNode* root) {
  5.         // 右中左:是从高到小遍历
  6.         if(root)
  7.         {
  8.             root->right = convertBST(root->right);
  9.             if (prev != nullptr)
  10.             {
  11.                 root->val += prev->val;
  12.             }
  13.             prev = root;
  14.             root->left = convertBST(root->left);
  15.         }
  16.         return root;
  17.     }
  18. };
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4