目录

  • 1、反转链表
  • 2、排序
  • 3、先序中序后序遍历
  • 4、最小的k个数
  • 5、子数组的最大累加和
  • 6、 用两个栈实现队列
  • 7、142. 环形链表 II
  • 8、20. 有效的括号
  • 9、最长公共子串(动态规划),磕磕绊绊
  • 10、二叉树之字形层序遍历
  • 11、重建二叉树
  • 12、LRU缓存
  • 13、合并两个有序链表
  • 15、大数加法
  • 16、一个二叉树和一个值sum,请找出所有的根节点到叶子节点的节点值之和等于sum 的路径
  • 17、寻找第K大
  • 18、买卖股票的最佳时机
  • 19、二数之和
  • 20、合并两个有序数组
  • 21、二叉树的最近公共祖先

感觉所有算法里面掌握最好的还是回溯,其他的都是半吊子。

1、反转链表

反转链表
双指针法

class Solution {public:ListNode* ReverseList(ListNode* pHead) {ListNode* cur = pHead;ListNode* prev = nullptr;while(cur != nullptr){ListNode* tmp = cur->next;cur->next = prev;prev = cur;cur = tmp;}return prev;}
};

2、排序

排序
这里我们选择使用快速排序来求解:

class Solution {public:void Quicksort(vector<int>& a, int s, int t){int i, j;if (s < t){//【1】设置两个变量i、j.分别指向首元素和尾元素,设定i指向的首元素为基准元素i = s;j = t + 1;while (1){do i++;while (!(a[s] <= a[i] || i == t));               //【2】重复i++操作,直到i指向的元素>=基准元素,或者i指向尾部do j--;while (!(a[s] >= a[j] || j == s));              //【3】反复执行j--,直到指向的元素<基准元素,或者j指向头部if (i < j)                                  //【5】若此时i<j,将i和j指向的元素进行交换。(大的元素在后面){swap(a[j], a[i]);}else break;                                  //【5】完成第一次交换后,重复执行步骤1、2,直到i>=j位置}//【6】此时i>=j,然后将基准元素与j指向的元素交换位置,至此完成了原序列的第一次划分swap(a[s], a[j]);//【7】接下来分别对基准元素前后的子序列中长度大于1的子序列重复执行上述操作。Quicksort(a, s, j - 1);                             //前半序列Quicksort(a, j + 1, t);                             //后半序列}}vector<int> MySort(vector<int>& arr) {// write code hereQuicksort(arr,0,arr.size()-1);return arr;}
};

3、先序中序后序遍历

递归法:

class Solution {public:/*** * @param root TreeNode类 the root of binary tree* @return int整型vector<vector<>>*/vector<int> pre;vector<int> mid;vector<int> post;void preorder(TreeNode* root){if(root == nullptr) return;pre.push_back(root->val);preorder(root->left);preorder(root->right);}void midorder(TreeNode* root){if(root == nullptr) return;midorder(root->left);mid.push_back(root->val);midorder(root->right);}void postorder(TreeNode* root){if(root == nullptr) return;postorder(root->left);postorder(root->right);post.push_back(root->val);}vector<vector<int> > threeOrders(TreeNode* root) {// write code herepre.clear();mid.clear();post.clear();preorder(root);midorder(root);postorder(root);return {pre,mid,post};}
};

4、最小的k个数

sort + 取值

class Solution {public:vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {if(k > input.size()) return {};vector<int> result(k,0);sort(input.begin(),input.end());for(int i = 0; i < k; i++)result[i] = input[i];return result;}
};

方法二:堆
我们用一个大根堆实时维护数组的前 k 小值。首先将前 k个数插入大根堆中,随后从第 k+1 个数开始遍历,如果当前遍历到的数比大根堆的堆顶的数要小,就把堆顶的数弹出,再插入当前遍历到的数。最后将大根堆里的数存入数组返回即可。在下面的代码中,由于 C++ 语言中的堆(即优先队列)为大根堆,我们可以这么做。

class Solution {public:vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {if(k > input.size()) return {};if(k == 0) return {};priority_queue<int> que;for(int i = 0; i < k; i++){que.push(input[i]);}int size = (int)input.size();for(int i = k; i < size; i++){if(input[i] < que.top()){que.pop();que.push(input[i]);}}vector<int> res(k,0);for(int i = 0; i < k; i++){res[i] = que.top();que.pop();}return res;}
};

如果是要求最大的k个数,就用小根堆

5、子数组的最大累加和

https://leetcode-cn.com/problems/lian-xu-zi-shu-zu-de-zui-da-he-lcof/

class Solution {public:int maxSubArray(vector<int>& nums) {if(nums.empty()) return 0;int res =INT_MIN;int sum = 0;for(int i = 0; i < nums.size(); i++){sum += nums[i];if(sum > res) res = sum;if(sum < 0) sum = 0;}return res;}
};

6、 用两个栈实现队列

用两个栈实现队列
一个输入栈,一个输出栈。
push数据的时候,只要把数据放进输入栈即可。
pop的时候:
1、输出栈如果为空,就将进栈的数据全部导入,再出栈弹出数据。
2、如果栈不为空,直接从出栈弹出数据

class Solution
{public:void push(int x) {stIn.push(x);}int pop() {if(stOut.empty()){while(!stIn.empty()){stOut.push(stIn.top());stIn.pop();}}//out有元素了,那么就popint result = stOut.top();stOut.pop();return result;}private:stack<int> stIn;stack<int> stOut;
};

7、142. 环形链表 II

环形链表 II
使用快慢指针:
通过数学证明,x = z;
即:从头节点出发一个index,从相遇地点出发一个index,每次移动一点,直到两者相遇,相遇地点就是入口
这里给出牛客网同样题目的代码:
https://www.nowcoder.com/practice/6e630519bf86480296d0f1c868d425ad?tpId=117&tqId=37713&companyId=134&rp=1&ru=%2Fcompany%2Fhome%2Fcode%2F134&qru=%2Fta%2Fjob-code-high%2Fquestion-ranking&tab=answerKey

class Solution {public:ListNode *detectCycle(ListNode *head) {ListNode* fast = head;ListNode* slow = head;while(fast != nullptr && fast->next != nullptr){slow = slow->next;fast = fast->next->next;//当两者相遇的时候,开始计算入口地点while(slow == fast){ListNode* index1 = slow;ListNode* index2 = head;while(index1 != index2){index1 = index1->next;index2 = index2->next;}return index1;}}//如果遇到nullptr,说明没有环return nullptr;}
};

8、20. 有效的括号

https://leetcode-cn.com/problems/valid-parentheses/
使用栈的时候三者对应到的栈的情况;
1、已经遍历完字符串,但是栈不为空
2、遍历字符串匹配的过程中,栈已经为空了
3、再遍历字符串匹配的过程中,发现栈中没有要匹配的字符。

class Solution {public:bool isValid(string s) {stack<char> st;for(int i = 0; i < s.size(); i++){if(s[i] == '(') st.push(')');else if(s[i] == '[') st.push(']');else if(s[i] == '{') st.push('}');//接下来就是判断,这个是1、3情况else if(st.empty() || st.top() != s[i]){return false;}//如果匹配,那么出栈else{st.pop();}}//第2种情况,遍历完字符串,栈不为空return st.empty();}
};

9、最长公共子串(动态规划),磕磕绊绊

给定两个字符串str1和str2,输出两个字符串的最长公共子串
题目保证str1和str2的最长公共子串存在且唯一。
1≤∣str1∣,∣str2∣≤5000

“1AB2345CD”,“12345EF”
“2345”

1、把两个字符串分别以行和列组成一个二维矩阵。

2、比较二维矩阵中每个点对应行列字符中否相等,相等的话值设置为1,否则设置为0。

3、通过查找出值为1的最长对角线就能找到最长公共子串。

