408算法题

提示:代码C++,部分引用自leetcode


文章目录

  • 408算法题
  • 一、链表
    • 1.1链表逆置
    • 1.2删除链表倒数第n个结点
    • 1.3 给定两个增序的链表,试将其合并成一个增序的链表。
    • 1.4 删除有序(递增)链表中的重复元素。
    • 1.5 以 O(1) 的空间复杂度,判断链表是否回文。
    • 1.6 已排序链表,删除所有重复元素(保留一个)
    • 1.7 给定两个链表,判断它们是否相交于一点,并求这个相交节点。
  • 二、栈与队列
  • 三、树与二叉树
    • 3.1 [递归]二叉树的深度
    • 3.2 [递归][树的判定]翻转平衡二叉树
    • 3.3 [递归][树的判定]平衡二叉树的判定
    • 3.4 [递归]二叉树的直径
    • 3.5 [双递归]二叉树的路径总和
    • 3.6 [递归]判断一个二叉树是否对称
    • 3.7 [遍历][递归]二叉树的前中后序遍历
    • 3.8 [遍历][迭代]二叉树的前序遍历
    • 3.9 [遍历]二叉树的层序遍历
  • 四、图(考的较少)
  • 五、排序
    • 5.1 [插入类]直接插入排序
    • 5.2 [插入类]希尔排序
    • 5.3 [交换类]冒泡排序
    • 5.3 [交换类]快排
    • 5.4 [选择类]简单选择
    • 5.5 归并排序(个人觉得会考)
  • 总结

提示:以下是本篇文章正文内容,下面案例可供参考

一、链表

1.1链表逆置

方法1.迭代

class Solution {public:ListNode* reverseList(ListNode* head) {ListNode* prev = nullptr;ListNode* curr = head;while (curr) {ListNode* next = curr->next;curr->next = prev;prev = curr;curr = next;}return prev;}
};

方法2.递归

class Solution {public:ListNode* reverseList(ListNode* head) {if (!head || !head->next) {return head;}ListNode* newHead = reverseList(head->next);head->next->next = head;head->next = nullptr;return newHead;}
};

1.2删除链表倒数第n个结点

方法1:双指针,使用快慢指针

//哑结点其实就是放在第一个存放数据结点之前、头结点之后的结点。加入哑结点之后就可以使所有数据结点都有前驱结点,这样就会方便执行链表的一些操作(比如删除)

