字节跳动测开面试手撕代码汇总(c++)
2020-07-14 05:15
489 查看
树相关
树的非递归遍历
#include<iostream> #include<string> #include<stack> struct TreeNode{ int val; TreeNode *l; TreeNode *r; }; TreeNode* createtree(){ TreeNode *root; int a[]={1,2,4,0,0,0,3,5,0,0,6,0,0}; static int t=0; root=new TreeNode; int data; data=a[t++]; if(data==0){ return NULL; } root->val=data; root->l=createtree(); root->r=createtree(); return root; } //非递归前序遍历 void preorder(TreeNode *root ) { stack<TreeNode *> s; TreeNode *p = root; while(p != NULL || !s.empty()) { while(p != NULL) { cout<<p->val; s.push(p); p = p->l; } if(!s.empty()) { p = s.top(); s.pop(); p = p->r; } } } //非递归中序遍历 void inorder(TreeNode *root) { stack<TreeNode *> s; TreeNode *p = root; while(p != NULL || !s.empty()) { while(p != NULL) { s.push(p); p = p->l; } if(!s.empty()) { p = s.top(); cout<<p->val; s.pop(); p = p->r; } } } //更简单的非递归后序遍历 void postorder(TreeNode *root)//局部后序,全部后序 {//将栈顶元素取出,使以此元素为“根”结点的局部有序入栈,但若此前已通过该结点将其局部入栈,则直接出栈输出即可。 stack< pair<TreeNode *, bool> > s; s.push(make_pair(root, false)); bool visited; while(!s.empty()) { root = s.top().first; visited = s.top().second; s.pop(); if(root == NULL) continue; if(visited) { cout<<root->val; } else { s.push(make_pair(root, true)); s.push(make_pair(root->r, false)); s.push(make_pair(root->l, false)); } } } int main() { TreeNode * root; root=createtree(); // preorder(root); // inorder(root); postorder(root); return 0; }
二叉树的最大距离
两种情况:
情况A: 路径经过左子树的最深节点,通过根节点,再到右子树的最深节点。
情况B: 路径不穿过根节点,而是左子树或右子树的最大距离路径,取其大者。
#include<iostream> #include<vector> using namespace std; struct TreeNode{ char val; TreeNode *left; TreeNode *right; TreeNode(int x):val(x),left(NULL),right(NULL){}; }; TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { if(preorder.size()==0||inorder.size()==0){ return NULL; } TreeNode* tree=new TreeNode(preorder[0]);//先序的第一个节点树根 int mid=distance(inorder.begin(),find(inorder.begin(),inorder.end(),preorder[0])); vector<int> pre_l(preorder.begin()+1,preorder.begin()+mid+1); vector<int>pre_r(preorder.begin()+mid+1,preorder.end()); vector<int> in_l(inorder.begin(),inorder.begin()+mid); vector<int>in_r(inorder.begin()+mid+1,inorder.end()); tree->left=buildTree(pre_l,in_l); tree->right=buildTree(pre_r,in_r); return tree; } int treedistance(TreeNode *root,int &maxdis){//返回树的深度 if(root== nullptr){//根深度为-1 return -1; } int leftdis=treedistance(root->left,maxdis)+1;//左边的距离 int rightdis=treedistance(root->right,maxdis)+1; int dis=leftdis+rightdis;//每次的距离 maxdis=dis>maxdis?dis:maxdis;//返回最大距离 return leftdis>rightdis?leftdis:rightdis; } int main(){ vector<int> preorder={1,2,4,7,3,5,6,8}; vector<int> inorder={4,7,2,1,5,3,8,6}; TreeNode *root; int maxdis=0; cout<<treedistance(buildTree(preorder,inorder),maxdis)<<endl; cout<<maxdis; return 0; }
3.
/** * 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: vector<int> arr; vector<vector<int>> matrix; vector<vector<int>> pathSum(TreeNode* root, int sum) { dfs(root,sum); return matrix; } void dfs(TreeNode* root,int sum){ if(!root){ return ; } arr.push_back(root->val); if(root->left==NULL&&root->right==NULL&&sum-root->val==0){ matrix.push_back(arr); } else{ dfs(root->left,sum-root->val); dfs(root->right,sum-root->val); } arr.pop_back();//回溯 sum+=root->val; } };
4.建树+交换子树
struct BTree { int val; BTree *left,*right; }; BTree* create_node() { int data; BTree *node = new BTree; int a[]={100,99,98,97,0,0,20,0,0,10,0,0,5,1,0,0,2,0,0}; static int t=0; data=a[t++]; if(data == 0) { return NULL; } node->val= data; node->left = create_node(); node->right= create_node(); return node; } void dfs(BTree* root) { if (root) { swap(root->left, root->right); dfs(root->left); dfs(root->right); } } BTree* invertTree(BTree* root) { dfs(root); return root; } void preorder(BTree* root){ if(!root){ return ; } cout<<root->val<<" "; preorder(root->left); preorder(root->right); } int main() { BTree *tree; BTree *root; tree= create_node(); root=invertTree(tree); preorder(root); return 0; }
字符串相关
动态规划
class Solution { public: int longestCommonSubsequence(string text1, string text2) { int len1=text1.size(); int len2=text2.size(); vector<vector<int>>dp(len1+1,vector<int>(len2+1)); for(int i=0;i<=len1;i++){ dp[i][0]=0; } for(int i=0;i<=len2;i++){ dp[0][i]=0; } for(int i=1;i<=len1;i++){ for(int j=1;j<=len2;j++){ if(text1[i-1]==text2[j-1]){ dp[i][j]=dp[i-1][j-1]+1;//公共字符存在在之前的子问题前text1的前i-1个字符和text2的j-1个字符的基础上+1 } else{ dp[i][j]=max(dp[i-1][j],dp[i][j-1]);//当不等的时候,在两个字问题中取最大 } } } return dp[len1][len2]; } };
6.
class Solution { public: bool repeatedSubstringPattern(string s) { return (s+s).find(s,1)!=s.size(); //设 s=abab; s+s=abababab,从下标1开始寻找s,若s为子串重复多次构成,则find返回的值不会为下标4,即第二个s的开头 //设 s=abc; s+s=abcabc,从下标1开始寻找s,返回值为3,即第二个s的开头,因为s=abc不是子串重复多次构成的 } };
class Solution { public: int findNumberOfLIS(vector<int>& nums) { if (nums.empty()) return 0; int N = nums.size(); // pair<int, int> 分别为最长递增长度与对应的数目 vector<pair<int, int> > dp(N, {1, 1}); int mx = 1; for (int i = 1; i < N; ++i) { for (int j = 0; j < i; ++j) { if (nums[i] > nums[j]) { if (dp[i].first < dp[j].first + 1) { dp[i] = {dp[j].first + 1, dp[j].second}; } else if (dp[i].first == dp[j].first + 1) { dp[i].second += dp[j].second; } } } mx = max(mx, dp[i].first); } int res = 0; for (int i = 0; i < N; ++i) { if (dp[i].first == mx) { res += dp[i].second; } } return res; } };
模拟
判断ip 是否合法
vector<string> split(const string& src, string separate_character) { vector<string> strs; int separate_characterLen = separate_character.size();//分割字符串的长度,这样就可以支持如“,,”多字符串的分隔符 int lastPosition = 0, index = -1; while (-1 != (index = src.find(separate_character, lastPosition))) { strs.push_back(src.substr(lastPosition, index - lastPosition)); lastPosition = index + separate_characterLen; } string lastString = src.substr(lastPosition);//截取最后一个分隔符后的内容 if (!lastString.empty()) strs.push_back(lastString);//如果最后一个分隔符后还有内容就入队 return strs; } bool isIP(string str) { if (str.length() < 7 || str.length() > 15) { return false; } vector<string> arr= split(str,"."); if (arr.size()!= 4) { return false; } for (int i = 0; i < 4; i++) { string s = arr[i]; for (int j = 0; j < s.length(); j++) { if (s.at(j) < '0' || s.at(j) > '9') { return false; } } } for (int i = 0; i < 4; i++) { int temp = stoi(arr[i]); if (temp < 0 || temp > 255) { return false; } } return true; } int main(){ string str="127.12.23.88"; cout<<isIP(str); return 0; }
微信抢红包
转自:
#include<iostream> #include<time.h> #include<math.h> #include<stdlib.h> using namespace std; //min 默认最小金额 1=0.01元 //max 默认最大金额 20000 = 200 元 //total 总钱数 //num 总人数 long long CalcRandomValue(long long min, long long max, long long total, long long num) { if (num == 1) { return total; } //跟新随机种子 srand((unsigned int)time(NULL)); //锁定本次随机范围 long long low = (total - (num - 1)*max) < min ? min : (total - (num - 1)*max); long long high = (total - (num - 1)*min) > max ? max : (total - (num - 1)*min); long long ave = (total / num) > 1 ? (total / num) : 1; //调整上限 if (high > 20 * ave) { high = 20* ave; } //生成随机值 long long ram = rand() % high; //防止溢出 if (ram < low) ram = low; if (ram > high) ram = high; return abs(ram); } long long qianghongbao(long long total,long long num ) { if (total > 0) { if (num == 1) { printf("发红包金额%ld\n", total); } total *= 100; long long low = 1; long long max = 20000; printf("红包总金额 %ld元\n", total/100); printf("抢红包总人数 %ld\n", num); long long ret = 0; int i = 1; float big = 0.0; int person = 0; while (num > 0) { ret = CalcRandomValue(low, max, total, num); float ram = ret / 100.0; printf("第%i个人抢到了%lf元\n", i,ram); if (ram > big) { big = ram; person = i; } total -= ret; --num; ++i; } printf("第%d个人抢了%f元,手气最佳\n", person, big); } return -1; } int main() { qianghongbao(11, 10); return 0; }
链表相关
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {//相交链表双指针法 ListNode *p=headA; ListNode *q=headB; int len1=0,len2=0; while(p!=NULL){ len1++; p=p->next; } while(q!=NULL){ len2++; q=q->next; } int len=abs(len1-len2); while(headA!=NULL&&headB!=NULL){ if(len1>len2){ while(len){ headA=headA->next; len--; } } if(len1<len2){ while(len){ headB=headB->next; len--; } } if(headA==headB){ return headB; } else{ headA=headA->next; headB=headB->next; } } return NULL; } };
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* partition(ListNode* head, int x) { if(head==NULL){//快慢双指针 交换值 return NULL; } ListNode *pre=head; ListNode *cur=head; while(cur){ if(cur->val<x){ swap(pre->val,cur->val); pre=pre->next; } cur=cur->next; } return head; } };
#include<iostream> using namespace std; struct ListNode{ int val; ListNode *next; ListNode(int x):val(x),next(NULL){}; }; /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ ListNode *detectCycle(ListNode *head) {//快慢指针 ListNode *fast=head; ListNode *slow=head; while(fast!=NULL&&fast->next!=NULL){ fast=fast->next->next;//快的是慢的两倍速度 slow=slow->next; if(fast==slow){//第一次相遇 fast=head; while(fast!=slow){//快的再走非环长度和慢的相遇即为入环点 fast=fast->next; slow=slow->next; } cout<<fast->val; return fast; } } cout<<"NULL"; return NULL; } int main(){ ListNode *head= new ListNode(0);//先建立头节点 ListNode *q=head,*r=head; for(int i=1;i<6;i++){ ListNode *p=new ListNode(i); q->next=p; q=p; } while(r->next){//注意条件是next r=r->next; } r->next=head;//根据想要的环节点 链接 q=head; detectCycle(head); return 0; }
排序链表
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* sortList(ListNode* head) {//运用map if(head==NULL||head->next==NULL){ return head; } map<int,int> myMap; ListNode* p = head; while(p!=NULL){ myMap[p->val]++; //保存链表中每个节点值出现的次数 p = p->next; } p = head; map<int,int>::iterator iter = myMap.begin(); while(iter!=myMap.end()){ //遍历map for(int i = 0;i<iter->second;i++){//second 代表键值对的值部分 p->val = iter->first;//first键值对的键 p = p->next; } iter++; } return head; } };
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* sortList(ListNode* head) {//用快慢指针找到中间的节点 if(!head || !head->next) return head; ListNode* pre = head, *slow = head, *fast = head;//pre记录分为两段以后前一段的最后一个节点 while(fast && fast->next) { pre = slow; slow = slow->next; fast = fast->next->next; } pre->next = nullptr; return mergeTwoList(sortList(head), sortList(slow));//分为两段 } ListNode* mergeTwoList(ListNode* h1, ListNode* h2) {//二路归并 if(!h1) return h2; if(!h2) return h1; if(h1->val < h2->val) { h1->next = mergeTwoList(h1->next, h2); return h1; } else { h2->next = mergeTwoList(h1, h2->next); return h2; } } };
实现交叉链表 1 2 3 4 5 6-----1 3 5 2 4 6
#include<iostream> using namespace std; struct LinkNode{ int val; LinkNode *next; LinkNode(int x):val(x),next(NULL){}; }; int main(){ LinkNode *head=new LinkNode(0); LinkNode *head1=new LinkNode(0);//建立两个新链表 LinkNode *p=head; for(int i=1;i<6;i++){//原始链表输入 LinkNode *node=new LinkNode(i); p->next=node; p=node; } LinkNode *r=head; LinkNode *r1=head1; while(r!=NULL){//偶数号先连接在新的链表 LinkNode *node1=new LinkNode(r->val); r1->next=node1; r1=node1; r=r->next->next; } LinkNode *q=head->next; while(q->next!=NULL){//奇数号再次链接注意while中的条件防止越界 LinkNode *node1=new LinkNode(q->val); r1->next=node1; r1=node1; q=q->next->next; } r1->next= new LinkNode(q->val);//最后一个数单独放入 while(head1->next){ cout<<head1->next->val<<" "; head1=head1->next; } return 0; }
两个字符串中最长的子串
#include <iostream> #include <vector> #include<algorithm> #include<string> using namespace std; int lenSIZE(string a, string b) { //初始化a.size()*b.size()的二维数组,其数组元初始化为0 vector<vector<int>> num(a.size(),vector<int> (b.size())); int len = 0; for (int i = 0; i < a.size(); i++) {//行 for (int j = 0; j < b.size(); j++) { if (a[i] == b[j]) {//对应位置相等,对角线为子串 if (i > 0 && j > 0) { num[i][j] = num[i - 1][j - 1] + 1;//避免对角线相加的工作 len=max(len, num[i][j]); } else { num[i][j] = 1; len = max(len, num[i][j]); } } } } return len; } int main() { string a = "acbcbcef"; string b = "abcbced"; cout << lenSIZE(a, b) << endl; return 0; }
给定一个字符串求出最长重复子串
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int test() { string s, t1, t2; cin >> s; for(int len = s.length(); len >= 0; len--) { for(int i = 0; i < s.length() - len; i++)//暴力枚举 { t1 = s.substr(i, len);//从i开始的len个字符 t2 = s.substr(i+1); if(t2.find(t1) != string::npos) { cout << t1 << endl; return 0; } } } return 0; } int main() { test(); return 0; }
从字符串S变到T,插入消耗2、删除消耗2、替换消耗3、求最小消耗
#include<iostream> #include<vector> using namespace std; //集合表示 dp[i][j] 对前i个字符进行操作,转换为目标的前j个字符的操作次数 属性->操作次数最小值 //集合划分 dp[i][j]的来源 考虑对第i个字符进行的操作是什么 //1 插入操作 从而相等 所以先让前i个字符变为j-1字符,然后在第i处插入j代表的字符 即dp[i][j-1]+1 //2 删除操作 从而相等 所以先让前i-1个字符变为j字符,然后在第i处删除 即dp[i-1][j]+1 //3 替换操作 从而相等 if(i处等于j处 不需要替换) 即dp[i-1][j-1] // else 需要替换 dp[i-1][j-1]+1 //上述取个最小值即可 int minDistance(string s1, string s2) { int n = s1.size(), m = s2.size(); vector<vector<int>> dp(n+1,vector<int>(m+1)); for(int i = 0; i <= n; i++) dp[i][0] = i*2;//i个字符转化为0个字符 只能一直删i次 for(int j = 0; j <= m; j++) dp[0][j] = j*2;//0个字符转化为j个字符 只能一直插入j次 for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ dp[i][j] = min(dp[i][j-1],dp[i-1][j])+2;//插入 删除 代价为2 dp[i][j] = min(dp[i][j],dp[i-1][j-1] + (s1[i-1]==s2[j-1] ? 0:3));//替换时代价为3 } } cout<<dp[n][m]; return dp[n][m]; } int main(){ string s1="horse"; string s2="ros"; minDistance(s1,s2); return 0; }
数组相关
class Solution { public: int maxProfit(vector<int>& prices) { if(prices.size()<2){ return 0; } int max_p=0; int mincost=prices[0]; for(int i=1;i<prices.size();i++){//只用进行一次循环 if(prices[i]<mincost){//用mincost记录最小投入 mincost=prices[i]; } else if(prices[i]-mincost>max_p){ max_p=prices[i]-mincost; } } return max_p; } };
leetcode 两数之和
class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { vector<int> arr; unordered_map<int,int> mp; for(int i=0;i<nums.size();i++){ mp[nums[i]]=i; } for(int i=0;i<nums.size();i++){ if(mp.count(target-nums[i])>0&&(mp[target-nums[i]]!=i)){//存在和num【i】相加为target的数,且由于不能重复利用这个数组中同样的元素 arr.push_back(i);//不可用mp【nums【i】】,可能元素相同覆盖 arr.push_back(mp[target-nums[i]]); return arr; } } return arr; } };
topk算法
#include<iostream> #include<vector> #include<iomanip> #include<queue> using namespace std; vector<int>heapsort(vector<int> &arr,int k){ priority_queue<int,vector<int>,greater<int>> heap(arr.begin(),arr.end()); arr.resize(k); for(int i=0;i<k;i++){ arr[i]=heap.top(); heap.pop(); } for(int i=0;i<k;i++){ cout<<arr[i]; } return arr; } int main(){ int k=3; vector<int> arr={1,4,6,8,6,5,4,2}; heapsort(arr,k); }
class Solution { public: vector<vector<int>> findContinuousSequence(int target) {//滑动窗口 左闭右开 只能向右移动 int left=1; int right=1; int sum=0; vector<vector<int>> res; while(left<=target/2){//注意循环条件 否则会超时 if(sum<target){ sum+=right; right++; } else if(sum>target){ sum-=left; left++; } else{ vector<int> arr; for(int i=left;i<right;i++){ arr.push_back(i); } res.push_back(arr); sum-=left;//完成一次 继续左边界向右移动 left++; } } return res; } };
class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { int left=0,right=nums.size()-1; vector<int> arr; while(left<right){ if(nums[left]+nums[right]>target){ --right; } else if(nums[left]+nums[right]<target){ ++left; } else { arr.push_back(nums[left]); arr.push_back(nums[right]); return arr; } } return arr; } };
相关文章推荐
- Java/C++面试手撕算法汇总
- C/C++ 笔试、面试题目汇总1——代码相关
- C/C++ 笔试、面试题目汇总1——代码相关
- C/C++ 笔试、面试题目大汇总
- java面试笔试题大汇总 及c/c++面试试题转载
- C/C++ 笔试、面试题目大汇总2
- c++笔试面试大汇总
- C/C++ 笔试、面试题目大汇总
- C/C++ 笔试、面试题目大汇总
- C/C++ 笔试、面试题目大汇总
- 【C++后台开发面试】复习内容整理汇总
- C/C++ 笔试、面试题目大汇总
- C/C++ 笔试、面试题目大汇总2
- C/C++ 笔试、面试题目大汇总
- [面试算法] 剑指Offer代码汇总
- C/C++ 笔试、面试题目大汇总
- [互联网面试笔试汇总C/C++-24] Linux守护进程工作原理和方式-雅虎
- [互联网面试笔试汇总C/C++-7] 堆栈的区别-百度
- C++面试常见题目问与答(汇总二)
- C/C++ 笔试、面试题目大汇总