文章目录
剑指 Offer 35. 复杂链表的复制
- 错在,把新链表结点的random赋值到了就链表结点
- 看了思路后,还是错了,错在边赋值变拆分
- 思路1:用哈希表,unordered_map(Node*, Node*)map
时间复杂度 O(N) : 两轮遍历链表,使用 O(N)O(N) 时间。
空间复杂度 O(N) : 哈希表 dic 使用线性大小的额外空间。 - 思路2:在旧结点后面插入创建的新节点,然后再给random赋值,最后再拆分时间
复杂度 O(N): 三轮遍历链表,使用 O(N)O(N) 时间。
空间复杂度 O(1): 节点引用变量使用常数大小的额外空间。
/*
// 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) {
if (head == nullptr) return nullptr;
Node* cur = head;
// 构建一条新链表
while (cur) {
// 创建一个新的结点
Node* temp = new Node(cur->val);
// 有个问题啊,我后面的结点还没创建呢。。
// wrong temp->next = cur->next;
// worng temp->random = cur->random;
temp->next = cur->next;
cur->next = temp;
cur = temp->next;
}
cur = head;
while (cur) {
if(cur->random) {
cur->next->random = cur->random->next;
}
cur = cur->next->next;
}
// 重新遍历,再赋值random,
// 错在不能将random赋值到旧的链表上
// A-a-B-b
// 错在边赋值,变拆分。。
cur = head;
Node* newHead = head->next;
Node* p = newHead;
while(cur) {
cur->next = p->next;
if (cur->next == nullptr) {
break;
}
p->next = p->next->next;
cur = cur->next;
p = p->next;
}
return newHead;
}
};
剑指 Offer 47. 礼物的最大价值
- 错在初始化出了问题或者说是没把i==0,j==0的情况考虑清楚
class Solution {
public:
int maxValue(vector<vector<int>>& grid) {
/*
当 i = 0 且 j = 0 时,为起始元素;
当 i = 0 且 j != 0 时,为矩阵第一行元素,只可从左边到达;
当 i != 0 且 j = 0 时,为矩阵第一列元素,只可从上边到达
当 i != 0 且 j != 0 时,可从左边或上边到达
*/
int m = grid.size();
int n = grid[0].size();
if (m == 0 || n == 0) return 0;
// 初始化出了问题
// 错 把0行、 0列 的初始成了和grid一样的
vector<vector<int>> dp(m, vector<int>(n));
dp[0][0] = grid[0][0];
for (int i = 1; i < m; ++i) {
dp[i][0] = grid[i][0] + dp[i - 1][0] ;
}
for (int j = 1; j < n; ++j) {
dp[0][j] = grid[0][j] + dp[0][j - 1];
}
for (int i = 1; i < m; ++i) {
for (int j = 1; j < n; ++j) {
dp[i][j] = max (dp[i - 1][j], dp[i][j - 1])+ grid[i][j];
}
}
return dp[m-1][n-1] ;
}
};
位运算
剑指 Offer 65. 不用加减乘除做加法
class Solution {
public:
int add(int a, int b) {
// 不进位相当于 异或
// 进位相当于 与 再左移1位
// 注意负数不能左移,累加也是加。。
while (b != 0) {
int c = (unsigned(a & b) << 1);
a = a ^ b;
b = c;
}
return a;
}
};
剑指 Offer 56 - I. 数组中数字出现的次数
class Solution {
public:
vector<int> singleNumbers(vector<int>& nums) {
// O(1)空间复杂度,说明没有另外申请空间,
// 思路:先拍个序,但是排序算法好像没有O(n)复杂度的
// 没有想到合适的O(n)方案。。。
// 然后回头看这个题,要求这么高,原来是位运算~~~
// 分组,确定不同的两个数字的位,然后通过这个位来区分组
// 注意,运算符的优先级,&低于==
int x = 0;
for (auto n : nums) {
x ^= n;
}
int map = 1;
while ((x & map) == 0) {
map <<= 1;
}
int a = 0, b = 0;
for (auto i : nums) {
if ((i & map) == 0) {
a ^= i;
} else {
b ^= i;
}
}
return vector<int>{a, b};
}
};
剑指 Offer 39. 数组中出现次数超过
- 法1,哈希表
- 法2,排序
- 法3,随机
剑指 Offer 66. 构建乘积数组
- 通过构建左右乘积列表
- 注意为空的情况
剑指 Offer 20. 表示数值的字符串
- 把状态转移画出来
- 然后通过unordered_map<State, unordered_map<CharType, State>> 状态转移
- 确定终止态
剑指 Offer 67. 把字符串转换成整数
- long 类型和 int 一样所占字节数为:4,是一个32位的存储单元。
long long类型所占字节数为:8,是一个64位的存储单元。 - ans 和(long long )INT_MAX 、-(long long) INT_MIN 取最小值
-最后处理符号
剑指 Offer 59 - I. 滑动窗口的最大值
法1
- 双端队列 deque,维护从大到小,
- 每次将队头存入结果集
- 每次入队的要保证队内是递减的
- 并且要维持队首的下标要在窗口内
法2
- priority_que优先队列,自动构建一个从大到小的队列。(大根堆)
剑指 Offer 37. 序列化二叉树
- 层次遍历,
- 序列化时,注意ostringstream 需要分空和非空的情况
/**
* 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:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
// 首先判断空
if (root == NULL) return "";
// 利用层次遍历,将所得保存在string里
queue<TreeNode*> bfs;
bfs.push(root);
ostringstream out;
while (!bfs.empty()) {
// 获取队头
TreeNode* temp = bfs.front();
// pop
bfs.pop();
// push
if (temp != NULL) {
out << temp->val << " ";
bfs.push(temp->left);
bfs.push(temp->right);
}
else {
out << "null ";
}
}
return out.str();
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
// 首先判断空
if (data.empty()) return NULL;
// 将data以空格为分隔,存入到集合
istringstream in(data);
string node;
vector<TreeNode*> str;
while (in >> node) {
if (node == "null")
str.push_back(NULL);
else {
str.push_back(new TreeNode(stoi(node)));
}
}
// 利用层次遍历构造二叉树
queue<TreeNode*> bfs;
// root
TreeNode* root = str[0];
bfs.push(root);
int i = 1;
while (!bfs.empty()) {
TreeNode* temp = bfs.front();
bfs.pop();
if (str[i] != NULL) {
temp->left = str[i];
bfs.push(temp->left);
}
i++;
if (str[i] != NULL) {
temp->right = str[i];
bfs.push(temp->right);
}
i++;
}
return root;
}
};
// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));