题目来源于牛客
https://www.nowcoder.com/discuss/455003?type=post&order=time&pos=&page=2&channel=-1&source_id=search_post_nctrack
题目以及答案(c++)
1. 剑指 Offer 53 - II. 0~n-1中缺失的数字
思路:
二分法,
代码:
class Solution {
public:
int missingNumber(vector<int>& nums)
{
//二分法
int left=0;
int right=nums.size()-1;
while(left<=right)
{
int mind=(left+right)/2;
//cout<<"left="<<left<< " mind"<<mind<<" right"<<right<<endl;
if(nums[mind]==mind) left=mind+1;
else if (nums[mind]!=mind) right=mind-1;
}
return left;
}
};
2.字节跳动 如何判断一个链表中有环
题目
思路:
快慢指针
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head)
{
ListNode *slow,*fast;
slow=fast=head;
while(fast!=NULL&&fast->next!=NULL)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast) return true;
}
return false;
}
};
3.字节跳动 给你一个数组,求三个数字之和为100
这题就是三数之和是0 改编而来的
题目:
思路:
双指针
代码:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums)
{
sort(nums.begin(),nums.end());
vector<vector<int>> ret_vv;
for(int i=0;i<nums.size();i++)
{
if(i>0&&nums[i]==nums[i-1]) continue;
int left=i+1;
int right=nums.size()-1;
while(left<right)
{
int sum=nums[i]+nums[left]+nums[right];
if(sum==0)
{
vector<int> temp_v;
temp_v.push_back(nums[i]);
temp_v.push_back(nums[left]);
temp_v.push_back(nums[right]);
ret_vv.push_back(temp_v);
while(left<right&&nums[left]==nums[left+1])
{
left++;
}
left++;
while(left<right&&nums[right]==nums[right-1])
{
right--;
}
right--;
}else if(sum>0)
{
right--;
}else if(sum<0)
{
left++;
}
}
}
return ret_vv;
}
};
4.字节跳动 客户端 算法题(合并链表
题目:
思路:
双指针
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2)
{
ListNode node(1);
ListNode * dummpy=&node;
ListNode *tail=dummpy;
while(l1&&l2)//两个链表都不为空
{
if(l1->val<l2->val)
{
tail->next=l1;
tail=l1;
l1=l1->next;
}else
{
tail->next=l2;
tail=l2;
l2=l2->next;
}
}
if(l2)
{
tail->next=l2;
}
if(l1)
{
tail->next=l1;
}
return dummpy->next;
}
};
5.字节跳动 客户端 求岛屿个数 2020.07.18
题目
思路:
floodfill:就是代码中,
1.used每次进行fill时设置为true
2.回溯是不恢复。
代码:
class Solution {
private:
vector<vector<int>> dxy{{1,0},{0,1},{-1,0},{0,-1}};
bool isArea(vector<vector<char>>& grid,int temp_i,int temp_j)
{
if(temp_i<0||temp_i>=grid.size()||temp_j<0||temp_j>=grid[0].size()) return false;
return true;
}
void dfs(vector<vector<char>>&grid,vector<vector<bool>>&used,int current_i,int current_j)
{
for(int i=0;i<dxy.size();i++)
{
int temp_i=current_i+dxy[i][0];
int temp_j=current_j+dxy[i][1];
if(isArea(grid,temp_i,temp_j)&&used[temp_i][temp_j]==false&&grid[temp_i][temp_j]=='1')
{
used[temp_i][temp_j]=true;//这就是flooefill 第一步
dfs(grid,used,temp_i,temp_j);
// used[temp_i][temp_j]=false;这就是flooefill 第二步 回溯过程中不还原状态
}
}
}
public:
int numIslands(vector<vector<char>>& grid)
{
vector<vector<bool>> used(grid.size(),vector<bool>(grid[0].size(),false));
int ret_count=0;;
for(int i=0;i<grid.size();i++)
{
for(int j=0;j<grid[0].size();j++)
{
int start_i=i;
int start_j=j;
if(isArea(grid,start_i,start_j)&&used[start_i][start_j]==false&&grid[start_i][start_j]=='1')
{
ret_count++;
used[start_i][start_j]=true;
dfs(grid,used,start_i,start_j);
}
}
}
return ret_count;
}
};
6.字节跳动 客户端 树找两节点最长距离 2020.07.18
题目:
思路:
这题是归并思想,具体可以看我写的一篇,这种自下而上的代码心得点击获取参考跳转页面
代码:
/**
* 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 {
private:
int maxLen=0;
int dfs(TreeNode* root)
{
if(root==NULL) return 0;
int leftMax=dfs(root->left);
int rightMax=dfs(root->right);
maxLen=max(maxLen,leftMax+rightMax+1);
return max(leftMax,rightMax)+1;//这个是与上层链接的这层节点一下(包含本节点)的最大深度
}
public:
int diameterOfBinaryTree(TreeNode* root) {
if(root==NULL) return 0;
dfs(root);
return maxLen-1;
}
};
7.字节跳动 java 1243534543634交换各位的数字,找出大于目前这个数的最小的一个数。 2020.07.18
这题就是下一个排列
题目:
思路:
我之前写过一篇博客,点击获取参考页面
代码:
class Solution {
//1.4.3.2.0
//2,0,1,3,4
public:
void nextPermutation(vector<int>& nums)
{
//首先找i(从后往前)
int i=nums.size()-1;
while(i>=1&&nums[i-1]>=nums[i])
{
i--;
}
if(i<1)
{
sort(nums.begin(),nums.end());
return ;
}
int left=i-1;
int j=nums.size()-1;
while(left<j&&nums[left]>=nums[j])
{
j--;
}
int right=j;
//肯定存在j,你放心
swap(nums[left],nums[right]);
sort(nums.begin()+left+1,nums.end());//注意交换后 是i+1,nums.size()-1 进行排序(less<>())
}
};
8.字节跳动 后端 对一个奇数位升序,偶数位降序的链表,进行排序,例如 1->100->20->80->40->30 2020.07.18
/**
* 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 {
private:
ListNode* reverseList(ListNode * head)
{
ListNode *m1=nullptr;
ListNode * m2=head;
if(head==nullptr) return m2;
ListNode * m3=head->next;
while(m2)
{
m2->next=m1;
m1=m2;
m2=m3;
if(m3) m3=m3->next;
}
return m1;
}
ListNode* mergeList(ListNode* listSingle, ListNode* listDouble)
{
ListNode *mergeListDummpy=new ListNode(1);
ListNode *mergeTail=mergeListDummpy;
while(listSingle&&listDouble)
{
if(listSingle->val<listDouble->val)
{
mergeTail->next=listSingle;
mergeTail=listSingle;
listSingle=listSingle->next;
}else{
mergeTail->next=listDouble;
mergeTail=listDouble;
listDouble=listDouble->next;
}
}
if(listSingle)
{
mergeTail->next=listSingle;
}
if(listDouble)
{
mergeTail->next=listDouble;
}
return mergeListDummpy->next;
}
public:
ListNode* sortList(ListNode* head)
{
//将奇偶两个链表分离
ListNode *listSingleDummpy=new ListNode(1);
ListNode *singleTail=listSingleDummpy;
ListNode * listDoubleDummpy=new ListNode(1);
ListNode *doubleTail=listDoubleDummpy;
int i=1;
ListNode *tempTail=head;
while(tempTail)
{
if(i%2==1)
{
singleTail->next=tempTail;
singleTail=tempTail;
}else
{
doubleTail->next=tempTail;
doubleTail=tempTail;
}
tempTail=tempTail->next;
i++;//这个就是区分奇偶位置的
}
//将一个链表划分为两个链表后,最后一个节点一定要置空
singleTail->next=nullptr;
doubleTail->next=nullptr;
listDoubleDummpy->next=reverseList(listDoubleDummpy->next);
//开始合并两个链表
return mergeList(listSingleDummpy->next, listDoubleDummpy->next);
}
};
9.字节跳动 后端 算法题:(1)设计sqtr(x) 2020.07.18
题目
思路:
二分法,注意边界条件,边界条件这个还没想好,知道 left徘徊在x的值左右,直接从返回值入手了。
代码
在这里插入代码片
class Solution {
public:
int mySqrt(int x) {
int left=0;
int right=x;
while(left<=right)
{
long long mind=(left+right)/2;
if(mind*mind>=x)
{
right=mind-1;
}else if(mind*mind<x) left=mind+1;
}
return (long long)left*left<=x?left:left-1;
}
};
10字节跳动 后端 2、算法题:(1)判断回文链表 2020.07.18
题目:
思路:
快慢指针,先将链表分为两个基本等长的链表,然后争对第二个链表进行反转,然后从头比较两个链表是否对应的元素相等
代码:
/**
* 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 {
private:
ListNode* reverseList(ListNode* head)
{
ListNode * m1=nullptr;
ListNode * m2=head;
if(head==nullptr) return nullptr;
ListNode * m3=head->next;
while(m2)
{
m2->next=m1;
m1=m2;
m2=m3;
if(m3) m3=m3->next;
}
return m1;
}
public:
bool isPalindrome(ListNode* head)
{
ListNode *slow,*fast;
slow=fast=head;
if(head==nullptr) return true;
fast=head->next;
while(fast!=nullptr&&fast->next!=nullptr)
{
slow=slow->next;
fast=fast->next->next;
}
ListNode * rightHead=slow->next;
// cout<<slow->val<<" "<<slow->next->val<<endl;
slow->next=nullptr;
ListNode * leftHead=head;
//将第二个链表进行翻转
rightHead=reverseList(rightHead);
while(leftHead&&rightHead&&leftHead->val==rightHead->val)
{
leftHead=leftHead->next;
rightHead=rightHead->next;
}
if(leftHead&&rightHead) return false;
return true;
}
};
11字节跳动 后端 (2)对于给定的数据,找出比这个数大的最小回文数(正反读都一样的数),如 12310 -> 12321 2020.07.18
题目:
代码:
12字节跳动 后端 第一道代码:数组只交换一次求最大 2020.07.18
题目
思路:
1,先将数每一位拆成数组
2,若数组为非升序序列,则直接返回原数即可
3,否则,就找到数组中第一次出现升序的位置,从该位置往后找到最后一个最大值max_val及其下标max_ind
4,从数组头开始找第一个比max_val小的数的下标i,交换i与max_ind位置的数即可
需要注意的是我们可以使用to_string stoi 将字符串和int之间转换
还有个特殊情况 (因为后面有个nums.size()-2 防止num只有一个数)
if(num<=9) return num;
另外这里必须加上等号
if(str[j]>=maxValue)//这里必须加上等号 3199 ==》9193 后面一个9才是交换的
{
maxValue=str[j];
maxIndex=j;
}
代码:
class Solution {
public:
int maximumSwap(int num)
{
if(num<=9) return num;
// https://leetcode-cn.com/problems/maximum-swap/solution/c-ti-jie-by-da-li-wang-12/
/*
1,先将数每一位拆成数组
2,若数组为非升序序列,则直接返回原数即可
3,否则,就找到数组中第一次出现升序的位置,从该位置往后找到最后一个最大值max_val及其下标max_ind
4,从数组头开始找第一个比max_val小的数的下标i,交换i与max_ind位置的数即可
*/
string str=to_string(num);
int i=0;
while(i<=str.size()-2&&str[i]>=str[i+1])
{
i++;
}
if(i==str.size()-1) //数字都是递减排序的不用交换
return num;
int maxIndex=i+1;//从第一个不满足str[i]>=str[i+1] 的i+1开始
char maxValue=str[maxIndex];
for(int j=maxIndex;j<str.size();j++)
{
if(str[j]>=maxValue)//这里必须加上等号 3199 ==》9193 后面一个9才是交换的
{
maxValue=str[j];
maxIndex=j;
}
}
i=0;
while(str[i]>=str[maxIndex])
{
i++;
}
swap(str[i],str[maxIndex]);
return stoi(str);
}
};
13字节跳动 后端 第二道代码: 单链表判断是否有环 2020.07.18
题目:
思路:
快慢指针
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head)
{
ListNode *slow,*fast;
slow=fast=head;
while(fast!=NULL&&fast->next!=NULL)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast) return true;
}
return false;
}
};
14字节跳动 客户端 leetcode原题 从一个数 l 一直 与 操作到 r ,怎么做最快,复杂度最小 2020.07.18
题目:
思路:
代码:
15字节跳动 客户端 k个一组反转链表 2020.07.18
题目:
思路:
具体可以参考之前我写的一篇文章点击获取链接
最重要的是记住 有四个指针, pre currentHead nextpre nextHead (这个含义有点欠妥)
记住一点 pre newHead 可以确定 nextpre nextHead ,因此将pre newHead作为进入循环体的已知条件
代码:
/**
* 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 {
ListNode* reverse(ListNode* head)
{
ListNode* m1=nullptr;
ListNode* m2=head;
if(head==nullptr) return m2;
ListNode* m3=head->next;
while(m2!=nullptr)
{
m2->next=m1;
m1=m2;
m2=m3;
if(m3!=nullptr) m3=m3->next;
}
return m1;
}
public:
ListNode* reverseKGroup(ListNode* head, int k)
{
ListNode node(1);
ListNode *dummpy=&node;
ListNode *pre=dummpy;
dummpy->next=head;
ListNode *newhead=head;
ListNode *nextprehead=nullptr;
ListNode *nexthead=nullptr;
while(head!=nullptr)
{
for(int i=1;head!=nullptr&&i<=k-1;i++)
{
head=head->next;
}
if(head==nullptr) return dummpy->next;
// cout<<"zjs666"<<endl;
nextprehead=head;
nexthead=head->next;
nextprehead->next=nullptr;//这必须断开
pre->next=nullptr;//这个只是为了更容易看出来
reverse(newhead);
//将中间反转的拉链条进行拼接
pre->next=nextprehead;
newhead->next=nexthead;
//准备下一次的循环
pre=newhead;
newhead=nexthead;
head=nexthead;//这个是循环体的大循环
}
return dummpy->next;
}
};
16字节跳动 客户端 二叉树的非递归后序遍历 2020.07.18
题目:
思路:
后序是根据非递归前序变化而来的 前序 根左右 》根右左》左右根
关于非递归前序,中序,后序可以参考(中序遍历刚开始不需要入一个节点)
二叉树的非递归先序遍历,非递归中序遍历,非递归后序遍历参考链接
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
private:
vector<int> ret_v;
public:
vector<int> postorderTraversal(TreeNode* root)
{
if(root==nullptr) return ret_v;
stack<TreeNode*> s;
s.push(root);
while(!s.empty())
{
TreeNode *pNode= s.top();
ret_v.push_back(pNode->val);
s.pop();
if(pNode->left) s.push(pNode->left);
if(pNode->right) s.push(pNode->right);
}
reverse(ret_v.begin(),ret_v.end());
return ret_v;
}
};
17字节跳动 后端 括号匹配 2020.07.17
题目:
思路:
用栈实现
代码:
class Solution {
public:
bool isValid(string str)
{
stack<char> s;
for(char c:str)
{
if(!s.empty())
{
if(c==')'&&s.top()=='('||c=='}'&&s.top()=='{'||c==']'&&s.top()=='[')
{
s.pop();
}else
{
s.push(c);
}
}else{
s.push(c);
}
}
return s.empty()?true:false;
}
};
18字节跳动 客户端 按字典序全排列输出 2020.07.17
题目:
思路:
很明显的一道dfs题目 ,下面代码中我用count表示temp中含有的元素个数,如果有重复的元素,直接在进入dfs内部前面加上
if(i>0&&nums[i]==nums[i-1]&&used[i]==false) continue;//代表同层剪枝
代码:
class Solution {
private:
vector<vector<int>> ret_vv;
void dfs(vector<int>& nums,vector<bool>& used, vector<int> &temp,int count)
{
if(count>=nums.size())
{
ret_vv.push_back(temp);
return;
}
for(int i=0;i<nums.size();i++)
{
if(used[i]==true) continue;
used[i]=true;
temp.push_back(nums[i]);
dfs(nums,used,temp,count+1);
temp.pop_back();
used[i]=false;
}
}
public:
vector<vector<int>> permute(vector<int>& nums)
{
vector<bool> used(nums.size(),false);
vector<int> temp;
int count=0;
dfs(nums,used,temp,count);
return ret_vv;
}
};
19字节跳动 客户端 跳台阶 2020.07.17
题目:
思路:
动态规划 状态转移方程 dp[i]=dp[i-1]+dp[i-2]
代码:
class Solution {
public:
int numWays(int n)
{
int mod=1000000007;
if(n==0||n==1) return 1;
vector<int> dp(n+1,0);
dp[0]=1;//这个完全是为了满足dp[2]=2
dp[1]=1;
for(int i=2;i<=n;i++)
{
dp[i]=(dp[i-1]+dp[i-2])%mod;
}
return dp[n];
}
};
20字节跳动 图形/图像岗 一棵完全二叉树的最底层的最右节点 2020.07.17
**题目:**用log(n)算法 找完全二叉树最底层最右边的结点
思路:
一颗二叉树的总结点其实是知道的,设为N。
如上图,总共有15个结点,那么找15号结点只需从根结点开始,向右–向右–向右。
假设只有14个点,那么向右–向右–向左
假设只有13个结点,那么向右—向左—向右
………
可以找到规律,总结点数即为最后一个结点,也就是我们要找的结点。把此结点一直除以2,记录其余数。之后根据余数来找。
例如15号结点,一直除以2,余数分别为(15%2)1、(7%2)1、(3%2)1
例如14号结点,一直除以2,余数分别为(14%2)0、(7%2)1、(3%2)1
…………
把这些余数逆序,从根结点开始找,如果是1,则向右,如果是0则向左。
这样算法时间复杂度为log(n)。
代码:
待定1
21字节跳动 测试 求子集 2020.07.17
题目:
思路:
我们使用dfs,其实也就是每次temp是否加入某一个索引的元素值
代码:
class Solution {
private:
vector<vector<int>> ret_vv;
void dfs(vector<int>& nums,vector<int> temp,int deep)
{
if(deep>=nums.size())
{
ret_vv.push_back(temp);
return;
}
dfs(nums,temp, deep+1);
temp.push_back(nums[deep]);
dfs(nums,temp, deep+1);
}
public:
vector<vector<int>> subsets(vector<int>& nums)
{
int deep=0;
vector<int> temp;
dfs(nums,temp, deep);
return ret_vv;
}
};
22字节跳动 测试 二维有序数组(从左到右递增,从上到下也递增),找目标数(我写的二分法) 2020.07.17
题目:
思路:
从右上角遍历,小的左移,大的下移,越界就是没找到
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target)
{
int i=0;
int j=matrix[0].size()-1;
while(i<matrix.size()&&j>=0)
{
if(matrix[i][j]>target)
{
j--;
}
else if(matrix[i][j]<target)
{
i++;
}
else
return true;
}
return false;
}
};
代码:
23字节跳动 算法 1.判断左右括号是否合理 2020.07.16
同17题?
24字节跳动 算法 2.朴素贝叶斯的算法实现 2020.07.16
题目:
如题
思路:
这个是就是明白概率公式就可以了
代码:
略
25字节跳动 算法 3.两个很大的数据集存着url 找到两个数据集共有的url 2020.07.16
题目:
如题
思路:
通常只说思路就可以了
step1:遍历文件a,对每个url求取hash(url)%1000,然后根据所取得的值将url分别存储到1000个小文件(记为a0,a1,…,a999,每个小文件约300M),为什么是1000?主要根据内存大小和要分治的文件大小来计算,我们就大致可以把320G大小分为1000份,每份大约300M(当然,到底能不能分布尽量均匀,得看hash函数的设计)
step2:遍历文件b,采取和a相同的方式将url分别存储到1000个小文件(记为b0,b1,…,b999)(为什么要这样做? 文件a的hash映射和文件b的hash映射函数要保持一致,这样的话相同的url就会保存在对应的小文件中,比如,如果a中有一个url记录data1被hash到了a99文件中,那么如果b中也有相同url,则一定被hash到了b99中)
所以现在问题转换成了:找出1000对小文件中每一对相同的url(不对应的小文件不可能有相同的url)
step2:
将每两次比较先遍历一个小文件a1,里面的数据用unordered_set s來存,然后b1寻找时,使用 s.count(value) 判断是否有这个url
代码:
略
26字节跳动 算法 4.一个二维矩阵由小到大排列 找target数字
同22题
27字节跳动 算法 5.二叉树按行输出 2020.07.16
题目:
思路:
这其实是层数序遍历,刚开始需要将一个节点放入队列中
代码:
/**
* 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 {
private:
vector<vector<int>> ret_vv;
public:
vector<vector<int>> levelOrder(TreeNode* root)
{
if(root==NULL ) return ret_vv;
queue<TreeNode*> qu;
qu.push(root);;
while(!qu.empty())
{
int n=qu.size();
vector<int> temp_v;
for(int i=0;i<n;i++)
{
TreeNode *pNode= qu.front();
temp_v.push_back(pNode->val);
qu.pop();
if(pNode->left)
{
qu.push(pNode->left);
}
if(pNode->right)
{
qu.push(pNode->right);
}
}
ret_vv.push_back(temp_v);
}
return ret_vv;
}
};
28字节跳动 算法 1.给二叉树前序遍历和中序遍历 输出这个树 2020.07.16
题目:
思路:
递归构造,可以参考我之前写的一篇,前序中序构造,中序后序构造点击获取页面
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
private:
TreeNode * constructTree(vector<int>& preorder,int preLeft,int preRight,unordered_map<int,int> &map,int inLeft,int inRight)
{
if(preLeft>preRight||inLeft>inRight) return nullptr;
TreeNode * root=new TreeNode(preorder[preLeft]);
int index=map[preorder[preLeft]];
root->left=constructTree(preorder,preLeft+1,preLeft+index-inLeft,map,inLeft,index-1);
root->right=constructTree(preorder,preLeft+index-inLeft+1,preRight,map,index+1,inRight);
return root;
}
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
{
int preLeft=0;
int preRight=preorder.size()-1;
unordered_map<int,int> map;
for(int i=0;i<inorder.size();i++)
{
map[inorder[i]]=i;
}
int inLeft=0;
int inRight=inorder.size()-1;
return constructTree(preorder,preLeft,preRight,map,inLeft,inRight);
}
};
29字节跳动 算法 2.翻转链表 2020.07.16
题目:
思路:
后面指针指向前面指针,然后移动,重复这样。。。
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head)
{
ListNode *m1=NULL;
ListNode *m2=head;
if(head==NULL) return NULL;
ListNode *m3=head->next;
while(m2)
{
m2->next=m1;
m1=m2;
m2=m3;
if(m3) m3=m3->next;
}
return m1;
}
};
30字节跳动 算法 3. 把只包含质因子2、3和5的数称作丑数。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。 2020.07.16
题目:
思路:
代码:
31字节跳动 算法 给一个类似树的结构,每个节点都可以有多个节点(不止两个树)然后每个根节点和字节点间的路径不一样,求叶子结点到叶子结点的最大路径 2020.07.16
题目:
思路:
自下而上思想 参考链接
代码:
class Solution {
private:
int maxGap=0;
int dfs(Node* root)
{
if(root==nullptr) return 0;
int childrenMax=0;
for(Node *pNode:root->children)
{
childrenMax=max(childrenMax,dfs(pNode));
}
return childrenMax+1;
}
public:
int preorderTraversal(Node* root)
{
return dfs(root);
}
};
32字节跳动 后端 链表每k个翻转 2020.07.16
同15
33字节跳动 后端 判断单链表有没有环,有的话找入口 2020.07.16
题目:
思路:
首先快慢指针,慢指针走一步,块指针走两步,找到相遇的点,然后 一个指针从头开始每次走一步,然后快指针每次也开始走一步,相遇就是环的入口点
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head)
{
ListNode *slow,*fast;
slow=fast=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast)
{
//有环
ListNode * pNode=head;
while(pNode!=fast)
{
pNode=pNode->next;
fast=fast->next;
}
return pNode;
}
}
return NULL;
}
};
34字节跳动 安卓 . 算法题:根据前中序重构二叉树 2020.07.16
同28
35字节跳动 安卓 算法:螺旋矩阵 2020.07.16
题目:
思路:
这题就不需要使用dfs了
代码:
class Solution {
private:
vector<vector<int>> dxy{{0,1},{1,0},{0,-1},{-1,0}};//右下左上
bool isArea(vector<vector<int>>& matrix,int temp_i,int temp_j)
{
if(temp_i<0||temp_i>=matrix.size()||temp_j<0||temp_j>=matrix[0].size()) return false;
return true;
}
public:
vector<int> spiralOrder(vector<vector<int>>& matrix)
{
vector<int> ret_v;
if(matrix.empty()||matrix[0].empty()) return ret_v;
int start_i=0;
int start_j=0;
vector<vector<bool>> used(matrix.size(),vector<bool>(matrix[0].size(),false));
used[start_i][start_j]=true;
ret_v.push_back(matrix[start_i][start_j]);
int fangxiang=0;
for(int i=0;i<matrix.size()*matrix[0].size()-1;i++)
{
// cout<<"zjs"<<endl;
int temp_i=start_i+dxy[fangxiang][0];
int temp_j=start_j+dxy[fangxiang][1];
if(isArea(matrix,temp_i,temp_j)==false||used[temp_i][temp_j]==true)//不满足时
{
fangxiang=(fangxiang+1)%4;
temp_i=start_i+dxy[fangxiang][0];
temp_j=start_j+dxy[fangxiang][1];
}
used[temp_i][temp_j]=true;//其实不要都可以
ret_v.push_back(matrix[temp_i][temp_j]);
start_i=temp_i;
start_j=temp_j;
}
return ret_v;
}
};
36字节跳动 后台 给定m和n,输出从1~n中任意多个数字,且和为m的组合(数字不能重复使用) 2020.07.16
题目:
题目来源应该是
思路:
就是dfs,加入某个元素,不加入某个元素 两种选择后,然后进行加和判断
代码:
class Solution {
private:
vector<vector<int>> ret_vv;
void dfs( vector<int> &nums,vector<int> temp,int deep)
{
if(deep>=nums.size())
{
//cout<<"zjs"<<endl;
ret_vv.push_back(temp);
return;
}
dfs(nums,temp,deep+1);//不加入当前元素nums[deep]
//加入当前元素nums[deep]
temp.push_back(nums[deep]);
dfs(nums,temp,deep+1);
}
public:
vector<vector<int>> subsets(vector<int>& nums)
{
vector<int> temp;
int deep=0;
dfs(nums,temp,deep);
return ret_vv;
}
};
题目的代码应该是
注意
int current_value = 1;
int current_sum = 0;
题目完整代码:
#include<iostream>
#include<vector>
using namespace std;
//输入n,m,从1-n个数字里输出和为m的组合
class Solution
{
private:
vector<vector<int> > ret_vv;
void dfs(int n, int &targetSum, vector<int> temp, int current_value,int current_sum)
{
/*if (current_value > n)
{
if(current_sum == targetSum) ret_vv.push_back(temp);
return;
}*/
if (current_sum >= targetSum|| current_value > n)
{
if (current_sum == targetSum) ret_vv.push_back(temp);
return;
}
dfs(n, targetSum, temp, current_value + 1, current_sum);
temp.push_back(current_value);
dfs(n, targetSum, temp, current_value + 1, current_sum+current_value);
}
public:
vector<vector<int> > find(int n,int m)
{
vector<int> temp;
int current_value = 1;
int current_sum = 0;
dfs( n, m, temp, current_value, current_sum);
return ret_vv;
}
};
int main()
{
Solution s;
vector<vector<int>> ret_vv;
ret_vv = s.find(9,10);
for (vector<int> temp_v: ret_vv)
{
for (int value:temp_v)
{
cout << value << " ";
}
cout << endl;
}
}
37字节跳动 后台 算法题(求第n个丑数,leetcode原题,难度mid) 2020.07.16
题目:
思路:
代码:
38字节跳动 后台 第一题是求开根号n的值 2020.07.16
同第九题
39字节跳动 后台 第二题是输出交错后的链表(比如链表a-b-c-d-e,交错后输出为a-e-b-d-c) 2020.07.16
题目:
思路:
首先找到中点(偏左偏右无所谓) 将两个链表断开,记得leftList最后需要值空, 第二个链表 reverse 然后从两个链表从头开始拼接
代码:
/**
* 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 {
private:
ListNode* reverseList(ListNode* head)
{
ListNode *m1=nullptr;
ListNode *m2=head;
if(head==nullptr) return nullptr;
ListNode * m3=head->next;
while(m2)
{
m2->next=m1;
m1=m2;
m2=m3;
if(m3) m3=m3->next;
}
return m1;
}
public:
void reorderList(ListNode* head)
{
ListNode *slow,*fast;
slow=head;
if(head==nullptr) return ;
fast=head->next;
while(fast!=nullptr&&fast->next!=nullptr)
{
slow=slow->next;
fast=fast->next->next;
}
ListNode* rightList=slow->next;
slow->next=nullptr;//一定记得最后值空
ListNode* leftList=head;
rightList=reverseList(rightList);
ListNode node(1);
ListNode *dummy=&node;
ListNode *tail=dummy;
int i=1;
while(leftList&&rightList)
{
if(i%2==1)
{
tail->next=leftList;
tail=leftList;
leftList=leftList->next;
}else
{
tail->next=rightList;
tail=rightList;
rightList=rightList->next;
}
i++;
}
if(leftList)
{
tail->next=leftList;
}
if(rightList)
{
tail->next=rightList;
}
head=dummy->next;
return;
}
};
40字节跳动 后台 反转链表 2020.07.16
同29题
41字节跳动 后台 找峰值 2020.07.16
题目:
思路:
方法1.线性查找
if(nums[i]>nums[i+1]) return i;
上面这个代码为什么能够这么做呢?首先题目已知了数组左边界是负无穷,
return nums.size()-1;
为什么默认返回值是这样,题目中就是说至少有一个峰值的意思
方法2.二分查找
代码:
方法一:
class Solution {
public:
int findPeakElement(vector<int>& nums)
{
for(int i=0;i<nums.size()-1;i++)
{
if(nums[i]>nums[i+1]) return i;
}
return nums.size()-1;
}
};
方法二:二分查找
class Solution {
public:
int findPeakElement(vector<int>& nums)
{
//二分查找
int left=0;
int right=nums.size()-1;
while(left<right)
{
int mind=(left+right)/2;
if(nums[mind]<=nums[mind+1]) left=mind+1;
else if(nums[mind]>nums[mind+1]) right=mind;
}
return left;
}
};
42字节跳动 客户端 1. 有两个单链表,其有交叉节点,求交叉节点。 2020.07.16
题目:
思路:
方法一:快慢指针
首先就是长链表多走链表的距离差就可以了,然后另外一个链表开始走,一次比较节点,若走到有个节点是空,则没有交点,否则找到了节点
方法二:我走过的路你也会走
代码:
方法一:快慢指针
略:
方法二:我走过的路你也会走
/**
* 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 * pA=headA;
ListNode * pB=headB;
while(pA!=pB)
{
pA=pA!=NULL?pA->next:headB;
pB=pB!=NULL?pB->next:headA;
}
return pA;
}
};
43字节跳动 客户端 2. LRU算法,给一个整数数组,若LRU的窗口大小是4,求下一个元素进来后剔除哪个元素。 2020.07.15
题目:
思路:
背多分
代码:
class LRUCache {
private:
int m_capacity;
list<pair<int,int> > m_list;
unordered_map<int,list<pair<int,int> > ::iterator> m_map;
public:
LRUCache(int capacity) {
m_capacity=capacity;
}
int get(int key)
{
auto it=m_map.find(key);
if(it==m_map.end())
{
return -1;
}
else
{
m_list.splice(m_list.begin(),m_list,it->second);
return it->second->second;
}
}
void put(int key, int value)
{
auto it=m_map.find(key);
if(it!=m_map.end())//找到了位置中的元素
{
it->second->second=value;
m_list.splice(m_list.begin(),m_list,it->second);
return ;
}
if(m_list.size()==m_capacity)//满了就开始删除节点
{
auto node=m_list.back();//这个node节点就是pair类型了
m_map.erase(node.first);
m_list.pop_back();//删除最后一个
}
//m_list.push_front(make_pair(key,value));//一定要注意是头插法,保持删除元素在后面
m_list.emplace_front(key,value);
m_map[key]=m_list.begin();
}
};
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache* obj = new LRUCache(capacity);
* int param_1 = obj->get(key);
* obj->put(key,value);
*/
44字节跳动 客户端 3. 求最小子数组,leetcode209题。 2020.07.15
题目:
思路:
双指针,滑动窗口
left指向当前节点,right指向下一个节点,sum代表left(包活left)到right(不包right)位置之间的和
注意每次移动right都需要判断
终止条件
while(right<nums.size())
代码:
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums)
{
if(nums.empty()) return 0;
int left=0;
int ret_min=INT_MAX;
int right=0;
int sum=0;
while(right<nums.size())
{
sum=sum+nums[right];
right++;
while(sum>=s)
{
ret_min=min(ret_min,right-left);
sum=sum-nums[left];
left++;
}
}
return ret_min==INT_MAX?0:ret_min;
}
};
45字节跳动 后端 2N的格子 12的格子填满它有多少种方法
题目:
如题
思路:
其实是动态规划
好好想想dp[i]代表 2N的格子 12的格子填满的方法
dp[i]=dp[i-1]+dp[i-2];
dp[1]=1;
dp[2]=2;
代码:
同19 跳台阶
46. 给个数组,找出右边第一个比它大的元素,
题目:
如题
思路:
这题可以用单调栈的思路
首先栈中的元素是不严格单调递减的(后面的比前面的大才弹出)
代码:
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
//找出右边第一个比他大的数,否则返回-1
class Solution
{
public:
vector<int> findRightMax(vector<int> nums)
{
vector<int> ret_v(nums.size(),-1);//循环结束后还在栈中的就是代表没有找到右边最大的,因此我们默认-1
stack<int> s; //一定需要注意栈中存的是下标
for (int i=0;i<nums.size();i++)
{
while (!s.empty() && nums[i] > nums[s.top()])
{
int index = s.top();
ret_v[index] = nums[i];
s.pop();
}
//一定需要注意栈中存的是下标
s.push(i);
}
return ret_v;
}
};
int main()
{
Solution s;
vector<int> ret_v= s.findRightMax({1,2,3,4,5,6});
for (int value:ret_v)
{
cout << value << " ";
}
}
47链表两两反转 2020.07.15
题目:
思路:
前面我们做过了k个链表反转,这个当然可以直接k=2,
但是我们因为是两两交换,所以可以写的更加简单点
while(pre->next!=nullptr&&pre->next->next!=nullptr)
这个while循环中的判断条件很精髓
代码:
/**
* 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* swapPairs(ListNode* head)
{
ListNode node(1);
ListNode* dumpy=&node;
dumpy->next=head;
ListNode* pre=dumpy;
while(pre->next!=nullptr&&pre->next->next!=nullptr)
{
ListNode* start=pre->next;
ListNode* end=pre->next->next;
ListNode* next=end->next;
end->next=start;
start->next=next;
pre->next=end;
pre=start;
}
return dumpy->next;
}
};
48字节跳动 前端 删除链表的倒数第n个 2020.07.15
题目:
思路:
我们熟悉输出倒数第k个节点,现在我们只需要寻找k前面的pre节点即可,
只需要slow从我们辅助头结点dummpy开始走就行了
代码:
/**
* 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* removeNthFromEnd(ListNode* head, int n)
{
// 也就是需要找到这个节点的前驱节点
ListNode * dummpy=new ListNode(1);
dummpy->next=head;
ListNode * pre=dummpy;
ListNode * fast=head;
for(int i=0;i<n;i++)//题目说了n是合理的
{
fast=fast->next;
}
while(fast)
{
pre=pre->next;
fast=fast->next;
}
pre->next=pre->next->next;
return dummpy->next;
}
};
49字节跳动 大数据 算法题1: 请对3个有序数组进行归并排序 2020.07.15
题目:
如题
思路:
就是两两归并,主要还是首先对两个数组进行归并
代码:
class Solution
{
private:
vector<int> merge(vector<int> nums1, vector<int> nums2)
{
vector<int> ret;
int i = 0;
int j = 0;
while (i<nums1.size()&&j< nums2.size())
{
if (nums1[i] < nums2[j])
{
ret.push_back(nums1[i]);
i++;
}
else
{
ret.push_back(nums2[j]);
j++;
}
}
while (i < nums1.size())
{
ret.push_back(nums1[i]);
i++;
}
while (j<nums2.size())
{
ret.push_back(nums2[j]);
j++;
}
return ret;
}
public:
vector<int> getSort(vector<int> nums1, vector<int> nums2, vector<int> nums3)
{
return merge(nums1,merge(nums2, nums3));
}
};
int main()
{
Solution s;
vector<int> ret_v = s.getSort({ 1,2,3 }, { 4,5,6 }, {7,8,9});
for (int value:ret_v)
{
cout << value << " ";
}
}
50字节跳动 大数据 算法题2: 求一个字符串中最长不重复子串的长度 2020.07.15
题目:
思路:
双指针法
代码:
class Solution {
public:
int lengthOfLongestSubstring(string s)
{
int maxlen=0;
unordered_map<int ,int> map;
for(int i=0,j=0;j<s.size();j++)
{
//cout<<"j="<<j<<endl;
map[s[j]]++;
while( map[s[j]]>1)//证明有重复的
{
map[s[i]]--;
i++;
}
//cout<<"maxlen="<<maxlen<<endl;
maxlen=max(maxlen,j-i+1);
}
return maxlen;
}
};
51字节跳动 服务端 给定一个int数组A,数组中元素互不重复,给定一个数x,求所有求和能得到x的数字组合,组合中的元素来自A,可重复使用。 2020.07.15
题目:
思路:
这题可以重复使用,貌似不能用求子集的方法,求子集在36题,36题还可以优化剪枝,
代码:
待定
52字节跳动 后端 手撕代码:Z字型遍历二叉树(剑指offer原题,LeetCode第1553题) 2020.07.15
题目:
思路:
就是层序遍历,将每偶数层reverse一下就可以了。
代码:
/**
* 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 {
private:
vector<vector<int>> ret_vv;
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root)
{
queue<TreeNode*> qu;
if(root==NULL) return ret_vv;
qu.push(root);
int ceng=0;
while(!qu.empty())
{
int n=qu.size();
vector<int> temp;
for(int i=0;i<n;i++)
{
TreeNode *pNode=qu.front();
temp.push_back(pNode->val);
qu.pop();
if(pNode->left)
{
qu.push(pNode->left);
}
if(pNode->right)
{
qu.push(pNode->right);
}
}
ceng++;
if(ceng%2==0)
{
reverse(temp.begin(),temp.end());
}
ret_vv.push_back(temp);
}
return ret_vv;
}
};
53字节跳动 算法 topk 2020.07.15
题目:
思路:
最快的是借助快排 二分加上快排
代码:
class Solution {
int sortIndex(vector<int>& nums,int left,int right)
{
//if(left>=right) return left;
int i=left;
int j=right;
int target=nums[left];
while(i!=j)
{
while(i<j&&nums[j]>=target)
{
j--;
}
while(i<j&&nums[i]<=target)
{
i++;
}
if(i<j)
{
swap(nums[i],nums[j]);
}
}
swap(nums[left],nums[i]);
return i;
}
public:
int findKthLargest(vector<int>& nums, int k) {
int left=0;
int right=nums.size()-1;
int mind=-1;
//cout<<"nums.size()-k="<<nums.size()-k<<endl;
while(mind!=nums.size()-k)//肯定可以找到
{
mind=sortIndex(nums,left,right);
cout<<"mind="<<mind<<endl;
if(mind>nums.size()-k)
{
right=mind-1;
}else if(mind<nums.size()-k)
{
left=mind+1;
}else
{
break;
}
}
return nums[mind];
}
};
54字节跳动 java 手撕平方根 2020.07.15
同第九题
55字节跳动 测试 反转链表? 2020.07.15
同29题
56字节跳动 前端 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 2020.07.15
题目:
思路:
用一个unordered_map来存取就可以了,一个元素不能重复使用
if(it->second!=i)
代码:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target)
{
unordered_map<int ,int> map;//value,index
//采用hash的方式,时间复杂度低一些
for(int i=0;i<nums.size();i++)
{
map[nums[i]]=i;
}
vector<int> v;
for(int i=0;i<nums.size();i++)
{
int target_value=target-nums[i];
auto it=map.find(target_value);
if(it!=map.end())//找到了位置
{
if(it->second!=i)
{
v.push_back(i);
v.push_back(it->second);
break;
}
}
}
return v;
}
};
57字节跳动 后端 算法题1:很大量的int型数,输出前100最大的数(中等) 2020.07.15
58字节跳动 后端 算法题2:单向链表,头尾奇偶交替输出(中等) 2020.07.15
题目:
思路:
将偶链表 reverse 然后再奇数链表 偶链表 交替组成一个新链表
代码:
同39题
59字节跳动 后端 单链表反转 2020.07.15
同29题
60字节跳动 后端 平衡二叉搜索树插入算法 2020.07.15
题目:
思路:
我是自上而下的寻找,然后返回时貌似是自下而上的
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* insertIntoBST(TreeNode* root, int val)
{
if(root==nullptr)
{
TreeNode*node=new TreeNode(val);
return node;
}
if(root->val>val)
{
root->left= insertIntoBST( root->left, val);
}
else root->right= insertIntoBST(root->right,val);
return root;
}
};
61字节跳动 客户端 2. 一个二叉树, 求路径之和。。。。 2020.07.15
题目:
思路:
思路就是从上到下,
注意是叶结点,也就是我们需要到叶结点再做出判断,(无法中途剪枝)
if(root->left==nullptr&&root->right==nullptr)
{
if(targetSum-root->val==0)
{
temp.push_back(root->val);
ret_vv.push_back(temp);
}
return;
}
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
private:
vector<vector<int>> ret_vv;
void dfs(TreeNode* root,vector<int> temp, int targetSum)
{
if(root==nullptr) return ;
if(root->left==nullptr&&root->right==nullptr)
{
if(targetSum-root->val==0)
{
temp.push_back(root->val);
ret_vv.push_back(temp);
}
return;
}
temp.push_back(root->val);
dfs(root->left, temp, targetSum-root->val);
dfs(root->right, temp, targetSum-root->val);
}
public:
vector<vector<int>> pathSum(TreeNode* root, int targetSum)
{
vector<int> temp;
dfs(root, temp, targetSum);
return ret_vv;
}
};
62字节跳动 后台 算法:掷骰子走路,1~6,给定的输入n,走到第n个格子有多少种走法 2020.07.15
题目:
如题
思路:
这题可以用dfs,题目意思就是有无数个骰子,我们需要每次将随机的投出的1-6加上,看是否会等于n,大于n就终止
代码:
#include<iostream>
using namespace std;
class Solution
{
private:
int fact = 0;
void dfs(int n,int sum)
{
if (sum >= n)
{
if (sum == n) fact++;
return;
}
for (int i=1;i<=6;i++)
{
//sum = sum + i; 这行只能写在下面
dfs(n,sum+i);
}
}
public:
int getNumFact(int n)
{
int sum = 0;
dfs(n, sum);
return fact;
}
};
int main()
{
int n;
cin >> n;
Solution s;
int steps=s.getNumFact(n);
cout << "steps="<<steps << endl;
return 0;
}
我们再来看看稍微变化的题目
题目:
思路:
显然是动态规划 ()
//确认状态 dp[i][j] 用i个骰子 组成和为j的组成方法数
//状态转移 方程 dp[i][j]=dp[i-1][j-1]+dp[i-1][j-2]…+dp[i-1][j-5]+dp[i-1][j-6]
//初始状态 dp[1][1]=1 dp[1][2]=1 dp[1][3]=1 dp[1][4]=1 dp[1][5]=1 dp[1][6]=1
//返回值 将所有的dp[n][j]/6^n sort一下即可
代码:
class Solution {
public:
vector<double> dicesProbability(int n)
{
//确认状态 dp[i][j] 用i个骰子 组成和为j的组成方法数
//状态转移 方程 dp[i][j]=dp[i-1][j-1]+dp[i-1][j-2]...+dp[i-1][j-5]+dp[i-1][j-6]
//初始状态 dp[1][1]=1 dp[1][2]=1 dp[1][3]=1 dp[1][4]=1 dp[1][5]=1 dp[1][6]=1
//返回值 将所有的dp[n][j]/6^n sort一下即可
vector<vector<int >>dp(n+1,vector<int>(6*n+1,0));
for(int i=1;i<=6;i++)
{
dp[1][i]=1;
}
for(int i=2;i<=n;i++)
{
for(int j=i;j<=6*i;j++)//第一个j=i是因为 第i个骰子 最小的和是i ,最大的和是 6*i 也就是说 j在【i,6*i】
{
for(int m=1;m<=6;m++) //因为当前和可以是之前的和的+1 + 2 + 3+ 4 +5 +6
{
int leftVaue=j-m;
// if(leftVaue<=0) break;
// if(j-m<i-1) break;
if(i-1<=leftVaue&&leftVaue<=6*(i-1)) //上一个骰子的最小值是i-1 最大值是 6*(i-1)
{dp[i][j]=dp[i][j]+dp[i-1][leftVaue];}// dp[i][j]十多个dp[i-1][leftVaue] 的和
}
}
}
vector<double> ret_v;
for(int i=n;i<=6*n;i++)
{
ret_v.push_back((double)dp[n][i]/pow(6,n));
}
//sort(ret_v.begin(),ret_v.end());
return ret_v;
}
};
63字节跳动 后台 算法:青蛙跳格子,数组里元素表示该位置石头个数,每次跳3-5格,问跳出数组最少踩多少石头。 2020.07.15
题目:
思路:
显然是动态规划
需要注意的是 顶层是指数组越上界的第一个层
状态转移方程h
代码:
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost)
{
vector<int> dp(cost.size()+1,0);
dp[0]=dp[1]=0;
for(int i=2;i<=cost.size();i++)
{
dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
}
return dp[cost.size()];
}
};
64字节跳动 后台 算法:给定链表和k,要求每k个元素翻转一次 2020.07.15
65字节跳动 计算机视觉工程师 做道题吧,LeetCode4:两个有序数组的中位数 2020.07.15
题目:
思路:
最快的当然是二分法
代码:
66字节跳动 后端 算法:找出数组里出现次数大于n/k的数 2020.07.14
题目:
思路:
这题是变体,
代码:
67字节跳动 后端 算法判断树是否对称 2020.07.14
题目:
思路:
方法一:运用递归
dfs(root->left,root->right);
上面这个一定要敢想
方法二:运用层序遍历 代码略
代码:
方法一:运用递归
/**
* 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 {
bool dfs(TreeNode* rootA,TreeNode* rootB)
{
if(rootA==NULL&&rootB==NULL) return true;
if(rootA==NULL||rootB==NULL) return false;
//现在两个都不是空了
if(rootA->val!=rootB->val) return false;
return dfs(rootA->left,rootB->right)&&dfs(rootA->right,rootB->left);
}
public:
bool isSymmetric(TreeNode* root)
{
if(root==NULL) return true;
return dfs(root->left,root->right);
}
};
68字节跳动 客户端 11.手撕代码:1)给定数组,求连续子串的最大和 2020.07.14
字节跳动 客户端 2)用两个栈实现队列 2020.07.14
字节跳动 客户端 10.手撕代码:1)给定一个二维数组,从左到右,从上到下都是递增的,查找某个元素 2020.07.14
字节跳动 客户端 2)给定一个矩阵,每次只能向右或向下走,从左上角开始到右下角一共有多少种走法 2020.07.14
字节跳动 客户端 ,第一题就是给一个矩阵,从右上角往左下角一层一层斜着遍历,类似于这样: 2020.07.14
字节跳动 客户端 层次遍历二叉树 2020.07.14
字节跳动 客户端 leetcode 236 2020.07.14
字节跳动 客户端 leetcode 62, 2020.07.14
字节跳动 服务端 1.给一个正整数,表示成一个或多个不同的正整数的和,输出所有的解决方案(深搜,但是我实现的时候写的不好) 2020.07.14
字节跳动 服务端 2.给一个n*n的方阵,螺旋填入数字 2020.07.14
字节跳动 android (手撕)1:[2,3] 表示 孩子和父母。输入一组这样的数据, 给两个数,问是否有共同祖先。 2020.07.14
字节跳动 后端 力扣 124. 2020.07.14
字节跳动 后端 第二题:二叉树的左视图 2020.07.14
字节跳动 后台 第一题,一个int数组,找出两个异或最大的数字,时间要求O(n) 2020.07.14
字节跳动 后台 第二题,四个int数组,从每个数组里边挑一个数,加起来等于指定数,要求打印出所有非重复的组合,要求最大n2。 2020.07.14
字节跳动 java 代码题:不含重复字符的最长子串(leetcode原题) 2020.07.14
字节跳动 后端 2.最长上升子序列的状态转移,时间复杂度 2020.07.14
字节跳动 后端 给出前序和中序数组,生成后序数组 2020.07.14
字节跳动 后端 11.算法题:给一棵二叉树和一个整数,要求输出二叉树中路径和等于这个整数的路径,如 2020.07.14
字节跳动 后端 1。算法题,两个链表了类型的整数求和,如1->2->5与3->6求和得到1->4->1。用栈或者反转链表 2020.07.13
字节跳动 后端 算法题:找波谷数; 2020.07.13
字节跳动 后端 算法题:复制带随机指针的单向链表; 2020.07.13
字节跳动 后端 14. 算法题:找到两个链表的公共节点 2020.07.13
字节跳动 后端 1. 给定两个单链表,判断是否有公共节点 2020.07.13
字节跳动 后端 3. 求字符数组的全排列(用的交换的方式,但是面试官问思路却有点紧张,没回答好,然后他问我leetcode刷了多少道题,八成认为我是直接背的题了,难受) 2020.07.13
字节跳动 后端 查找有序数组中一个目标值出现的第一次位置,没有找到返回 -1 2020.07.13
字节跳动 后端 5. 算法:滑动窗口寻找满足的字符串 2020.07.13
字节跳动 后端 爬楼梯 2020.07.13
字节跳动 前端 leetcode 93 没写出来。。面试官说我思绪混乱 导致后面脑子空白 2020.07.13
字节跳动 前端 二叉树层序遍历 2020.07.13
字节跳动 后端 说思路:实现一个栈,o(1)时间找最大值 2020.07.13
字节跳动 后端 写代码:矩阵从左上到右下找最小路径 2020.07.13
字节跳动 后端 说思路:删除单链表的倒数第k个节点 2020.07.13
字节跳动 客户端 编程:判断两个链表是否相交并返回交点; 2020.07.13
字节跳动 测试 代码:无重复最长字串 2020.07.13
字节跳动 测试 10、算法:求数组中升序的子序列 2020.07.13
字节跳动 测试 11、算法:两个链表找公共节点 2020.07.13
字节跳动 前端 Merge 两个有序的链表 2020.07.13
字节跳动 ios 1. 如何用两个栈实现一个队列?如何优化前面说的那种思路? 2020.07.13
字节跳动 ios 2. 编程题:上台阶(那个简单的fabonacci)然后就又来了一道 2020.07.13
字节跳动 ios 3. 编程题:区间合并求并集 2020.07.13
字节跳动 ios 算法题:连续子数组的最大和 2020.07.13
字节跳动 ios 1. 二分查找在升序数组中找出绝对值最小的那个数 2020.07.13
字节跳动 ios 2. 8个桶(每个桶只能放一个球),5个球,三个连续的情况有几种。一般情况下呢 2020.07.13
字节跳动 后端 merge k list 2020.07.13
字节跳动 客户端 LeetCode 25. K个一组反转链表 2020.07.13
字节跳动 客户端 LeetCode 53.最大子序和 2020.07.13
字节跳动 客户端 给定一个包含大写英文字母和数字的句子,找出这个句子所包含的最大的十六进制整数,返回这个整数的值。数据保证该整数在int表示范围内。 2020.07.13
字节跳动 后端 01矩阵最大正方形,经典题了,dp选左上最小+1,随便写了一下,没让跑test. 2020.07.13
字节跳动 后端 二叉树找target路径 2020.07.13
字节跳动 后端 二叉树转单链表,常规题,递归一下完事了. 2020.07.13
字节跳动 后端 算法题:从左上角走到右下角有多少种不同的路线 2020.07.13
字节跳动 C++客户端 10.leetcode 奇偶链表 2020.07.12
字节跳动 C++客户端 二进制中1的个数 2020.07.12
字节跳动 C++客户端 反转字符串 2020.07.12
字节跳动 游戏客户端 字符串数组两个字符串的最小距离(easy) 2020.07.12
字节跳动 游戏客户端 做题,数组中和最大的连续子数组(mid) 2020.07.12
字节跳动 客户端 189. 旋转数组 2020.07.12
字节跳动 游戏客户端 手撕 无序数组两数之和 2020.07.12
字节跳动 游戏客户端 手撕代码 两个栈实现队列 2020.07.12
字节跳动 游戏客户端 手撕代码 实现洗牌算法 2020.07.12
字节跳动 算法 二叉树子路径和为k的路径个数 2020.07.12
字节跳动 算法 1. 求和为k的子数组个数 2020.07.12
字节跳动 算法 2. 判断是否存在个数超过数组长度一半的数 2020.07.12
字节跳动 客户端 10、简化路径(算法提) 2020.07.12
字节跳动 客户端 11、二叉树的右视图(算法题) 2020.07.12
字节跳动 andriod 代码题:旋转数组 2020.07.12
字节跳动 andriod 代码题:两数相加(链表,要求原地实现,空间复杂度O(1),这个犯蠢撕了好久结果还是靠强行打印发现的问题) 2020.07.12
字节跳动 andriod 代码题:a) 螺旋遍历矩阵 2020.07.12
字节跳动 andriod ;b)(变种)原地旋转图像 2020.07.12
字节跳动 服务端 算法题 反转链表(白给) 2020.07.12
字节跳动 后端 两个有序链表合并 2020.07.12
字节跳动 后端 给定2D矩阵,求里面1构成的正方形的最大面积。 2020.07.12
字节跳动 后端 算法题:接雨水 2020.07.12
字节跳动 前端 14.找出两个链表的交叉点( 2020.07.12
字节跳动 客户端 10.手撕代码:从无序数组中找到右边第一个大的数(与leetcode 739 每日体温类似) 2020.07.12
字节跳动 后端 22.抛硬币(一个0.3 一个0.7 如何保证公平) 2020.07.12
字节跳动 后端 23 z字形打印二叉树 2020.07.12
字节跳动 后端 - 一颗搜索二叉树有两个节点是颠倒的,恢复成正确的 2020.07.12
字节跳动 后端 - 单链表高位在前、低位在后,大数计算 2020.07.12
字节跳动 后端 - 阶乘 2020.07.12
字节跳动 后端 - 一个有序、有重复元素数组找到有多少满足 a + b = target的 2020.07.12
字节跳动 前端 1.斐波那契 递归实现/dp实现/空间优化 2020.07.11
字节跳动 前端 . 算法题 找出sum大于等于target的最短连续数组的长度 要通过所有测试数据 (找bug找半天,面试官一直温柔的说别着急哈哈) 2020.07.11
字节跳动 测试 10.代码:链表的逆序输出 2020.07.11
字节跳动 测试 11.代码:判断回文 2020.07.11
字节跳动 C++客户端 两两反转链表 2020.07.10
字节跳动 C++客户端 算法:判断两个链表是否相交 2020.07.10
字节跳动 C++客户端 算法:查找二叉树中两个节点的最近公共祖先 2020.07.10
字节跳动 前端 7.算法:合并有序数组 2020.07.10
字节跳动 前端 12 算法:逆序输出数字。 2020.07.10
字节跳动 后端 手撕:层序遍历 2020.07.10
字节跳动 后端 二叉树中序遍历 2020.07.10
字节跳动 后端 手撕 lru 2020.07.10
字节跳动 算法 第K大个数 2020.07.10
字节跳动 算法 链表找环 2020.07.10
字节跳动 算法 合并数组 2020.07.10
字节跳动 后端 编程题:字符串转换为整数,leetcode第67题 2020.07.10
字节跳动 后端 3 sum 2020.07.10
字节跳动 客户端 字符串反转 2020.07.10
字节跳动 后端 先问两个无序数组怎么找交集。 2020.07.10
字节跳动 客户端 手撕数组A-数组B 2020.07.10
字节跳动 客户端 手撕旋转矩阵90度 2020.07.10
字节跳动 c++、 手撕代码 求m个数中最大的n个数 2020.07.10
字节跳动 服务端 7.手撕代码,一道旋转链表的题目,leetcode easy水平 2020.07.10
字节跳动 服务端 8.手撕代码,一道矩阵相乘,也很简单。 2020.07.10
字节跳动 算法 给定一个数组,求连续子序列乘积为完全平方数的最大长度 2020.07.10
字节跳动 算法 判断给定序列是否为二叉搜索树的前序遍历 2020.07.10
字节跳动 前端 算法题:数组去重 2020.07.10
字节跳动 前端 爬楼梯 2020.07.10
字节跳动 后端 算法题,最长连续相同字符的子串 2020.07.10
字节跳动 后端 写个题,每K个节点翻转链表 2020.07.10
字节跳动 后端 1.原题,字符串全排列 2020.07.09
字节跳动 后端 2.原题,二叉树的最大路径和 2020.07.09
字节跳动 后端 1、类似于并查集的问题,最终求连通分量的数量 2020.07.09
字节跳动 客户端 算法题 镜像二叉树 2020.07.09
字节跳动 测试 算法题: leetcode1636 2020.07.09
字节跳动 测试 我一道leetcode 32 2020.07.09
字节跳动 测试 我一道leetcode 1 2020.07.09
字节跳动 测试 LeetCode 20 有效的括号 2020.07.09
字节跳动 测试 平衡二叉树 2020.07.09
字节跳动 测试 ,二叉树遍历 2020.07.09
字节跳动 后台 回文串判断 2020.07.09
字节跳动 后台 二叉搜索树转链表 2020.07.09
字节跳动 后台 二叉树求和leetcode129-讲一下时间复杂度 2020.07.09
字节跳动 后台 1)求链表的倒数第k个节点 2020.07.09
字节跳动 后台 (2)序列化和反序列化二叉树 2020.07.09
字节跳动 后台 (3)求数组的极值点,找出一个满足的就行(二分查找) 2020.07.09
字节跳动 后台 前序遍历和中序遍历重构二叉树 (不给用HashMap 好在做出来了) 2020.07.09
字节跳动 后台 算法题:判断回文链表(中间拆分两条链表 后面的反转链表 对比数值是否相等) 2020.07.09
字节跳动 后台 算法题:奇数位升序偶数位降序的链表要求时间O(n)空间O(1)的排序?(奇偶拆分 偶链反转 归并merge) 2020.07.09
字节跳动 测试 手撕代码:求一个数组的所有子集 2020.07.09
字节跳动 测试 手撕代码:驼峰数组最大值 2020.07.09
字节跳动 客户端 问了一道链表反转; 2020.07.09
字节跳动 客户端 1、力扣原题113 路径综合 2020.07.09
字节跳动 客户端 2、给定一个升序数组,可能会有重复的数字,将数组里的数平方后,有多少不同的数。 2020.07.09
字节跳动 前端 二叉树所有根到叶子节点路径上所有节点,组成的数字之和 2020.07.08
字节跳动 后端 手撕代码:链表加法 2020.07.08
字节跳动 客户端 手写算法:链表合并 2020.07.08
字节跳动 客户端 手写算法:判断一棵树是否是镜像树 2020.07.08
字节跳动 前端 8、 算法题:判断给定的一颗树是否是 二叉查找树 2020.07.08
字节跳动 前端 9、算法题:给定一个数字数组,及数字出现次数, 2020.07.08
字节跳动 客户端 如何判断一颗树是否是完全二叉树 2020.07.08
字节跳动 客户端 lru 2020.07.08
字节跳动 ios 算法题:求k大数 2020.07.08
字节跳动 ios leetcode1 两数之和 2020.07.08
字节跳动 ios 剑指offer 62 圆圈中剩下的数字(约瑟夫环问题) 2020.07.08
字节跳动 ios leetcode 41 缺失的第一个正数 2020.07.08
字节跳动 前端 输出数组第k大元素 2020.07.08
字节跳动 服务端 括号匹配 2020.07.08
字节跳动 后端 链表的两两翻转 2020.07.08
字节跳动 后端 LRu 2020.07.08
字节跳动 测试 算法:返回一棵树的最大叶节点距离 2020.07.07
字节跳动 测试 对含有重复数字的数组去重并排序,手撕快排 2020.07.07
字节跳动 测试 算法:两个大数字符串求和输出字符串 2020.07.07
字节跳动 测试 lru 2020.07.07
字节跳动 后端 一面:最大连续子序列和和回文链表 2020.07.07
字节跳动 后端 二面:一个奇数位升序、偶数位降序的单向无环链表,排成一个有序链表 2020.07.07
字节跳动 后端 三面:S型打印二叉树,两条单向链表的相交节点,任意数组中的第一个缺失的正整数 2020.07.07
字节跳动 客户端 字符串反转 2020.07.07
字节跳动 测试 来个简单的—第一题:求二叉树最大长度 2020.07.07
字节跳动 测试 第二题:用String存两个很长的数,求和 2020.07.07
字节跳动 后端 1. 第一题 判断是否回文链表 2020.07.07
字节跳动 后端 2. 第二题 求逆数对 2020.07.07
字节跳动 后端 3.第三题 动态规划 2020.07.07
字节跳动 后端 1.第一题 最大化股票交易 2020.07.07
字节跳动 后端 2.第二题 最大化股票交易(有限交易) 2020.07.07
字节跳动 客户端 手撕代码 反转链表。 2020.07.07
字节跳动 测试 7.代码:驼峰字符串问题 2020.07.07
字节跳动 后台 算法题:滑动窗口匹配字符串 2020.07.07
字节跳动 前端 1. 实现斐波纳西数列( 2020.07.07
字节跳动 算法 用两个栈实现一个队列 2020.07.07
字节跳动 算法 一个list,一个target,求list中两数之和等于target的所有组合,list中有重复的,算medium吧。 2020.07.07
字节跳动 算法 1. Leetcode124 2020.07.07
字节跳动 后端 补充:8. 大数问题中的topK问题 2020.07.07
字节跳动 后端 补充:9. 给整数数组做数字次数统计,答unordered_map,让我再想其他方法,不会。 2020.07.07
字节跳动 后端 1.给你一个数组和一个target,找出和是target整数倍的连续子串 2020.07.07
字节跳动 后端 2.一个括号字符串,找出最长合法长度(写完了,优化一下,优化了) 2020.07.07
字节跳动 算法 子序最大和(要求子序列长度大于等于k) 2020.07.07
字节跳动 后端 LC128 2020.07.07
字节跳动 客户端 找链表交点, 2020.07.07
字节跳动 客户端 1. 判断二叉树是否镜像 2020.07.07
字节跳动 客户端 2. 给一个分数n/m,如果这个分数是无线循环小数,找出循环位。 2020.07.07
字节跳动 客户端 3. I am student 返回 student am I 2020.07.07
字节跳动 客户端 6.先升后降数组,找峰值的坐标,二分法 2020.07.07
字节跳动 测试 5. 撕代码环节:题目为leetcode第三题,求最长连续不含重复字符子串 2020.07.07