class Solution {public:ListNode* removeNthFromEnd(ListNode* head, int n) {//在头结点之前设置哑结点ListNode* dummy = new ListNode(0, head);ListNode* first = head;//慢的用哑结点赋值,与快的同步往后会相差一位 便于删除ListNode* second = dummy;for (int i = 0; i < n; ++i) {first = first->next;}while (first) {first = first->next;second = second->next;}second->next = second->next->next;ListNode* ans = dummy->next;delete dummy;return ans;}
};

1.3 给定两个增序的链表,试将其合并成一个增序的链表。

样例
Input: 1->2->4, 1->3->4
Output: 1->1->2->3->4->4

方法1:递归

class Solution {public:ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {if (l1 == nullptr) {return l2;} else if (l2 == nullptr) {return l1;} else if (l1->val < l2->val) {l1->next = mergeTwoLists(l1->next, l2);return l1;} else {l2->next = mergeTwoLists(l1, l2->next);return l2;}}
};

方法2:迭代

class Solution {public:ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {ListNode* preHead = new ListNode(-1);ListNode* prev = preHead;while (l1 != nullptr && l2 != nullptr) {if (l1->val < l2->val) {prev->next = l1;l1 = l1->next;} else {prev->next = l2;l2 = l2->next;}prev = prev->next;}// 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可prev->next = l1 == nullptr ? l2 : l1;return preHead->next;}
};

1.4 删除有序(递增)链表中的重复元素。

leetcode:83
输入:head = [1,1,2]
输出:[1,2]

class Solution {public:ListNode* deleteDuplicates(ListNode* head) {if (!head) {return head;}ListNode* cur = head;while (cur->next) {if (cur->val == cur->next->val) {cur->next = cur->next->next;}else {cur = cur->next;}}return head;}
};

1.5 以 O(1) 的空间复杂度,判断链表是否回文。

leetcode:234
输入:head = [1,2,2,1]
输出:true

方法1:非O(1)
借助辅助栈,将链表值放入栈中,遍历看两个值是否相等

//借用辅助栈
class Solution {public:bool isPalindrome(ListNode* head) {ListNode* cur = head;stack<int> s;while (cur){s.push(cur->val);cur = cur->next;}while (!s.empty()){if (s.top() != head->val)return false;s.pop();head = head->next;}return true;}
};

方法2:递归 递归也不满足O(1)

方法3:双指针
使用快慢指针找到中点,后半段翻转,看是否相同

class Solution {public:
// 主函数bool isPalindrome(ListNode* head) {if (!head || !head->next) {return true; }ListNode *slow = head, *fast = head;while (fast->next && fast->next->next) {slow = slow->next;fast = fast->next->next;}//由于链表的长度有奇数和偶数之分//在奇数时slow在中间//偶数时slow在中间两个数的第一个//所以他们需要翻转后续的结点slow = reverseList(slow->next);while (slow) {if (head->val != slow->val){return false; }  head = head->next;slow = slow->next;}return true; }       //逆置ListNode* reverseList(ListNode* head) {ListNode *prev = nullptr, *next;while (head) {next = head->next;head->next = prev;prev = head;head = next;}return prev;}
};

1.6 已排序链表,删除所有重复元素(保留一个)

Leeetcode 83

class Solution {public:ListNode* deleteDuplicates(ListNode* head) {if (!head) {return head;}ListNode* cur = head;while (cur->next) {if (cur->val == cur->next->val) {cur->next = cur->next->next;}else {cur = cur->next;}}return head;}
};

1.7 给定两个链表,判断它们是否相交于一点,并求这个相交节点。

a+b+c = a+c+b

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->next;pB = pB == nullptr ? headA : pB->next;}return pA;}
};

二、栈与队列

栈与队列一般不作为单独算法考点,只会以辅助栈和辅助队列的形式出现,算法不予以统计


三、树与二叉树

3.1 [递归]二叉树的深度

class Solution{public:int maxDepth(TreeNode* root){return 1+man(maxDepth(root->left),maxDepth(root->right)):0;}
};

3.2 [递归][树的判定]翻转平衡二叉树

class Solution {public:TreeNode* invertTree(TreeNode* root) {if (root == nullptr) {return nullptr;}TreeNode* left = invertTree(root->left);TreeNode* right = invertTree(root->right);root->left = right;root->right = left;return root;}
};

3.3 [递归][树的判定]平衡二叉树的判定

Leetcode
概念:左右子树高度差小于等于1
思路:类似于求树的深度,但有两个不同的地方:一是我们需要先处理子树的深度再进行
比较,二是如果我们在处理子树时发现其已经不平衡了,则可以返回一个-1。

