第一天 数组
136 只出现一次的数字
位运算。
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ret = 0;
for (auto e: nums) ret ^= e;
return ret;
}
};
169 多数元素
排序。
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(), nums.end());
return nums[nums.size() / 2];
}
};
15 三数之和
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
// 枚举 a
for (int first = 0; first < n; ++first) {
// 需要和上一次枚举的数不相同
if (first > 0 && nums[first] == nums[first - 1]) {
continue;
}
// c 对应的指针初始指向数组的最右端
int third = n - 1;
int target = -nums[first];
// 枚举 b
for (int second = first + 1; second < n; ++second) {
// 需要和上一次枚举的数不相同
if (second > first + 1 && nums[second] == nums[second - 1]) {
continue;
}
// 需要保证 b 的指针在 c 的指针的左侧
while (second < third && nums[second] + nums[third] > target) {
--third;
}
// 如果指针重合,随着 b 后续的增加
// 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环
if (second == third) {
break;
}
if (nums[second] + nums[third] == target) {
ans.push_back({nums[first], nums[second], nums[third]});
}
}
}
return ans;
}
};
第二天 数组
75 颜色分类
双指针。
class Solution {
public:
void sortColors(vector<int>& nums) {
int n = nums.size();
if (n < 2) {
return;
}
//双指针
int p = 0, q = n - 1;
for (int i = 0; i <= q; ++i) {
if (nums[i] == 0)
{
nums[i] = nums[p];
nums[p] = 0;
++p;
}
if (nums[i] == 2)
{
nums[i] = nums[q];
nums[q] = 2;
--q;
if (nums[i] != 1) {
--i;
}
}
}
return;
}
};
56 合并区间
排序法。
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
if (!intervals.size()) return {};
sort(intervals.begin(), intervals.end());
vector<vector<int>> outputs;
outputs.push_back(intervals[0]);
for (int i = 1; i < intervals.size(); i++) {
vector<int>& lastInterval = outputs.back();
int currLeft = intervals[i][0];
int currRight = intervals[i][1];
if (lastInterval[1] < currLeft) {
outputs.push_back(intervals[i]);
} else {
lastInterval[1] = max(lastInterval[1], currRight);
}
}
return outputs;
}
};
706 设计哈希映射
不会啊5555
//==================链表======================
typedef struct linklist{
int key;//表示键
int value;//表示值
struct linklist* next;//表示指向下一个节点
}Linklist;//创建一个储存键值对的链表结构体(头节点不储存数据)
void push(Linklist* h,int key,int value)//插入方法
{
Linklist* Add = malloc(sizeof(Linklist));//分配一个Linklsit的空间
Add->key = key;
Add->value = value;
//头插法构建链表
Add->next = h->next;
h->next = Add;
}
void Remove(Linklist* h,int key)//删除方法
{
for(Linklist* i=h;i->next;i=i->next)//从头节点开始遍历链表
{
if(i->next->key==key)//当下一个节点的key等于key,删除下一个节点
{
Linklist* re = i->next;//获取下一个节点
i->next = re->next;//将当前节点指向原本下一个节点的下位
free(re);//释放空间
break;
}
}
}
Linklist* find(Linklist* h,int key)//根据键查找节点
{
for(Linklist* i=h;i->next;i=i->next)//从头节点开始遍历链表
{
if(i->next->key==key)//如果找到该键
{
return i->next;//返回该键的节点指针
}
}
return NULL;//返回空
}
void Freelist(Linklist* h)//清空链表
{
while(h->next)
{
Linklist* re = h->next;//取出h下一个节点re
h->next = re->next;//将h指向re的下一个节点
free(re);//释放re空间
}
}
//================哈希映射表===================
int count = 769;//用于哈希计算取模标准,使用任意一个质数
int hash(int key)//哈希值计算
{
return key%count;
}
typedef struct {
Linklist* map;//创建一个键值对链表
} MyHashMap;
/** Initialize your data structure here. */
MyHashMap* myHashMapCreate(){
MyHashMap* result = malloc(sizeof(MyHashMap));//创建一个MyHashMap空间
result->map = malloc(sizeof(Linklist)*count);//分配result中的map空间大小为count个LinKlist
for(int i=0;i<count;i++)//遍历map,初始化链表
{
result->map[i].key = 0;
result->map[i].value = 0;
result->map[i].next = NULL;
}
return result;//返回result的指针
}
/** value will always be non-negative. */
void myHashMapPut(MyHashMap* obj, int key, int value) {
int hx = hash(key);//计算key的哈希值
Linklist* fl = find(&(obj->map[hx]),key);//获取key在map中的键值对节点
if(fl == NULL)//如果fl为空,即在链表中不存在该键
{
push(&(obj->map[hx]),key,value);//将该键值对放入链表
}
else//否则
{
fl->value = value;//更改新值
}
}
/** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */
int myHashMapGet(MyHashMap* obj, int key) {
int hx = hash(key);//计算key的哈希值
Linklist* fl = find(&(obj->map[hx]),key);//获取key在map中的键值对节点
if(fl == NULL)//如果fl为空,即在链表中不存在该键
{
return -1;
}
else//否则
{
return fl->value;//返回值
}
}
/** Removes the mapping of the specified value key if this map contains a mapping for the key */
void myHashMapRemove(MyHashMap* obj, int key) {
int hx = hash(key);//计算key的哈希值
Remove(&(obj->map[hx]),key);//移除该哈希索引中的指定键值对
}
void myHashMapFree(MyHashMap* obj) {
for(int i=0;i<count;i++)//遍历map
{
Freelist(&(obj->map[i]));//释放一个链表空间
}
free(obj->map);//释放map
}
/**
* Your MyHashMap struct will be instantiated and called as such:
* MyHashMap* obj = myHashMapCreate();
* myHashMapPut(obj, key, value);
* int param_2 = myHashMapGet(obj, key);
* myHashMapRemove(obj, key);
* myHashMapFree(obj);
*/
第三天 数组
119 杨辉三角II
class Solution {
public:
vector<int> getRow(int rowIndex) {
vector<vector<int>> C(rowIndex + 1);
for (int i = 0; i <= rowIndex; ++i)
{
C[i].resize(i + 1);
C[i][i] = C[i][0] = 1;
for (int j = 1; j < i; j++)
{
C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
}
}
return C[rowIndex];
}
};
48 旋转图像
秒啊。
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < i; ++ j)
{
swap(matrix[i][j], matrix[j][i]);
}
}
for (int i = 0; i < n; ++ i)
{
for (int j = 0, k = n - 1; j < k; ++j, --k)
{
swap(matrix[i][j], matrix[i][k]);
}
}
}
};
59 螺旋矩阵II
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
int t = 0; // top
int b = n-1; // bottom
int l = 0; // left
int r = n-1; // right
vector<vector<int>> ans(n,vector<int>(n));
int k=1;
while(k<=n*n){
for(int i=l;i<=r;++i,++k) ans[t][i] = k;
++t;
for(int i=t;i<=b;++i,++k) ans[i][r] = k;
--r;
for(int i=r;i>=l;--i,++k) ans[b][i] = k;
--b;
for(int i=b;i>=t;--i,++k) ans[i][l] = k;
++l;
}
return ans;
}
};
第四天 数组
240 搜索二维矩阵II
二分查找。
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
for (const auto& row: matrix)
{
auto it = lower_bound(row.begin(), row.end(), target);
if (it != row.end() && *it == target)
{
return true;
}
}
return false;
}
};
435 无重叠区间
class Solution {
public:
// 按照区间右边界排序
static bool cmp (const vector<int>& a, const vector<int>& b) {
return a[1] < b[1];
}
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
if (intervals.size() == 0) return 0;
sort(intervals.begin(), intervals.end(), cmp);
int count = 1; // 记录非交叉区间的个数
int end = intervals[0][1]; // 记录区间分割点
for (int i = 1; i < intervals.size(); i++) {
if (end <= intervals[i][0]) {
end = intervals[i][1];
count++;
}
}
return intervals.size() - count;
}
};
第五天 数组
334 递增的三元子序列
class Solution {
public:
bool increasingTriplet(vector<int>& nums) {
int len = nums.size();
int small = INT_MAX, mid = INT_MAX;
for (auto num: nums)
{
if (num <= small)
{
small = num;
}
else if (num < mid)
{
mid = num;
}
else if (num >mid)
{
return true;
}
}
return false;
}
};
238 除自身以外数组的乘积
建立左右乘积表。
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int length = nums.size();
vector<int> L(length, 0), R(length, 0);
vector<int> answer(length);
L[0] = 1;
for (int i = 1; i < length; i++) {
L[i] = nums[i - 1] * L[i - 1];
}
R[length - 1] = 1;
for (int i = length - 2; i >= 0; i--) {
R[i] = nums[i + 1] * R[i + 1];
}
for (int i = 0; i < length; i++) {
answer[i] = L[i] * R[i];
}
return answer;
}
};
560 和为k的子数组
前缀和+哈希表
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
unordered_map<int, int> mp;
mp[0] = 1;
int count = 0, pre = 0;
for (auto& x:nums) {
pre += x;
if (mp.find(pre - k) != mp.end()) {
count += mp[pre - k];
}
mp[pre]++;
}
return count;
}
};
第六天 字符串
415 字符串相加
class Solution {
public:
string addStrings(string num1, string num2) {
int i = num1.length() - 1, j = num2.length() - 1, add = 0;
string ans = "";
while (i >= 0 || j >= 0 || add != 0) {
int x = i >= 0 ? num1[i] - '0' : 0;
int y = j >= 0 ? num2[j] - '0' : 0;
int result = x + y + add;
ans.push_back('0' + result % 10);
add = result / 10;
i -= 1;
j -= 1;
}
// 计算完以后的答案需要翻转过来
reverse(ans.begin(), ans.end());
return ans;
}
};
409 最长回文串
哈希表。
class Solution {
public:
int longestPalindrome(string s) {
vector<int> m(128,0);
int len=0;
for(auto c:s) {
if(m[c]&1) len+=2;
m[c]++;
}
if(len<s.size()) len++;
return len;
}
};
第7天 字符串
290 单词规律
class Solution {
public:
bool wordPattern(string pattern, string s) {
vector<string> str;
stringstream iss(s); //直接截取字符串的函数
string word;
while(iss>>word) str.push_back(word); //把字符串放入
if(str.size()!=pattern.size()) return false; //判断是不是满射
unordered_map<char,string>pw; //判断是不是单射
unordered_map<string,char>wp; //判断是不是映射
for(int i = 0;i<pattern.size();i++)
{
auto a = pattern[i];
auto b = str[i];
if(pw.count(a)&&pw[a]!=b) return false; //如果存在该字母对应的字符串不一致,则返回false
pw[a] = b; //存入哈希表
if(wp.count(b)&&wp[b]!=a) return false; //如果存在该字符串对应的单词有多个(不一致) ,返回false
wp[b] = a; //存入哈希表
}
return true;
}
};
763 划分字母区间
贪心算法。
class Solution {
public:
vector<int> partitionLabels(string S) {
//用end 和 start来划分现在的一个区间
int map[26], length = S.size(), end = 0, start = 0;
vector<int> ans;
//记录字符串中每个字母最后出现的位置
for(int i = 0;i < length;i++){map[S[i]-'a'] = i;}
//遍历字符串
for(int i = 0;i < length;i++)
{
end = max(end, map[S[i]-'a']); //贪心策略:每次刷新到最小的但是要全部包含字母的位置
if(i == end) //如果指针i找到了end的话,就代表这个区间已经搜索完毕
{
ans.push_back(end-start+1);
start = end + 1;
}
}
return ans;
}
};
第八天 字符串
49 字母异位词分组
排序。
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
unordered_map<string, vector<string>> mp;
for (string& str: strs) {
string key = str;
sort(key.begin(), key.end());
mp[key].emplace_back(str);
}
vector<vector<string>> ans;
for (auto it = mp.begin(); it != mp.end(); ++it) {
ans.emplace_back(it->second);
}
return ans;
}
};
43字符串相乘
class Solution {
public:
string multiply(string num1, string num2) {
vector<int> A, B;
int n = num1.size(), m = num2.size();
for (int i = n - 1; i >= 0; i -- ) A.push_back(num1[i] - '0'); //反向存贮
for (int i = m - 1; i >= 0; i -- ) B.push_back(num2[i] - '0');
vector<int> C(n + m);
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
C[i + j] += A[i] * B[j];
int t = 0; //存贮进位
for (int i = 0; i < C.size(); i ++ ) {
t += C[i];
C[i] = t % 10;
t /= 10;
}
int k = C.size() - 1;
while (k > 0 && !C[k]) k -- ; //去除前导0
string res;
while (k >= 0) res += C[k -- ] + '0'; //反转
return res;
}
};
第九天 字符串
187. 重复的DNA序列
哈希表。
class Solution {
const int L = 10;
public:
vector<string> findRepeatedDnaSequences(string s) {
vector<string> ans;
unordered_map<string, int> cnt;
int n = s.length();
for (int i = 0; i <= n - L; ++i) {
string sub = s.substr(i, L);
if (++cnt[sub] == 2) {
ans.push_back(sub);
}
}
return ans;
}
};
5. 最长回文子串
class Solution {
public:
string longestPalindrome(string s) {
if(s.size()<2)return s;
int maxstar=0;
int maxlen=1;
int len=s.size();
vector<vector<bool>>dp(len,vector<bool>(len,false));//初始化
dp[0][0]=true;
for(int r=1;r<len;++r){
for(int l=0;l<r;++l){
dp[r][r]=true;
//r-l<=2是保证中心位为两位的子字符串能够被截取到
if(s[r]==s[l]&&(dp[l+1][r-1]||r-l<=2)){
dp[l][r]=true;
if(maxlen<r-l+1){
maxstar=l;
maxlen=r-l+1;
}
}
}
}
return s.substr(maxstar,maxlen);
}
};
第十天 链表
2. 两数相加
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode *head = nullptr, *tail = nullptr;
int carry = 0;
while (l1 || l2) {
int n1 = l1 ? l1->val: 0;
int n2 = l2 ? l2->val: 0;
int sum = n1 + n2 + carry;
if (!head) {
head = tail = new ListNode(sum % 10);
} else {
tail->next = new ListNode(sum % 10);
tail = tail->next;
}
carry = sum / 10;
if (l1) {
l1 = l1->next;
}
if (l2) {
l2 = l2->next;
}
}
if (carry > 0) {
tail->next = new ListNode(carry);
}
return head;
}
};
142. 环形链表 II
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
unordered_set<ListNode *> visited;
while (head != nullptr) {
if (visited.count(head)) {
return head;
}
visited.insert(head);
head = head->next;
}
return nullptr;
}
};
第十一天 链表
160 相交指针。
双指针。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (headA == nullptr || headB == nullptr)
{
return nullptr;
}
ListNode * pA = headA, *pB = headB;
while (pA != pB)
{
pA = pA == nullptr ? headB : pA = pA -> next;
pB = pB == nullptr ? headA : pB = pB -> next;
}
return pA;
}
};
82 删除排序链表中的重复元素
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if (!head) {
return head;
}
ListNode* dummy = new ListNode(0, head);
ListNode* cur = dummy;
while (cur->next && cur->next->next) {
if (cur->next->val == cur->next->next->val) {
int x = cur->next->val;
while (cur->next && cur->next->val == x) {
cur->next = cur->next->next;
}
}
else {
cur = cur->next;
}
}
return dummy->next;
}
};
第十二天 链表
24 两两交换链表中的节点
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if (head == nullptr || head->next == nullptr) {
return head;
}
ListNode* newHead = head->next;
head->next = swapPairs(newHead->next);
newHead->next = head;
return newHead;
}
};
707 设计链表
class MyLinkedList {
public:
// 定义链表节点结构体
struct LinkedNode {
int val;
LinkedNode* next;
LinkedNode(int val):val(val), next(nullptr){}
};
// 初始化链表
MyLinkedList() {
_dummyHead = new LinkedNode(0); // 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点
_size = 0;
}
// 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点
int get(int index) {
if (index > (_size - 1) || index < 0) {
return -1;
}
LinkedNode* cur = _dummyHead->next;
while(index--){ // 如果--index 就会陷入死循环
cur = cur->next;
}
return cur->val;
}
// 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点
void addAtHead(int val) {
LinkedNode* newNode = new LinkedNode(val);
newNode->next = _dummyHead->next;
_dummyHead->next = newNode;
_size++;
}
// 在链表最后面添加一个节点
void addAtTail(int val) {
LinkedNode* newNode = new LinkedNode(val);
LinkedNode* cur = _dummyHead;
while(cur->next != nullptr){
cur = cur->next;
}
cur->next = newNode;
_size++;
}
// 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
// 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点
// 如果index大于链表的长度,则返回空
void addAtIndex(int index, int val) {
if (index > _size) {
return;
}
LinkedNode* newNode = new LinkedNode(val);
LinkedNode* cur = _dummyHead;
while(index--) {
cur = cur->next;
}
newNode->next = cur->next;
cur->next = newNode;
_size++;
}
// 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的
void deleteAtIndex(int index) {
if (index >= _size || index < 0) {
return;
}
LinkedNode* cur = _dummyHead;
while(index--) {
cur = cur ->next;
}
LinkedNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
_size--;
}
// 打印链表
void printLinkedList() {
LinkedNode* cur = _dummyHead;
while (cur->next != nullptr) {
cout << cur->next->val << " ";
cur = cur->next;
}
cout << endl;
}
private:
int _size;
LinkedNode* _dummyHead;
};
第十三天 链表
25. K 个一组翻转链表
class Solution {
private:
// 反转链表
ListNode* reverseListNode(ListNode* head) {
ListNode* prev = nullptr;
ListNode* curr = head;
while (curr != nullptr) {
ListNode* next = curr->next;
curr->next = prev;
tie(prev, curr) = make_tuple(curr, next);
}
return prev;
}
public:
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode dummy; // 定义一个哑节点指向链表头部
dummy.next = head;
ListNode* prev = &dummy;// prev是指向当前最后一组反转完毕的链表的最后一个节点
while (head != nullptr) {
// innerLast 指向需要反转的k个节点的最后一个
ListNode* tmp = head, * innerLast = nullptr;
bool ableReverse = true;
for (int i = 0; i < k; ++i) {
if (head == nullptr) {
ableReverse = false;
break;
}
innerLast = head;
head = head->next;
}
// 剩下的节点足够 k 个
if (ableReverse) {
// 断开需要反转的k个节点的最后一个节点,与下一组链表节点的连接,head此时已经指向了下一组的头节点
innerLast->next = nullptr;
// 翻转之前,本组的第一个节点需要连接下一组节点,因此需要保存
ListNode* nextPrev = prev->next;
// 前一组已经反转完毕,前一组的最后一个节点指向,本组反转后的第一个节点
prev->next = reverseListNode(tmp);
// 本组节点翻转之后,需要连接下一组节点的头
nextPrev->next = head;
// 更新下一组组节点的前继节点
prev = nextPrev;
}
}
return dummy.next;
}
};
143. 重排链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
void reorderList(ListNode *head) {
if (head == nullptr) {
return;
}
vector<ListNode *> vec;
ListNode *node = head;
while (node != nullptr) {
vec.emplace_back(node);
node = node->next;
}
int i = 0, j = vec.size() - 1;
while (i < j) {
vec[i]->next = vec[j];
i++;
if (i == j) {
break;
}
vec[j]->next = vec[i];
j--;
}
vec[i]->next = nullptr;
}
};
第十四天 链表
155 最小栈
class MinStack {
stack<int> x_stack;
stack<int> min_stack;
public:
MinStack() {
min_stack.push(INT_MAX);
}
void push(int x) {
x_stack.push(x);
min_stack.push(min(min_stack.top(), x));
}
void pop() {
x_stack.pop();
min_stack.pop();
}
int top() {
return x_stack.top();
}
int getMin() {
return min_stack.top();
}
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(val);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
1249. 移除无效的括号
class Solution {
public:
string minRemoveToMakeValid(string s) {
int left = 0;
int right = count(begin(s), end(s), ')');
string ans = "";
for (auto& c : s) {
if (c == '(') {
if (right > 0) {
ans += c;
left++;
right--;
}
} else if (c == ')') {
if (left > 0) {
ans += c;
left--;
} else {
right--;
}
} else {
ans += c;
}
}
return ans;
}
};
1823. 找出游戏的获胜者
class Solution {
public:
int findTheWinner(int n, int k) {
queue<int> qu;
for (int i = 1; i <= n; i++) {
qu.emplace(i);
}
while (qu.size() > 1) {
for (int i = 1; i < k; i++) {
qu.emplace(qu.front());
qu.pop();
}
qu.pop();
}
return qu.front();
}
};
第 15 天 树
108. 将有序数组转换为二叉搜索树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
return helper(nums, 0, nums.size() - 1);
}
TreeNode* helper(vector<int>& nums, int left, int right) {
if (left > right) {
return nullptr;
}
// 总是选择中间位置左边的数字作为根节点
int mid = (left + right) / 2;
TreeNode* root = new TreeNode(nums[mid]);
root->left = helper(nums, left, mid - 1);
root->right = helper(nums, mid + 1, right);
return root;
}
};
105. 从前序与中序遍历序列构造二叉树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
private:
unordered_map<int, int> index;
public:
TreeNode* myBuildTree(const vector<int>& preorder, const vector<int>& inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {
if (preorder_left > preorder_right) {
return nullptr;
}
// 前序遍历中的第一个节点就是根节点
int preorder_root = preorder_left;
// 在中序遍历中定位根节点
int inorder_root = index[preorder[preorder_root]];
// 先把根节点建立出来
TreeNode* root = new TreeNode(preorder[preorder_root]);
// 得到左子树中的节点数目
int size_left_subtree = inorder_root - inorder_left;
// 递归地构造左子树,并连接到根节点
// 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
root->left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1);
// 递归地构造右子树,并连接到根节点
// 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
root->right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int n = preorder.size();
// 构造哈希映射,帮助我们快速定位根节点
for (int i = 0; i < n; ++i) {
index[inorder[i]] = i;
}
return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);
}
};
103. 二叉树的锯齿形层序遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>> ans;
if (!root) {
return ans;
}
queue<TreeNode*> nodeQueue;
nodeQueue.push(root);
bool isOrderLeft = true;
while (!nodeQueue.empty()) {
deque<int> levelList;
int size = nodeQueue.size();
for (int i = 0; i < size; ++i) {
auto node = nodeQueue.front();
nodeQueue.pop();
if (isOrderLeft) {
levelList.push_back(node->val);
} else {
levelList.push_front(node->val);
}
if (node->left) {
nodeQueue.push(node->left);
}
if (node->right) {
nodeQueue.push(node->right);
}
}
ans.emplace_back(vector<int>{levelList.begin(), levelList.end()});
isOrderLeft = !isOrderLeft;
}
return ans;
}
};
第十六天 树
199. 二叉树的右视图
层序遍历。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
queue<TreeNode*> que;
if (root != NULL) que.push(root);
vector<int> result;
while (!que.empty()) {
int size = que.size();
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
if (i == (size - 1)) result.push_back(node->val); // 将每一层的最后元素放入result数组中
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return result;
}
};
113. 路径总和 II
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> ret;
vector<int> path;
void dfs(TreeNode* root, int targetSum) {
if (root == nullptr) {
return;
}
path.emplace_back(root->val);
targetSum -= root->val;
if (root->left == nullptr && root->right == nullptr && targetSum == 0) {
ret.emplace_back(path);
}
dfs(root->left, targetSum);
dfs(root->right, targetSum);
path.pop_back();
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
dfs(root, targetSum);
return ret;
}
};
450. 删除二叉搜索树中的节点
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if (root == nullptr) {
return nullptr;
}
if (root->val > key) {
root->left = deleteNode(root->left, key);
return root;
}
if (root->val < key) {
root->right = deleteNode(root->right, key);
return root;
}
if (root->val == key) {
if (!root->left && !root->right) {
return nullptr;
}
if (!root->right) {
return root->left;
}
if (!root->left) {
return root->right;
}
TreeNode *successor = root->right;
while (successor->left) {
successor = successor->left;
}
root->right = deleteNode(root->right, successor->val);
successor->right = root->right;
successor->left = root->left;
return successor;
}
return root;
}
};
第十七天 树
230. 二叉搜索树中第K小的元素
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int kthSmallest(TreeNode* root, int k) {
stack<TreeNode *> stack;
while (root != nullptr || stack.size() > 0) {
while (root != nullptr) {
stack.push(root);
root = root->left;
}
root = stack.top();
stack.pop();
--k;
if (k == 0) {
break;
}
root = root->right;
}
return root->val;
}
};
173. 二叉搜索树迭代器
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class BSTIterator {
private:
TreeNode* cur;
stack<TreeNode*> stk;
public:
BSTIterator(TreeNode* root): cur(root) {}
int next() {
while (cur != nullptr) {
stk.push(cur);
cur = cur->left;
}
cur = stk.top();
stk.pop();
int ret = cur->val;
cur = cur->right;
return ret;
}
bool hasNext() {
return cur != nullptr || !stk.empty();
}
};
/**
* Your BSTIterator object will be instantiated and called as such:
* BSTIterator* obj = new BSTIterator(root);
* int param_1 = obj->next();
* bool param_2 = obj->hasNext();
*/
第十八天 树
236. 二叉树的最近公共祖先
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* ans;
bool dfs(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == nullptr) return false;
bool lson = dfs(root->left, p, q);
bool rson = dfs(root->right, p, q);
if ((lson && rson) || ((root->val == p->val || root->val == q->val) && (lson || rson))) {
ans = root;
}
return lson || rson || (root->val == p->val || root->val == q->val);
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
dfs(root, p, q);
return ans;
}
};
297. 二叉树的序列化与反序列化
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Codec {
public:
void rserialize(TreeNode* root, string& str) {
if (root == nullptr) {
str += "None,";
} else {
str += to_string(root->val) + ",";
rserialize(root->left, str);
rserialize(root->right, str);
}
}
string serialize(TreeNode* root) {
string ret;
rserialize(root, ret);
return ret;
}
TreeNode* rdeserialize(list<string>& dataArray) {
if (dataArray.front() == "None") {
dataArray.erase(dataArray.begin());
return nullptr;
}
TreeNode* root = new TreeNode(stoi(dataArray.front()));
dataArray.erase(dataArray.begin());
root->left = rdeserialize(dataArray);
root->right = rdeserialize(dataArray);
return root;
}
TreeNode* deserialize(string data) {
list<string> dataArray;
string str;
for (auto& ch : data) {
if (ch == ',') {
dataArray.push_back(str);
str.clear();
} else {
str.push_back(ch);
}
}
if (!str.empty()) {
dataArray.push_back(str);
str.clear();
}
return rdeserialize(dataArray);
}
};
// Your Codec object will be instantiated and called as such:
// Codec ser, deser;
// TreeNode* ans = deser.deserialize(ser.serialize(root));
第十九天 图
997. 找到小镇的法官
class Solution {
public:
int findJudge(int n, vector<vector<int>>& trust) {
vector<int> inDegrees(n + 1);
vector<int> outDegrees(n + 1);
for (auto& edge : trust) {
int x = edge[0], y = edge[1];
++inDegrees[y];
++outDegrees[x];
}
for (int i = 1; i <= n; ++i) {
if (inDegrees[i] == n - 1 && outDegrees[i] == 0) {
return i;
}
}
return -1;
}
};
1557. 可以到达所有点的最少点数目
class Solution {
public:
vector<int> findSmallestSetOfVertices(int n, vector<vector<int>>& edges) {
auto ans = vector<int>();
auto endSet = unordered_set<int>();
for (auto edge : edges) {
endSet.insert(edge[1]);
}
for (int i = 0; i < n; i++) {
if (endSet.find(i) == endSet.end()) {
ans.push_back(i);
}
}
return ans;
}
};
841. 钥匙和房间
class Solution {
public:
vector<int> vis;
int num;
void dfs(vector<vector<int>>& rooms, int x) {
vis[x] = true;
num++;
for (auto& it : rooms[x]) {
if (!vis[it]) {
dfs(rooms, it);
}
}
}
bool canVisitAllRooms(vector<vector<int>>& rooms) {
int n = rooms.size();
num = 0;
vis.resize(n);
dfs(rooms, 0);
return num == n;
}
};
第二十天 优先队列
215. 数组中的第K个最大元素
class Solution {
public:
int quickSelect(vector<int>& a, int l, int r, int index) {
int q = randomPartition(a, l, r);
if (q == index) {
return a[q];
} else {
return q < index ? quickSelect(a, q + 1, r, index) : quickSelect(a, l, q - 1, index);
}
}
inline int randomPartition(vector<int>& a, int l, int r) {
int i = rand() % (r - l + 1) + l;
swap(a[i], a[r]);
return partition(a, l, r);
}
inline int partition(vector<int>& a, int l, int r) {
int x = a[r], i = l - 1;
for (int j = l; j < r; ++j) {
if (a[j] <= x) {
swap(a[++i], a[j]);
}
}
swap(a[i + 1], a[r]);
return i + 1;
}
int findKthLargest(vector<int>& nums, int k) {
srand(time(0));
return quickSelect(nums, 0, nums.size() - 1, nums.size() - k);
}
};
347. 前 K 个高频元素
class Solution {
public:
static bool cmp(pair<int, int>& m, pair<int, int>& n) {
return m.second > n.second;
}
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> occurrences;
for (auto& v : nums) {
occurrences[v]++;
}
// pair 的第一个元素代表数组的值,第二个元素代表了该值出现的次数
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> q(cmp);
for (auto& [num, count] : occurrences) {
if (q.size() == k) {
if (q.top().second < count) {
q.pop();
q.emplace(num, count);
}
} else {
q.emplace(num, count);
}
}
vector<int> ret;
while (!q.empty()) {
ret.emplace_back(q.top().first);
q.pop();
}
return ret;
}
};
第21天 优先队列
451. 根据字符出现频率排序
class Solution {
public:
string frequencySort(string s) {
unordered_map<char, int> mp;
int length = s.length();
for (auto &ch : s) {
mp[ch]++;
}
vector<pair<char, int>> vec;
for (auto &it : mp) {
vec.emplace_back(it);
}
sort(vec.begin(), vec.end(), [](const pair<char, int> &a, const pair<char, int> &b) {
return a.second > b.second;
});
string ret;
for (auto &[ch, num] : vec) {
for (int i = 0; i < num; i++) {
ret.push_back(ch);
}
}
return ret;
}
};
973. 最接近原点的 K 个点
class Solution {
public:
vector<vector<int>> kClosest(vector<vector<int>>& points, int k) {
sort(points.begin(), points.end(), [](const vector<int>& u, const vector<int>& v) {
return u[0] * u[0] + u[1] * u[1] < v[0] * v[0] + v[1] * v[1];
});
return {points.begin(), points.begin() + k};
}
};