您的位置:首页 > 编程语言 > C语言/C++

字节跳动测开面试手撕代码汇总(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;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: