【机试c++】力扣题目练习合集
参考题单:LeetCode 热题 100
哈希表(unordered_map、unordered_set)
1. 两数之和
代码中的 x 不是一个 pair 对象,而是一个指针 / 迭代器(iterator),需要用->来调用。
如果是增强for循环遍历得到的就是pair对象,可以用.调用。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> a; // (数据,索引)
for(int i = 0;i < nums.size();i++){
auto x = a.find(target - nums[i]);
// mp.find(key); 查找key,返回迭代器,找不到返回end()
if(x != a.end()) return {x->second, i};
a[nums[i]] = i; // 放入map
}
return {};
}
};
49. 字母异位词分组
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
unordered_map<string, vector<string>> mp;
for(int i = 0;i < strs.size();i++){
string s = strs[i];
sort(s.begin(), s.end());
mp[s].push_back(strs[i]); // 键值对mp[s]是一个vector,将strs[i]加入这个vector
}
vector<vector<string>> ans;
for(pair<const string, vector<string>>& p : mp){
// 其中 key 必须是 const,因为 map 的 key 不能被你通过迭代器直接修改。
ans.push_back(p.second);
}
return ans;
}
};
128. 最长连续序列
如果有比 x 更小的数,那么在这个子序列里面,就还没有找到它的起始点。
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_set<int> a;
for(int x : nums) a.insert(x);
int ans = 0;
for(int x : a){
if(!a.count(x - 1)){ // 当前数最小,没有比它小的
int n = x;
while(a.count(n)) n++; // 找比x大的连续数,直到没有,此时n-1是最大的连续数
ans = max(ans, n - x); // 连续子序列长度为 n-1 - x + 1
}
}
return ans;
}
};
矩阵
54. 螺旋矩阵,蛇形矩阵
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
int d[4][2] = {{0,1},{1,0},{0,-1},{-1,0}}; // 右下左上
int n = matrix.size(); // 行
int m = matrix[0].size(); //列
int dis = 0; // 当前遍历方向
vector<int> ans(m * n);
int i = 0, j = 0;
for(int k = 0;k < m * n;k++){
ans[k] = matrix[i][j];
matrix[i][j] = INT_MAX;
int x = i + d[dis][0];
int y = j + d[dis][1]; // 判断这个方向是否超纲
if(x < 0 || x >= n || y < 0 || y >= m || matrix[x][y] == INT_MAX){
dis = (dis + 1) % 4; // 更新遍历方向
}
i += d[dis][0]; // 确认完方向之后,真正的更新坐标
j += d[dis][1];
}
// cout << INT_MAX; // 2147483647
return ans;
}
};
链表
ListNode* a = new ListNode(1);中new ListNode(1)返回的是指针,需要ListNode*接受。ListNode a(1);才是定义一个对象,赋值next的时候使用引用a.next = &b,赋值val使用a.val = 10。
160. 相交链表
参考题解:160. 相交链表(双指针,清晰图解)
简单来说,就是同时遍历两个链表,遍历完自己之后,遍历另外一个链表,直至两个链表节点相等,即为第一个公共节点。(天才想法,太厉害了)
- 如果两个链表有公共部分,则相遇时是第一个节点;
- 如果没有,则相遇时,两个遍历的节点将A、B两个链表都遍历完,
A == B == NULL。
/**
* 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) {
// 定义两个指针,不是重新创建两个节点。
// 使A、B 作为遍历指针,而不直接修改 headA、headB。
ListNode* A = headA;
ListNode* B = headB;
while(A != B){
A = (A == NULL) ? headB : A->next;
B = (B == NULL) ? headA : B->next;
}
return A;
}
};
206. 反转链表
/**
* 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:
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* curr = head;
while(curr){
ListNode* next = curr->next; // ① 先保存下一个节点
curr->next = prev; // ② 当前节点指向前一个节点
prev = curr; // ③ prev 向后移动(指向新链表的头节点)
curr = next; // ④ curr 向后移动(继续遍历原节点)
}
return prev;
}
};
234. 回文链表
/**
* 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:
bool isPalindrome(ListNode* head) {
// 快慢指针:找链表中间节点(用于给链表后半部分反转)
ListNode* slow = head, *fast = head;
while(fast && fast -> next){
slow = slow->next;
fast = fast->next->next;
}
// 反转链表后半部分
ListNode* pre = nullptr, *curr = slow;
while(curr){
ListNode* next = curr->next;
curr->next = pre;
pre = curr;
curr = next;
}
// 开始比较
ListNode* p1 = head, *p2 = pre;
while(p1 && p2){
if(p1->val != p2->val) return false;
p1 = p1->next;
p2 = p2->next;
}
return true;
}
};
141. 环形链表
环状链表快慢指针问题,
- 如果不存在环,那么fast先到链表结尾且始终不存在fast == slow,直到循环结束对吗
- 如果存在环,当fast先进入环中,一定会追赶上slow,最终二者相遇
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast && fast -> next){
slow = slow->next;
fast = fast->next->next;
if(slow == fast) return true;
}
return false;
}
};
写一个完整的自测试代码,注意
ListNode* a = new ListNode(1);中new ListNode(1)返回的是指针,需要ListNode*接受。ListNode a(1)才是定义一个对象,赋值next的时候使用引用a.next = &b,赋值val使用a.val = 10。
点击查看代码
#include <iostream>
using namespace std;
// 链表节点
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
// 判断链表是否有环
bool hasCycle(ListNode* head) {
ListNode* fast = head;
ListNode* slow = head;
while (fast && fast->next) {
slow = slow->next; // 慢指针走一步
fast = fast->next->next; // 快指针走两步
if (slow == fast) {
return true;
}
}
return false;
}
int main() {
// =========================
// 测试1:无环链表
// 1 -> 2 -> 3 -> 4 -> nullptr
// =========================
ListNode* a = new ListNode(1);
ListNode* b = new ListNode(2);
ListNode* c = new ListNode(3);
ListNode* d = new ListNode(4);
a->next = b;
b->next = c;
c->next = d;
d->next = nullptr;
cout << "测试1:";
cout << (hasCycle(a) ? "有环" : "无环") << endl;
// =========================
// 测试2:有环链表
// 1 -> 2 -> 3 -> 4
// ↑ ↓
// └────┘
// =========================
ListNode* e = new ListNode(1);
ListNode* f = new ListNode(2);
ListNode* g = new ListNode(3);
ListNode* h = new ListNode(4);
e->next = f;
f->next = g;
g->next = h;
h->next = g; // 4重新指向3,形成环
cout << "测试2:";
cout << (hasCycle(e) ? "有环" : "无环") << endl;
return 0;
}
142. 环形链表 II
题解:灵茶山艾府,天才!
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* slow = head;
ListNode* fast = head;
while(fast && fast -> next){
slow = slow->next;
fast = fast->next->next;
ListNode* head2 = head;
if(slow == fast){ // 和fast相遇后slow再走a步到入环点,head从头走a步到入环点,二者相遇
while(slow != head2){
slow = slow->next;
head2 = head2->next;
}
return slow;
}
}
return nullptr;
}
};
21. 合并两个有序链表
/**
* 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:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode* head = new ListNode(); // 头节点,head->next才是真正的第一个节点
ListNode* prev = head;
while(list1 != nullptr && list2 != nullptr){
if(list1->val < list2->val){
prev->next = list1;
list1 = list1->next;
}else{
prev->next = list2;
list2 = list2->next;
}
prev = prev->next; // 指向尾结点
}
// 直接将链表末尾指向未合并完的链表即可
prev->next = (list1 == nullptr) ? list2 : list1;
return head->next;
}
};
2. 两数相加
/**
* 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:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
// 类似大数加法
ListNode* head = new ListNode();
ListNode* curr = head;
int t = 0; // 进位
while(l1 || l2 || t){
int sum = t; //两数之和 + 进位
if(l1){
sum += l1->val;
l1 = l1->next;
}
if(l2){
sum += l2->val;
l2 = l2->next;
}
ListNode* node = new ListNode(sum % 10);
curr->next = node;
curr = curr->next;//遍历到新链表的尾部
t = sum / 10; // 保留进位
}
return head->next;
}
};
19. 删除链表的倒数第 N 个结点
向有一个指针走n步,然后新加入一个指针一起向下同速遍历,当第一个指针遍历到链表结束,第二个指针就到倒数第n个节点的前一个位置了。
由于可能会删除链表头部,所以新创建一个头节点,两个指针都从这个新头节点开始遍历,而不是从原头节点开始遍历。
/**
* 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:
ListNode* removeNthFromEnd(ListNode* head, int n) {
// 由于可能会删除链表头部,所以新创建一个头节点
ListNode* newHead = new ListNode();
newHead->next = head;
ListNode* first = newHead;
ListNode* second = newHead;
while(n--) first = first->next;
while(first->next){
first = first->next;
second = second->next;
}
// 此时已经到倒数第n+1个节点
ListNode* x = second->next;
second->next = second->next->next;
delete x;
return newHead->next;
}
};
24. 两两交换链表中的节点

法一
/**
* 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:
ListNode* swapPairs(ListNode* head) {
ListNode* newHead = new ListNode(0, head); // val没有用,next指向head
ListNode* n0 = newHead;
ListNode* n1 = head;
while(n1 && n1->next){
ListNode* n2 = n1->next;
ListNode* n3 = n2->next;
n0->next = n2;
n2->next = n1;
n1->next = n3; // 由于上一行n2->next已经更新,所以需要用n3记录原n2->next
// 节点位置变化:n0 n1 n2 (n3) → n0 n2 n1 (n3)
n0 = n1; // 向下移动两个节点
n1 = n3;
}
return newHead->next;
}
};
法二
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* newHead = new ListNode(0, head); // val没有用,next指向head
ListNode* n0 = newHead;
ListNode* n1 = head;
while(n1 && n1->next){
ListNode* n3 = n1->next->next;
n0->next = n1->next;
n1->next->next = n1;
n1->next = n3; // 由于上一行n2->next已经更新,所以需要用n3记录原n2->next
// 节点位置变化:n0 n1 n2 (n3) → n0 n2 n1 (n3)
n0 = n1; // 向下移动两个节点
n1 = n3;
}
return newHead->next;
}
};
138. 随机链表的复制
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
// 复制每个节点,把新节点直接插到原节点的后面
for(Node* cur = head;cur;cur = cur->next->next){
cur->next = new Node(cur->val, cur->next,nullptr);
}
// 遍历交错链表中的原链表节点
for(Node* cur = head;cur;cur = cur->next->next){
// 要复制的 random 是 cur->random 的下一个节点
if(cur->random) cur->next->random = cur->random->next;
}
// 把交错链表分离成两个链表
Node* newHead = new Node(0);
Node* t = newHead;
for(Node* cur = head;cur;cur = cur->next, t = t->next){
Node* copy = cur->next;//复制的新节点
t->next = copy; // 把新节点插在 t 的后面,构建新的链表
cur->next = copy->next; // 恢复原节点的 next
}
return newHead->next;
}
};
25. K 个一组翻转链表

/**
* 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:
ListNode* reverseKGroup(ListNode* head, int k) {
int n = 0;
for(ListNode* cur = head;cur;cur = cur->next) n++;
ListNode* nh = new ListNode(0, head);
ListNode* tail = nh; // 每组数的前一个节点(上一组的尾结点)
for(int i = 0;n - i >= k;i += k){
ListNode* pre = nullptr;
ListNode* cur = tail->next; // 下一组k个节点的前一个
// k个节点的反转
for(int j = 0;j < k;j++){
ListNode* next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
// 此时,cur 是下一组的起始节点,pre 是当前组的头节点
ListNode* t = tail->next; // 存一下当前组的尾结点(反转前的头节点)
tail->next->next = cur; // 将反转后的当前组的尾结点接到下一组上
tail->next = pre; // 将上一组的尾结点接到反转后的当前组的头节点上
tail = t; // 更新下一组的前一个节点,用于下次遍历找到下一组的头节点
}
return nh->next;
}
};
二叉树
94. 二叉树的中序遍历【三种遍历】
三种遍历方式的方法类似,只需要改变递归函数中三个语句的顺序
- 先序遍历:根左右
- 中序遍历:左根右
- 后序遍历:左右根
/**
* 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:
void inoreder(TreeNode* root, vector<int>& ans){
if(!root) return;
// 左右根
inoreder(root->left, ans);
ans.push_back(root->val);
inoreder(root->right, ans);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ans;
inoreder(root, ans);
return ans;
}
};
104. 二叉树的最大深度
/**
* 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 maxDepth(TreeNode* root) {
if(!root) return 0;
return max(maxDepth(root->left) + 1, maxDepth(root->right) + 1);
}
};
226. 翻转二叉树
/**
* 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* invertTree(TreeNode* root) {
if(!root) return nullptr;
TreeNode* l = invertTree(root->left);
TreeNode* r = invertTree(root->right);
root->left = r;
root->right = l;
return root;
}
};
101. 对称二叉树
/**
* 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:
bool check(TreeNode* l, TreeNode* r){
if(!l && !r) return true; // 都不存在
if(l && r && l->val == r->val) // 都存在且值相等,继续遍历左右子树
return check(l->left, r->right) && check(l->right, r->left);
return false;
}
bool isSymmetric(TreeNode* root) {
return check(root->left, root->right);
}
};
543. 二叉树的直径
/**
* 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 ans = 0;
int dfs(TreeNode* root){
if(!root) return -1; // 对于叶子来说,左、右链长都是 -1+1=0
// 这里的长度实际上是按照边数计算的。
int l_len = dfs(root->left) + 1;
int r_len = dfs(root->right) + 1;
ans = max(ans, l_len + r_len); // 两条链拼成路径
return max(l_len, r_len); // 当前子树最大链长
}
int diameterOfBinaryTree(TreeNode* root) {
dfs(root);
return ans;
}
};
102. 二叉树的层序遍历
/**
* 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>> levelOrder(TreeNode* root) {
vector<vector<int>> ans;
if(!root) return ans;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
vector<int> level;
int n = q.size();
while(n-- > 0){
TreeNode* t = q.front();
q.pop();
level.push_back(t->val);
if(t->left) q.push(t->left);
if(t->right) q.push(t->right);
}
ans.push_back(level);
}
return ans;
}
};
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 {
public:
unordered_map<int, int> mp;// 记录每个节点在中序遍历中的索引
TreeNode* buid(const vector<int>& preorder, const vector<int>& inorder,
int preStart, int preEnd, int inStart, int inEnd){
// 前序、中序的起始节点作为参数
if(preStart > preEnd) return nullptr;
int root = preorder[preStart]; // 前序的根节点就是整个二叉树的根节点
int index = mp[root]; // 获取根节点在中序遍历中的位置
TreeNode* ans = new TreeNode(root); // 创建根节点
int left = index - inStart; // 左子树长度(节点个数)
int right = inEnd - index; // 右子树长度(节点个数)
// 找左子树的根节点
ans->left = buid(preorder, inorder, preStart + 1, preStart + left, inStart, index - 1);
// 找右子树的根节点
ans->right = buid(preorder, inorder, preStart + left + 1, preEnd, index + 1, inEnd);
return ans;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
for(int i = 0;i < inorder.size();i++){
mp[inorder[i]] = i; // 键值对为 (数据,索引)
}
return buid(preorder, inorder, 0, preorder.size() - 1, 0, inorder.size() - 1);
}
};
后序 + 中序 → 构造
class Solution {
public:
unordered_map<int, int> mp;// 记录每个节点在中序遍历中的索引
TreeNode* buid(const vector<int>& postorder, const vector<int>& inorder,
int postStart, int postEnd, int inStart, int inEnd){
// 后序、中序的起始节点作为参数
if(postStart > postEnd) return nullptr;
int root = postorder[postEnd]; // 后序的最后一个节点就是整个二叉树的根节点
int index = mp[root]; // 获取根节点在中序遍历中的位置
TreeNode* ans = new TreeNode(root); // 创建根节点
int left = index - inStart; // 左子树长度(节点个数)
int right = inEnd - index; // 右子树长度(节点个数)
// 找左子树的根节点
ans->left = buid(postorder, inorder, postStart, postStart + left - 1, inStart, index - 1);
// 找右子树的根节点
ans->right = buid(postorder, inorder, postStart + left, postEnd - 1, index + 1, inEnd);
return ans;
}
TreeNode* buildTree(vector<int>& postorder, vector<int>& inorder) {
for(int i = 0;i < inorder.size();i++){
mp[inorder[i]] = i; // 键值对为 (数据,索引)
}
return buid(postorder, inorder, 0, postorder.size() - 1, 0, inorder.size() - 1);
}
};
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:
// 把数组 [left, right - 1] 转成平衡二叉搜索树
TreeNode* dfs(vector<int>& nums, int left, int right){
if(left == right) return nullptr;
int mid = (left + right) / 2; // 取中间值做根节点
return new TreeNode(nums[mid], dfs(nums, left, mid), dfs(nums, mid + 1, right));
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
// 二叉搜索树:小的放左节点,大的放右节点
// 平衡 二叉搜索树:取有序数组的中位数做根节点
return dfs(nums, 0, nums.size());
}
};
动态规划
198. 打家劫舍【线性DP】

class Solution {
public:
int rob(vector<int>& nums) {
if(nums.size() == 0) return 0;
// f(k) = 偷 [0, k-1] 房间中的最大金额
// f(0) = 0, f(1) = nums[0]
// f(k) = max{ rob(k-1), nums[k-1] + rob(k-2) }
vector<int> dp;
dp.push_back(0);
dp.push_back(nums[0]);
for(int i = 2;i <= nums.size();i++){
dp.push_back(max(dp[i - 1], dp[i - 2] + nums[i - 1]));
}
return dp[nums.size()];
}
};
可以直接定义dp数组大小,并初始化为0。
class Solution {
public:
int rob(vector<int>& nums) {
if(nums.size() == 0) return 0;
// f(k) = 偷 [0, k-1] 房间中的最大金额
// f(0) = 0, f(1) = nums[0]
// f(k) = max{ rob(k-1), nums[k-1] + rob(k-2) }
int n = nums.size();
vector<int> dp(n + 1, 0);
dp[0] = 0;
dp[1] = nums[0];
for(int i = 2;i <= nums.size();i++){
dp[i] = max(dp[i - 1], dp[i - 2] + nums[i - 1]);
}
return dp[n];
}
};
53. 最大子数组和
class Solution {
public:
int maxSubArray(vector<int>& nums) {
vector<int> dp(nums.size());
dp[0] = nums[0];
for(int i = 1;i < nums.size();i++){
dp[i] = max(dp[i - 1], 0) + nums[i];// 要么就前半部分加上自己,要么只要自己
}
int ans = -1e9;
for(int x : dp) ans = max(ans, x);
return ans;
}
};
152. 乘积最大子数组
维护两个dp数组,一个是最大值,一个是最小值,因为有负负得正的可能,所以最小的数乘以一个负数可能得到最大的数,所以需要记录一个dp_min。
class Solution {
public:
int maxProduct(vector<int>& nums) {
vector<int> dp_max(nums.size()), dp_min(nums.size());
dp_max[0] = nums[0], dp_min[0] = nums[0];
for(int i = 1;i < nums.size();i++){
int x = nums[i];
dp_max[i] = max({dp_max[i - 1] * x, dp_min[i - 1] * x, x});
dp_min[i] = min({dp_max[i - 1] * x, dp_min[i - 1] * x, x});
}
int ans = -1e9;
for(int x : dp_max) ans = max(ans, x);
return ans;
}
};
补充题目
求二叉树第K层的度不为1的结点个数
#include <iostream>
#include <queue>
using namespace std;
struct TreeNode{
char val;
TreeNode * left, * right;
TreeNode(char c){
val = c;
left = NULL;
right = NULL;
}
};
int count(TreeNode * root, int k){
if(root == NULL) return 0;
queue<TreeNode*> q;
q.push(root);
int level = 1;
int ans = 0;
while(!q.empty()){
int n = q.size();
if(level < k){
for(int i = 0;i < n;i++){
TreeNode* t = q.front();
q.pop();
if(t->left != NULL) q.push(t->left);
if(t->right != NULL) q.push(t->right);
}
level++;
}else if(k == level){
for(int i = 0;i < n;i++){
TreeNode* t = q.front();
q.pop();
int x = 0;
if(t->left != NULL) x++;
if(t->right != NULL) x++;
if(x != 1) ans++;
}
return ans;
}
}
return 0;
}
int main() {
// 构造二叉树
TreeNode* root = new TreeNode('A');
root->left = new TreeNode('B');
root->right = new TreeNode('C');
root->left->left = new TreeNode('D');
root->left->right = new TreeNode('E');
root->right->right = new TreeNode('F');
root->left->right->left = new TreeNode('G');
cout << count(root,3);
return 0;
}

浙公网安备 33010602011771号