    string LCS(string str1, string str2) {// write code hereint len1 = str1.size();int len2 = str2.size();int start_index = 0;int res_length = 0;if(len1 == 0 || len2 == 0) return "";vector<vector<int>> f(len1+1,vector<int>(len2+1,0));for(int i=0;i < len1;i++)      //防止数组越界{for(int j=0;j < len2;j++){//i-1:text中的第i个字符          if(str1[i] == str2[j]){if( i == 0 || j == 0){f[i][j] = 1;}else{f[i][j] = f[i-1][j-1] + 1;}}else f[i][j] = 0;//更新坐标if(f[i][j] >= res_length){start_index = i - res_length;res_length = f[i][j];}}}
//         cout << start_index << endl;
//         cout << res_length << endl;return str1.substr(start_index,res_length);}

10、二叉树之字形层序遍历

层序遍历+flag标志即可

    vector<vector<int> > zigzagLevelOrder(TreeNode* root) {// write code herequeue<TreeNode*> que;if(root != nullptr) que.push(root);vector<vector<int>> result;int flag = 0;while(!que.empty()){int size = que.size();vector<int> vec;for(int i = 0; i < size; i++){TreeNode* node = que.front();que.pop();vec.push_back(node->val);if(node->left) que.push(node->left);if(node->right) que.push(node->right);}if(flag == 0){result.push_back(vec);flag = 1;}else{reverse(vec.begin(),vec.end());result.push_back(vec);flag = 0;}}return result;}

11、重建二叉树

https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {public:TreeNode* traversal(vector<int>& preorder,int prestart,int preend,vector<int>& inorder,int instart,int inend){//首先,检查先序数组大小,根据下标if(prestart == preend){return nullptr;}//先序数组中第一个节点就是当前中间节点,new一个节点int rootval = preorder[prestart];TreeNode* root = new TreeNode(rootval);//如果是叶子节点,就不需要分割了,直接返回该节点if(preend - prestart == 1){return root;}//中序数组找切割点int splitIndex = instart;    //注意,区间是左闭右开的for(splitIndex = instart; splitIndex < inend; splitIndex++){if(inorder[splitIndex] == rootval) break;}//切割中序数组int leftInbegin = instart;int leftInend = splitIndex;int rightInbegin = splitIndex + 1;int rightInend = inend;//切割先序数组int leftPrebegin = prestart + 1;int leftPreend = prestart + leftInend - leftInbegin;int rightPrebegin = leftPreend;int rightPreend = preend;//递归处理左区间和右区间root->left = traversal(preorder,leftPrebegin,leftPreend,inorder,leftInbegin,leftInend);root->right = traversal(preorder,rightPrebegin,rightPreend,inorder,rightInbegin,rightInend);return root;}TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {if(preorder.empty() || inorder.empty()) return nullptr;return traversal(preorder,0,preorder.size(),inorder,0,inorder.size());}
};

12、LRU缓存

struct DLinkedNode {public:int key;int value;DLinkedNode* prev;DLinkedNode* next;DLinkedNode() : key(0), value(0), prev(nullptr), next(nullptr) {};DLinkedNode(int _key, int _value) : key(_key), value(_value), prev(nullptr), next(nullptr) {};
};
class LRUCache {private:unordered_map<int,DLinkedNode*> cache;//dummyhead and dummytailDLinkedNode* dummyhead;DLinkedNode* dummytail;// now size of cacheint _size;// capacity of cacheint _capacity;
public:LRUCache(int capacity) {_capacity = capacity;_size = 0;dummyhead = new DLinkedNode();dummytail = new DLinkedNode();dummyhead->next = dummytail;dummytail->prev = dummyhead;}~LRUCache() {delete dummyhead;delete dummytail;}int get(int key) {// if not findif(cache.find(key) == cache.end()){return -1;}//if find//haxi DLinkedNode* node = cache[key];//move this Node to headmoveHead(node);return node->value;}void put(int key, int value) {// if key not exist ,create itif(cache.find(key) == cache.end()){// if size > capacity delete tail nodeif(_size + 1 > _capacity){DLinkedNode* deleted_node = deleteTail();cache.erase(deleted_node->key);delete deleted_node;_size--;}DLinkedNode* newnode = new DLinkedNode(key,value);cache[key] = newnode;addHead(newnode);_size++;}else        //chage value{DLinkedNode* node = cache[key];node->value = value;moveHead(node);}}void addHead(DLinkedNode* node){//双向指针操作 + 虚拟头节点node->prev = dummyhead;node->next = dummyhead->next;dummyhead->next->prev = node;dummyhead->next = node;}DLinkedNode* deleteTail(){//尾节点是虚拟tail前面一个。DLinkedNode* node = dummytail->prev;deleteNode(node);return node;}void deleteNode(DLinkedNode* node){node->prev->next = node->next;node->next->prev = node->prev;}void moveHead(DLinkedNode* node){//先删除当前节点deleteNode(node);//然后将它加入头部addHead(node);}
};

13、合并两个有序链表

https://leetcode-cn.com/problems/merge-two-sorted-lists/

/*** 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* l1, ListNode* l2) {ListNode* dummyHead = new ListNode(-1);ListNode* cur = dummyHead;while(l1 != nullptr && l2 != nullptr){if(l1->val > l2->val){cur->next = l2;cur = cur->next;l2 = l2->next;}else{cur->next = l1;cur = cur->next;l1 = l1->next;}} while(l1 != nullptr) {cur->next = l1;cur = cur->next;l1 = l1->next;}while(l2 != nullptr){cur->next = l2;cur = cur->next;l2 = l2->next;}ListNode* ret = dummyHead->next;delete dummyHead;return ret;}
};

15、大数加法

大数加法

class Solution {public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可* 计算两个数之和* @param s string字符串 表示第一个整数* @param t string字符串 表示第二个整数* @return string字符串*/string solve(string s, string t) {// write code hereif(s.empty()) return t;if(t.empty()) return s;if(s.size()<t.size()) swap(t,s);int tail = s.size() - t.size();int tmp = 0;//补零操作 t是短的那个while(tail--) t = '0'+t;//每次只处理1位,从低到高for(int i=s.size()-1;i>=0;i--){tmp = s[i]-'0' + t[i] -'0' + tmp;s[i] = tmp%10 + '0';tmp/=10;}//最高位是否有进位位if(tmp) s = '1'+s;return s;}
};

16、一个二叉树和一个值sum,请找出所有的根节点到叶子节点的节点值之和等于sum 的路径

一个二叉树和一个值sum…
普通的回溯即可。

class Solution {public:/*** * @param root TreeNode类 * @param sum int整型 * @return int整型vector<vector<>>*/vector<vector<int> > result;vector<int> path;void traversal(TreeNode* root,int count){if(root->left == nullptr && root->right == nullptr){if(count == 0) {result.push_back(path);}return ;}if(root->left){count -= root->left->val;path.push_back(root->left->val);traversal(root->left,count);path.pop_back();count += root->left->val;}if(root->right){count -= root->right->val;path.push_back(root->right->val);traversal(root->right,count);path.pop_back();count += root->right->val;}return ;}vector<vector<int> > pathSum(TreeNode* root, int sum) {// write code herepath.clear();result.clear();if(root == nullptr) return result;path.push_back(root->val);traversal(root,sum - root->val);return result;}
};

17、寻找第K大

18、买卖股票的最佳时机

int maxProfit(vector<int>& prices) {// write code hereint n = prices.size();vector<int> dp(n+1,0);int minnum = prices[0];for(int i = 1; i < n; i++){minnum = min(minnum,prices[i]);dp[i] = max(prices[i] - minnum,dp[i-1]);}return dp[n-1];}

可以使用滚动数组优化:

int maxProfit(vector<int>& prices) {int n=prices.size();if(n==0) return 0;int ans=0;int minnum =prices[0];for(int i=1;i<n;i++){minnum=min(minnum,prices[i]);ans=max(ans,prices[i]-minnum);}if(ans<=0)ans=0;return ans;}

19、二数之和

https://leetcode-cn.com/problems/two-sum/

class Solution {public:vector<int> twoSum(vector<int>& nums, int target) {unordered_map<int,int > umap;for(int i = 0; i < nums.size(); i++){auto iter = umap.find(target - nums[i]);//如果找到了if(iter != umap.end()){return {i,iter->second};}//否则,进行插入操作umap.insert(pair<int,int>(nums[i],i));}return {};}
};

20、合并两个有序数组

void merge(int A[], int m, int B[], int n) {int l1 = 0;int l2 = 0;vector<int> res;while(l1 < m && l2 < n){if(A[l1] <= B[l2]){res.push_back(A[l1]);l1++;}else{res.push_back(B[l2]);l2++;}}while(l1 < m) {res.push_back(A[l1]);l1++;}while(l2 < n) {res.push_back(B[l2]);l2++;}for(int i = 0; i < res.size(); i++)A[i] = res[i];}

21、二叉树的最近公共祖先

NC二叉树的最近公共祖先

    int lowestCommonAncestor(TreeNode* root, int o1, int o2) {// write code hereif(root == nullptr) return -1;if(o1 == root->val || o2 == root->val) return root->val;int left = lowestCommonAncestor(root->left,o1,o2);int right = lowestCommonAncestor(root->right,o1,o2);if(left == -1) return right;if(right == -1) return left;return root->val;}

牛客网与leetcode刷题(高频题中简单or中等的)相关推荐

  1. 为了OFFER而战,大四那些日子在牛客网和Leetcode刷SQL题目

    @Author:Runsen @Date:2020/9/18 大四刷题拼offer系列,不拼不行啊 现在集中火力进军SQL,然后过渡到Java.下面的SQL题目都是来自牛客网,都是本人觉得挺重要的题目 ...

  2. LeetCode 牛客网 C++ 算法 刷题必备基础知识

    LeetCode 牛客网 C++ 算法 刷题必备基础知识 {ignore} 文章目录 LeetCode 牛客网 C++ 算法 刷题必备基础知识 {ignore} main综合模板 数组排序库 字符串库 ...

  3. python刷题 NOI题库 python题解 洛谷、牛客网、AcWing 刷题等

    NOI题库 python题解-2022.01.07整理(1.1-1.3) NOI题库 python题解-2022.01.07整理(1.1-1.3)_dllglvzhenfeng的博客-CSDN博客 N ...

  4. 【牛客网面试必刷TOP101】链表篇(一)

    链表 一.前言 二.学习刷题网站 1.推荐的原因 三.刷题 <1>反转链表 递归法 <2>链表内指定区间反转 ①头插法 ②递归法 <3>链表中的节点每k个一组翻转 ...

  5. 「解析」牛客网-华为机考企业真题 1-20

    又是一年春招时,有幸收到华为自动驾驶算法岗,之前刷题不多,在此汇总下牛客网的真题,主要采用Python编写,个人觉得语言只是实现工具而已,并不是很关键,Python简洁易懂,更加适合算法工程师快速验证 ...

  6. 「解析」牛客网-华为机考企业真题 41-60

    又是一年春招时,有幸收到华为自动驾驶算法岗,之前刷题不多,在此汇总下牛客网的真题,主要采用Python编写,个人觉得语言只是实现工具而已,并不是很关键,Python简洁易懂,更加适合算法工程师快速验证 ...

  7. 「解析」牛客网-华为机考企业真题 81-108

    又是一年春招时,有幸收到华为自动驾驶算法岗,之前刷题不多,在此汇总下牛客网的真题,主要采用Python编写,个人觉得语言只是实现工具而已,并不是很关键,Python简洁易懂,更加适合算法工程师快速验证 ...

  8. 「解析」牛客网-华为机考企业真题 21-40

    又是一年春招时,有幸收到华为自动驾驶算法岗,之前刷题不多,在此汇总下牛客网的真题,主要采用Python编写,个人觉得语言只是实现工具而已,并不是很关键,Python简洁易懂,更加适合算法工程师快速验证 ...

  9. 牛客网--蘑菇街2016研发工程师编程题

    牛客网--蘑菇街2016研发工程师编程题 第一题: 搬圆桌 时间限制:1秒 空间限制:32768K 现在有一张半径为r的圆桌,其中心位于(x,y),现在他想把圆桌的中心移到(x1,y1).每次移动一步 ...

最新文章

  1. halcon python 联合开发_使用pythonnet调用halcon脚本
  2. 【Android 插件化】Hook 插件化框架总结 ( 插件包管理 | Hook Activity 启动流程 | Hook 插件包资源加载 ) ★★★
  3. IDEA+Hadoop运行TriangleCount程序
  4. es6语法-对象拓展运算符
  5. servlet url-pattern配置中 / 和 /* 的区别 记录
  6. 新安搭信息快车建智慧城市
  7. NGINX 502 Bad Gateway 用upstream解决方法
  8. c语言过程化程序设计方法,程序的设计基础(C语言入门及编程环境)(修改).ppt
  9. gpu服务器性能测试用例,多目标测试用例预优化方法及其在GPU上的应用研究
  10. oracle安装很慢,oracle11g安装后电脑启动很慢怎么解决
  11. Codeforces 464E. The Classic Problem
  12. Linux下conda 安装以后 activate无法使用
  13. 基于Java Web的随意购商城系统(开源项目)
  14. 商标注册成功后的中肯建议
  15. 暴雪战网国际版[国区登录战网国际版方法]
  16. 日期插件layui的》laydate
  17. day01 pathon基础
  18. 推荐一个C# 制作免安装程序的工具和方法,超级好用 fody
  19. android必备软件!零基础如何成为高级Android开发,薪资翻倍
  20. 简述计算机组装的具体流程,简述计算机的组装流程??

热门文章

  1. 事关每个程序员的职业规划与履历
  2. gitlab或者gitee生成/添加SSH公钥的解决办法
  3. Autorize插件的使用方法
  4. mysql二进制大文件_Mysql实例Mysql LONGTEXT 类型存储大文件(二进制也可以) (修改+调试+整理)...
  5. 【...】小程序扩展运算符 ... 说明
  6. JS_理解函数参数按值传递
  7. 酷毙了!三种风格的全屏幻灯片效果【附源码下载】
  8. 【代码笔记】Web-HTML-颜色
  9. VirtualDOM与diff(Vue实现)
  10. CSS染色图标(图片)