class Solution {public:int height(TreeNode* root) {if (root == NULL) {return 0;} else {return max(height(root->left), height(root->right)) + 1;}}bool isBalanced(TreeNode* root) {if (root == NULL) {return true;} else {//当前结点的左右平衡因子小于等于1,递归判断其左右子树是否满足平衡二叉树return abs(height(root->left) - height(root->right)) <= 1 && isBalanced(root->left) && isBalanced(root->right);}}
};

3.4 [递归]二叉树的直径

Leetcode
注意 int&的用法

class Solution {public:int diameterOfBinaryTree(TreeNode* root) {int diameter = 0;helper(root, diameter);return diameter;}//辅助函数  注意int& 转为引用类型,使得实参双向传递int helper(TreeNode* node,int& diameter){//终止条件if(node == nullptr)return 0;//返回左右子树的高度int l = helper(node->left, diameter);int r = helper(node->right, diameter);//比较此时左右子树的和与最大值的大小diameter = max(l + r, diameter);return max(l, r) + 1;     }
};

3.5 [双递归]二叉树的路径总和

Leetcode
给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。
辅助函数:计算连续加入节点的路径。

class Solution {public:int pathSum(TreeNode* root, int targetSum) {return root==nullptr?0:dfs(root,targetSum)+dfs(root->left,targetSum)+dfs(root->right,targetSum);}int dfs(TreeNode* root, int targetSum){if(!root)return 0;//注意此时相等不能返回,int count = (root->val == targetSum)? 1: 0;count+=dfs(root->left,targetSum-root->val);count+=dfs(root->right,targetSum-root->val);return count;}};

3.6 [递归]判断一个二叉树是否对称

辅助函数:判断两棵子树是否相等
“四步法”:
(1)如果两个子树都为空指针,则它们相等或对称
(2)如果两个子树只有一个为空指针,则它们不相等或不对称
(3)如果两个子树根节点的值不相等,则它们不相等或不对称
(4)根据相等或对称要求,进行递归处理。

class Solution {public:bool check(TreeNode *p, TreeNode *q) {if (!p && !q) return true;if (!p || !q) return false;return p->val == q->val && check(p->left, q->right) && check(p->right, q->left);}bool isSymmetric(TreeNode* root) {return check(root, root);}
};

3.7 [遍历][递归]二叉树的前中后序遍历

class Solution {public://前序void preorder(TreeNode *root, vector<int> &res) {if (root == nullptr) {return;}res.push_back(root->val);preorder(root->left, res);preorder(root->right, res);}//中序void inorder(TreeNode* root, vector<int>& res) {if (!root) {return;}inorder(root->left, res);res.push_back(root->val);inorder(root->right, res);}//后序void aftorder(TreeNode *root, vector<int> &res) {if (root == nullptr) {return;}aftorder(root->left, res);aftorder(root->right, res);res.push_back(root->val);}vector<int> inorderTraversal(TreeNode* root) {vector<int> res;inorder(root, res);return res;}
};

3.8 [遍历][迭代]二叉树的前序遍历

借助辅助栈

class Solution {public:vector<int> preorderTraversal(TreeNode* root) {vector<int> res;if (root == nullptr) {return res;}stack<TreeNode*> stk;TreeNode* node = root;while (!stk.empty() || node != nullptr) {while (node != nullptr) {res.emplace_back(node->val);stk.emplace(node);node = node->left;}node = stk.top();stk.pop();node = node->right;}return res;}
};

3.9 [遍历]二叉树的层序遍历

借助辅助队列 BFS

class Solution {public:vector<vector<int>> levelOrder(TreeNode* root) {vector <vector <int>> ret;if (!root) {return ret;}queue <TreeNode*> q;q.push(root);while (!q.empty()) {int currentLevelSize = q.size();ret.push_back(vector <int> ());for (int i = 1; i <= currentLevelSize; ++i) {auto node = q.front(); q.pop();ret.back().push_back(node->val);if (node->left) q.push(node->left);if (node->right) q.push(node->right);}}return ret;}
};

四、图(考的较少)


五、排序

5.1 [插入类]直接插入排序

void InsertSort(int arr[], int n){int i, j, temp;//遍历数组for (i = 1; i < n; i++){//当前元素的前驱大于当前元素if (arr[i - 1] > arr[i]) {//保存arr[i]temp = arr[i];//将前面有序序列中的所有大于arr[i]的值全部后移一位for (j = i - 1; j >= 0 && arr[j] > temp; j--){arr[j + 1] = arr[j];}//将原arr[i]赋值给arr[j + 1]arr[j + 1] = temp;}//if}//for
}

5.2 [插入类]希尔排序

void ShellSort(int arr[], int n) {int d;//初始化d为n/2,每一轮d为上一轮的1/2for (d = n / 2; d >= 1; d /= 2) {//从每个个分组的第二个元素开始,遍历剩余元素,进行直接插入排序for (int i = 1 + d; i < n; i++) {//直接插入排序(组间元素对比)if (arr[i] < arr[i - d]) {arr[0] = arr[i];int j;for (j = i - d; j > 0 && arr[j] > arr[0]; j -= d) {arr[j + d] = arr[j];}arr[j + d] = arr[0];}}}
}

5.3 [交换类]冒泡排序

//交换
void swap(int &a, int &b) {int temp = a;a = b;b = temp;
}
//冒泡排序
void BubbleSort(int arr[], int n) {for (int i = 0; i < n - 1; i++) {//标记此轮循环中是否进行了交换bool flag = false;//每次从数组中最后一个元素向前遍历,直到第i个元素for (int j = n - 1; j >= i; j--) {//将相邻两个逆序元素交换为正序,并更改flagif (arr[j - 1] > arr[j]) {swap(arr[j - 1], arr[j]);flag = true;}}//for//此次循环元素都是正序,则结束函数if (!flag) return;}//for
}

5.3 [交换类]快排

分治法

void QuickSort(vector<int>& v, int low, int high)
{if (low >= high)        // 结束标志return;int first = low;        // 低位下标int last = high;        // 高位下标int key = v[first];     // 设第一个为基准while (first < last){// 将比第一个小的移到前面while (first < last && v[last] >= key)last--;if (first < last)v[first++] = v[last];// 将比第一个大的移到后面while (first < last && v[first] <= key)first++;if (first < last)v[last--] = v[first];}// 基准置位v[first] = key;// 前半递归QuickSort(v, low, first - 1);// 后半递归QuickSort(v, first + 1, high);
}

5.4 [选择类]简单选择

//交换元素
void swap(int &a, int &b){int temp = a;a = b;b = temp;
}//简单选择排序
void SelectSort(int arr[], int n){//遍历数组for (int i = 0; i < n; i++){//标记当前数组中最小值元素的下标,初始为第 i 个元素int min = i;//从i + 1开始遍历数组for (int j = i + 1; i < n; j++){if (arr[j] < arr[min]) min = j;}//交换第 i 个元素和最小值元素swap(arr[i] , arr[j]);}
}

5.5 归并排序(个人觉得会考)

leetcode

在这里插入代码片

总结

【408数据结构】备考常见必会算法图鉴相关推荐

  1. 前端必会算法——线性数据结构的递归遍历

    上一篇: 前端必会算法--线性数据结构的遍历 线性数据结构的递归遍历 数组是知道长度的,最好的遍历方式的循环 var arr = [1,2,3,4]; //循环遍历数组,常见,常用 function ...

  2. 数据结构 - 二叉树 - 面试中常见的二叉树算法题

    数据结构 - 二叉树 - 面试中常见的二叉树算法题 数据结构是面试中必定考查的知识点,面试者需要掌握几种经典的数据结构:线性表(数组.链表).栈与队列.树(二叉树.二叉查找树.平衡二叉树.红黑树).图 ...

  3. 数据结构 - 链表 - 面试中常见的链表算法题

    数据结构 - 链表 - 面试中常见的链表算法题 数据结构是面试中必定考查的知识点,面试者需要掌握几种经典的数据结构:线性表(数组.链表).栈与队列.树(二叉树.二叉查找树.平衡二叉树.红黑树).图. ...

  4. 【数据结构---排序】庖丁解牛式剖析常见的排序算法

    排序算法 一.常见的排序算法 二.常见排序算法的实现 1. 直接插入排序 2. 希尔排序 3. 直接选择排序 4. 堆排序 5. 冒泡排序 6. 快速排序 6.1 递归实现快速排序 思路一.hoare ...

  5. 机械转码日记【5】《数据结构》常见排序算法及对比(第一次画动图)

    目录 前言 1.冒泡排序 2.直接插入排序 3.希尔排序 4.直接选择排序 5.堆排序 6.快速排序 6.1将区间按照基准值划分为左右两半部分的常见方式 6.1.1Hoare版本 6.1.2挖坑法 6 ...

  6. access两字段同时升序排序_7 天时间,我整理并实现了这 9 种常见的排序算法

    排序算法 回顾 我们前面已经介绍了 3 种最常见的排序算法: java 实现冒泡排序讲解 QuickSort 快速排序到底快在哪里? SelectionSort 选择排序算法详解(java 实现) 然 ...

  7. 力扣高频算法php_互联网公司最常见的面试算法题有哪些?

    很多时候,你即使提前复习了这些最常见的面试算法题,你依旧无法通过算法面试! 为什么?你在提前准备复习的时候,在网上找了半天相应题目的分析文章,但你看了就是不懂. 你在面试的时候,卡壳了,一时间忘了怎么 ...

  8. python常用算法有哪些_python常见的排序算法有哪些?

    大家都知道,关于python的算法有很多,其中最为复杂的就是python的排序算法,因为它并不是单一的,而是复杂的,关于排序算法就有好几种不同的方式,大家可以根据以下内容,结合自己的项目需求,选择一个 ...

  9. 常见的GC算法(GC的背景与原理)

    常见的GC算法(GC的背景与原理) GC 是英文词汇Garbage Collection的缩写,中文一般直译为 "垃圾收集".当然也会说 "垃圾回收". 三种垃 ...

最新文章

  1. 图像配准----Harris算子
  2. 鸿洋android屏幕适配四部曲-传送门
  3. java web nodejs_我的2013--从java web到nodejs
  4. [渝粤教育] 西南科技大学 动态网页设计(JSP) 在线考试复习资料
  5. UVA 116——Unidirectional TSP
  6. PJSIP UA分析(2)--PJSUA注册
  7. 随机名字生成小demo源码
  8. java名人_识别名人 · Find the Celebrity
  9. python 字符串不区分大小写_还在吐槽文本字符串难以处理,Python的这个绝活你还不知道
  10. Android 屏幕适配攻略(四)获取手机屏幕的相关信息 与动态设置控件的大小
  11. epoll示例程序——服务端
  12. JavaScript 基础(十六):Navigator对象
  13. [面试] 算法(八)—— 树
  14. 数据分析好学吗_数据分析篇 | 一个虎扑社区数据分析实战
  15. python 文本处理---英文文本预处理(简单易懂 全有注释)!!!!!使用正则表达式以及nltk库分词器双方法!
  16. 使用Python给罗永浩生成卡通头像
  17. Spring Cloud Gateway编码实现任意地址跳转
  18. 原生js高仿浏览器ctrf+f
  19. BGP高防服务器与普通高防服务器有什么区别?
  20. Lumerical---FDE中的金属边界条件仿真

热门文章

  1. 搭建K8S 的dashboard的坑the server could not find the requested resource
  2. 【数据结构和算法】赫夫曼树 | 实战演练(二)
  3. pcf8563c语言程序,PCF8563实时时钟C源程序
  4. 星巴克招人!要技术大拿。
  5. 修复花雨庭服务器,我的世界手机版怎么进花雨庭服务器 | 手游网游页游攻略大全...
  6. 练习2-6 编写一个函数setbits(x, p ,n, y),该函数返回对x执行下列操作后的结果值: 将x中从第p位开始的n个(二进制)位设置为y中最右边n位的值,x的其余各位保持不变。
  7. VMware虚拟机硬盘大小修改
  8. STM32学习心得十八:通用定时器基本原理及相关实验代码解读
  9. XTU Oj 128
  10. html格式显示图标异常,HTM或HTML图标变成无法显示和识别的解决方法大全