LeetCode刷题笔记_20210926
1. 判断计数/偶数写法:
相关题目:《剑指 Offer 21. 调整数组顺序使奇数位于偶数前面》
https://leetcode-cn.com/problems/diao-zheng-shu-zu-shun-xu-shi-qi-shu-wei-yu-ou-shu-qian-mian-lcof/
常规写法: 取模(对2取模)
if( i % 2 != 0 ) //奇数
if( i% 2 == 0 ) //偶数
优化写法: 位运算(用1与运算)
if( i & 1 == 1 )
if( i & 1 == 0 )
位运算的效率高于取模运算。
2. 移位操作“>>”:
相应题目:《剑指 Offer 15. 二进制中1的个数》
https://leetcode-cn.com/problems/er-jin-zhi-zhong-1de-ge-shu-lcof/solution/
2.1 关于移位运算符“>>”的一个低级错误:
想要对一个无符号整数要进行移位操作,
正确的写法是:
n = n >> 1;
或者:
n >>= 1;
错误的写法:
n >> 1;
这样的写法就相当于是一个 表达式 直接放在了这里,并没有更新n的值:
n + 1;
2.2 形参的值也是可以修改的:
void func(int n) {cout << n; //n = 5; 打印的是传入的实参的值n = 6;cout << n; //n = 6; 形参的值被修改,打印的是修改后的值
}int main() {func(5);return 0;
}
总结:
遇到一些求解“二进制”相关的问题(比如求某个整数中的 0 / 1 比特的个数),首先想到的方法就是 移位操作。
3. 经典问题:反转单向链表:
相关题目:《剑指 Offer 24. 反转链表》
https://leetcode-cn.com/problems/fan-zhuan-lian-biao-lcof/
方法一:递归法:
class Solution {public:ListNode* reverseList(ListNode* head) {if(head == nullptr || head->next == nullptr) return head;ListNode* newHead = reverseList(head->next); //newHead只有在最后一层递归才会赋值,并一路返回,成为最终结果head->next->next = head;head->next = nullptr; //这一步是为了防止表成环return newHead;}
};
方法二:迭代法:
class Solution {public:ListNode* reverseList(ListNode* head) {ListNode* cur = head;ListNode* prev = nullptr;while(cur) {ListNode* next = cur->next;cur->next = prev;prev = cur;cur = next;}return prev;}
};
4. unordered_map的count与find方法:
相关题目:《剑指 Offer 39. 数组中出现次数超过一半的数字》
https://leetcode-cn.com/problems/shu-zu-zhong-chu-xian-ci-shu-chao-guo-yi-ban-de-shu-zi-lcof/
计算map中对应某个key的元素个数,使用count方法。
map类型中就两个方法比价特殊,与其他的STL类不同:
一个是 map.find(key);, 一个是 map.count(key);。
map.find(key);
map.count(key);
另外,在算法题中,不要求元素有序的地方就用 unordered_map 代替 map。
5. 快速排序:
快速排序的基本思想是:
通过一趟排序将数组分割成独立的两部分,其中一部分的元素的值均比另一部分的元素的值小;然后再对这两个细分的区间进行排序,以达到整个数组有序。
快速排序是工程代码中使用的最多的,使用的是 分治 思想。
快速排序在这几个 O(N*log(N)) 的排序算法中也是效率最高的。
class Solution {public:void quickSort(vector<int>& nums, int begin, int end) {if(begin >= end) return; //terminatorint pivot = partition(nums, begin, end); //process current layerquickSort(nums, begin, pivot - 1); //drill downquickSort(nums, pivot + 1, end);}int partition(vector<int>& nums, int begin, int end) {int counter = begin;int pivot = end;for(int i = begin; i < end; ++i) {if(nums[i] < nums[pivot]) {swap(nums[i], nums[counter++]); //快慢指针 //counter的目标是counter以前都是比nums[pivot]小的元素}}swap(nums[counter], nums[pivot]);return counter;}
};
6. 归并排序:
归并和快排具有相似性,但步骤顺序相反。
归并:先排序左右子序列,然后合并两个有序子数组;
快排:先调配出左右子数组,然后对于左右子数组记性排序(分治)。
class Solution {public: void mergeSort(vector<int>& nums, int begin, int end) {if(begin >= end) return ; //terminatorint mid = begin + (end - begin) / 2;mergeSort(nums, begin, mid); //drill downmergeSort(nums, mid + 1, end);mergeArray(nums, begin, mid, end);}void mergeArray(vector<int>& nums, int begin, int mid, int end) {vector<int> temp;temp.resize(end - begin + 1);int i = begin, m = mid; //第一部分int j = mid + 1, n = end; //第二部分int k = 0;while(i <= m && j <= n) {temp[k++] = nums[i] < nums[j] ? nums[i++] : nums[j++];} while(i <= m) {temp[k++] = nums[i++];} while(j <= n) {temp[k++] = nums[j++];}for(int i = 0; i < k; ++i) {nums[begin + i] = temp[i];}}
};
7. 冒泡排序怎么写:
void bubbleSort(vector<int>& nums) {for(int i = 0; i < nums.size(); i++) {for(int j = i + 1; j < nums.size(); j++) {if(nums[j] < nums[i]) {swap(nums[i], nums[j]);}}}
}
8. 使用迭代器直接初始化vector时是尾后迭代器:
相关题目:《剑指 Offer 40. 最小的k个数》
https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/
STL中的vector容器类型 支持使用另一个容器的范围迭代器的方式直接初始化,例如下面的例子:
int main() {vector<int> array;vector<int> ret(arr.begin(), arr.begin() + k);
}
需要注意的是: 在直接初始化的操作中,迭代器同样是 “尾后迭代器”,即初始化的真正范围是 从 ( arr.begin()) 到 (arr.begin() + k - 1)
,不包括 第k个元素。
同理,使用数组进行直接初始化时也是相同的原理:
int main() {int array[] = {1,2,3,4};vector<int> vec(array, array + sizeof(array)/sizeof(int));
}
9. 二叉树的遍历:
相关题目:剑指 Offer 32 - II. 从上到下打印二叉树 II
https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof/
为什么要遍历二叉树?
就像是遍历数组、遍历链表一样,唯一的目的就是数据结构中 查找 某个元素。
遍历数组、链表都很简单,使用指针和迭代器从前向后遍历整个数组/链表即可,这是因为它们是 “一维” 的存储结构,或者形象的说是线性的数据结构。
而二叉树(N叉树)的结构不是线性的,因此就不可能像数组和链表那样的方式进行遍历、查找。
对于某一组数据的搜索,除非这个数据结构支持特定的查找操作(例如unordered_map的查找根据哈希公式找到对一个位置,时间复杂度是O(1)),否则就要使用 遍历 的方式进行搜索。
对于树这种数据结构的遍历,有这样几种方式:
前序遍历、中序遍历、后序遍历,这些都是 “深度优先遍历”;
层序遍历,这个是 “广度优先遍历”。
9.1 深度优先遍历 和 广度优先遍历:
根据对树中节点的访问顺序的不同,将树的遍历分为“深度优先遍历”和“广度优先遍历”,或者说叫 “深度优先搜索”(DFS,Depth First Search)和“广度优先搜索”(BFS,Breadth First Search)。
深度优先遍历的写法:“栈(迭代法)” 或 “递归法”;
广度优先遍历的写法:“队列(迭代法)”。
9.1.1 深度优先遍历的写法模板:
方法一:迭代法:(根左右)
深度优先遍历的迭代法中使用了 “回溯” 的思想。
所谓 “回溯”,就是在遍历的时候,就给自己留好退路(回溯点),当这条路走到尽头,可以直接跳转到回溯点。
在深度优先遍历中每个入栈的right右节点就是回溯点。
树节点的定义:
typedef struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int n) : val(n) {}TreeNode(int n, TreeNode* l, TreeNode* r) : val(n), left(l), right(r) {}
} TreeNode;
一个“根左右”顺序的DFS遍历:(如果需要“左右根”或者“左根右”的遍历顺序,调整一下推入vector的顺序即可)
vector<int> binaryTreeDfs(TreeNode* root) {vector<int> result; //保存结果stack<TreeNode*> s;s.push(root);while(!s.empty()) {TreeNode* cur = s.top();s.pop();result.push_back(cur->val);if(cur->right)s.push(cur->right); //回溯点if(cur->left)s.push(cur->left);}return result;
}
方法二:递归法:
(根左右)
vector<int> result;
void binaryTreeDfs(TreeNode* root) {travelTree(root);return;
}void travelTree(TreeNode* root) {if(!root) return;result.push_back(root->val);travelTree(root->left);travelTree(root->right);
}
上面的递归例子中,result.push_back(val) 放在两个递归函数的中间就是“左根右”,放在两个递归函数的后面就是“左右根”。
9.1.2 广度优先遍历的写法模板:
一个广度优先遍历的代码模板:
关键点在于使用一个 队列。
vector<int> binaryTreeBfs(TreeNode* root) {vector<int> result;queue<TreeNode*> q;q.push(root);while(!q.empty()) {TreeNode* cur = q.front();q.pop();result.push_back(cur->val);if(cur->left) q.push(cur->left);if(cur->right)q.push(cur->right);}return result;
}
9.1.3 广度优先遍历的按层打印:
广度优先遍历的一个变种是“按层打印”,这种问题需要再额外的借助一个for循环,每次按照 queue.size()
进行循环处理一层。
有一点需要注意的是 for中的循环条件 queue.size 需要另外保存在一个局部变量中,因为在for循环体内会修改循环条件。
class Solution {public:vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> result;if(root == nullptr) return result;queue<TreeNode*> q;q.push(root);while(!q.empty()) {result.push_back(vector<int>()); //先推一个空的vector进去int curQueueSize = q.size(); //切记:在for【循环体内】如果有改变【循环条件】的操作,那就应该在进入for循环前使用一个临时变量将这个循环条件保存下来。这与“迭代器失效”的原理是一样的for(int i = 0; i < curQueueSize; ++i) {TreeNode* cur = q.front();q.pop();result.back().push_back(cur->val);if(cur->left)q.push(cur->left);if(cur->right)q.push(cur->right);}} return result;}
};
LeetCode刷题笔记_20210926相关推荐
- 卷进大厂系列之LeetCode刷题笔记:二分查找(简单)
LeetCode刷题笔记:二分查找(简单) 学算法,刷力扣,加油卷,进大厂! 题目描述 涉及算法 题目解答 学算法,刷力扣,加油卷,进大厂! 题目描述 力扣题目链接 给定一个 n 个元素有序的(升序) ...
- LeetCode刷题笔记2——数组2
LeetCode刷题笔记2--数组2 重塑数组 题目 在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原 ...
- 小何同学的leetcode刷题笔记 基础篇(01)整数反转
小何同学的leetcode刷题笔记 基础篇(01)整数反转[07] *** [01]数学取余法*** 对数字进行数位操作时,常见的方法便是用取余的方法提取出各位数字,再进行操作 操作(1):对10取余 ...
- LeetCode刷题笔记汇总
LeetCode刷题笔记汇总 第一次刷LeetCode写的一些笔记. 1.两数之和 3.无重复字符的最长子串 15.三数之和 18.四数之和 19.删除链表的倒数第 N 个结点 20.有效的括号 21 ...
- 【leetcode刷题笔记】动态规划
#[leetcode刷题笔记]动态规划 石子游戏 public boolean stoneGame(int[] piles) {int N = piles.length;// dp[i][j] is ...
- LeetCode刷题笔记-动态规划-day4
文章目录 LeetCode刷题笔记-动态规划-day4 55. 跳跃游戏 1.题目 2.解题思路 3.代码 45. 跳跃游戏 II 1.题目 2.解题思路 3.代码 LeetCode刷题笔记-动态规划 ...
- LeetCode刷题笔记- 15.三数之和
LeetCode刷题笔记- 15.三数之和 C语言 题目 注意点 C语言 /*** Return an array of arrays of size *returnSize.* The sizes ...
- LeetCode刷题笔记第6题:Z字形变换
LeetCode刷题笔记第6题:Z字形变换 想法: 要完成字符串根据给定的行数从上往下,从左到右完成Z字形排列.当只有一行时直接返回原字符串,当行数大于1时,先以行数构建一个行数数值个空字符串的列表, ...
- leetcode刷题笔记——二分查找
leetcode刷题笔记--二分查找 目前完成的贪心相关的leetcode算法题序号: 中等:80,81 困难:4 来源:力扣(LeetCode) 链接:https://leetcode-cn.com ...
最新文章
- linux 根目录下的子目录的意义
- Linux下配置JAVA 环境变量及查看JDK安装路径
- SAP SOAMANAGER报错原因与故障排除方法
- HBase伪分布式集群配置
- linux应用开发:头文件和库文件的路径及使用
- mac lion 安装 mysql_mac osx下安装mysql
- scriptalert(1)/script
- 水晶报表从VS2008升级到VS2010 注意事项
- 07-图5 Saving James Bond - Hard Version
- popen函数的实现
- css带三角形的对话框
- php背景图片居中对齐命令,css怎么设置背景图片自适应居中
- 罗技G29方向盘linux下的开发
- 单个文件如何修改MD5
- matlab中ans的含义
- linux运行魔兽世界,暴雪内部就这么玩:Linux运行《魔兽世界》教程
- Unity3d场景渲染出图
- 【大学生数学建模竞赛时间一览表】
- 30 个 Python 的最佳实践、小贴士和技巧
- Meanshift 和 Camshift
热门文章
- 简单在线提取查看 清晰QQ头像的API 可以定义图片尺寸
- 【杂谈】如何通过目标职位确定学习路径和努力方向(拿测试工程师举例子)
- linux 轻量化图形界面,Linux轻量化桌面环境LXDE之时钟设置技巧
- Linux中$1、$@等含义是什么
- Android-利用动画实现背景逐渐变暗
- zip压缩包密码强制解除,zip压缩包复制打印限制如何解除?
- 计算机常见故障任务书,客车空调常见故障分析及处理设计毕业设计任务书
- Salesforce公司简介
- [Shader 着色器]冰霜效果的思考和实现
- 结巴分词关键词相似度_结巴分词5--关键词抽取