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相关推荐

  1. 卷进大厂系列之LeetCode刷题笔记:二分查找(简单)

    LeetCode刷题笔记:二分查找(简单) 学算法,刷力扣,加油卷,进大厂! 题目描述 涉及算法 题目解答 学算法,刷力扣,加油卷,进大厂! 题目描述 力扣题目链接 给定一个 n 个元素有序的(升序) ...

  2. LeetCode刷题笔记2——数组2

    LeetCode刷题笔记2--数组2 重塑数组 题目 在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原 ...

  3. 小何同学的leetcode刷题笔记 基础篇(01)整数反转

    小何同学的leetcode刷题笔记 基础篇(01)整数反转[07] *** [01]数学取余法*** 对数字进行数位操作时,常见的方法便是用取余的方法提取出各位数字,再进行操作 操作(1):对10取余 ...

  4. LeetCode刷题笔记汇总

    LeetCode刷题笔记汇总 第一次刷LeetCode写的一些笔记. 1.两数之和 3.无重复字符的最长子串 15.三数之和 18.四数之和 19.删除链表的倒数第 N 个结点 20.有效的括号 21 ...

  5. 【leetcode刷题笔记】动态规划

    #[leetcode刷题笔记]动态规划 石子游戏 public boolean stoneGame(int[] piles) {int N = piles.length;// dp[i][j] is ...

  6. LeetCode刷题笔记-动态规划-day4

    文章目录 LeetCode刷题笔记-动态规划-day4 55. 跳跃游戏 1.题目 2.解题思路 3.代码 45. 跳跃游戏 II 1.题目 2.解题思路 3.代码 LeetCode刷题笔记-动态规划 ...

  7. LeetCode刷题笔记- 15.三数之和

    LeetCode刷题笔记- 15.三数之和 C语言 题目 注意点 C语言 /*** Return an array of arrays of size *returnSize.* The sizes ...

  8. LeetCode刷题笔记第6题:Z字形变换

    LeetCode刷题笔记第6题:Z字形变换 想法: 要完成字符串根据给定的行数从上往下,从左到右完成Z字形排列.当只有一行时直接返回原字符串,当行数大于1时,先以行数构建一个行数数值个空字符串的列表, ...

  9. leetcode刷题笔记——二分查找

    leetcode刷题笔记--二分查找 目前完成的贪心相关的leetcode算法题序号: 中等:80,81 困难:4 来源:力扣(LeetCode) 链接:https://leetcode-cn.com ...

最新文章

  1. linux 根目录下的子目录的意义
  2. Linux下配置JAVA 环境变量及查看JDK安装路径
  3. SAP SOAMANAGER报错原因与故障排除方法
  4. HBase伪分布式集群配置
  5. linux应用开发:头文件和库文件的路径及使用
  6. mac lion 安装 mysql_mac osx下安装mysql
  7. scriptalert(1)/script
  8. 水晶报表从VS2008升级到VS2010 注意事项
  9. 07-图5 Saving James Bond - Hard Version
  10. popen函数的实现
  11. css带三角形的对话框
  12. php背景图片居中对齐命令,css怎么设置背景图片自适应居中
  13. 罗技G29方向盘linux下的开发
  14. 单个文件如何修改MD5
  15. matlab中ans的含义
  16. linux运行魔兽世界,暴雪内部就这么玩:Linux运行《魔兽世界》教程
  17. Unity3d场景渲染出图
  18. 【大学生数学建模竞赛时间一览表】
  19. 30 个 Python 的最佳实践、小贴士和技巧
  20. Meanshift 和 Camshift

热门文章

  1. 简单在线提取查看 清晰QQ头像的API 可以定义图片尺寸
  2. 【杂谈】如何通过目标职位确定学习路径和努力方向(拿测试工程师举例子)
  3. linux 轻量化图形界面,Linux轻量化桌面环境LXDE之时钟设置技巧
  4. Linux中$1、$@等含义是什么
  5. Android-利用动画实现背景逐渐变暗
  6. zip压缩包密码强制解除,zip压缩包复制打印限制如何解除?
  7. 计算机常见故障任务书,客车空调常见故障分析及处理设计毕业设计任务书
  8. Salesforce公司简介
  9. [Shader 着色器]冰霜效果的思考和实现
  10. 结巴分词关键词相似度_结巴分词5--关键词抽取