本篇主要是介绍一些笔试中常用的算法。
文章目录
- 一、二叉树的后序遍历序列
- 二、二叉树中和为某一值的路径(二)
- 三、字符串的排列
- 四、最下的K个数
- 五、连续子数组的最大和
- 六、回文数索引
- 七、把数组排成最下的数
- 八、两个链表的第一个公共结点
- 九、二叉树的深度
- 十、数组中只出现一次的数字
- 十一、和为S的连续正数序列
- 十二、左旋转字符串
- 十三、翻转单词序列
- 十四、按之字形顺序打印二叉树
- 十五、二叉搜索树的第k个结点
一、二叉搜索树的后序遍历序列OJ链接
class Solution {
public:
bool VerifySquenOfBSTHelper(vector<int> sequence,int start, int end)
{
//如果此时start比end大说明此时满足二叉搜索树的条件
if(start>=end)
return true;
int root=sequence[end];//根节点为为遍历数组序列的最后一个元素
int i=start;
while(i<=end&&sequence[i]<root)//查找二叉树中左子树中是否是满足左子树是小于根节点的条件
{
i++;
}
//查找二叉树中右子树是否是满足右子树是大于根节点的条件,如果不满足,则直接返回false
for(int j=i;j<end;j++)
{
if(sequence[j]<root)
return false;
}
return VerifySquenOfBSTHelper(sequence,start,i-1)&&VerifySquenOfBSTHelper(sequence,i,end-1);
}
bool VerifySquenceOfBST(vector<int> sequence) {
//前提条件:如果此时所给的后序遍历数组为空则直接返回false
if(sequence.empty())
return false;
//如果不为空,则进行将后序遍历序列进行分序查找
return VerifySquenOfBSTHelper(sequence,0,sequence.size()-1);
}
};
二、二叉树中和为某一值的路径(二)OJ链接
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
void FindPathDFS(TreeNode*root,int expectNumber,vector<vector<int>>&result,vector<int>&list)
{
if(root==nullptr)
return;
//先进行添加值
list.push_back(root->val);
expectNumber-=root->val;
//将现有结果进行判断
if(expectNumber==0&&root->left==nullptr&&root->right==nullptr)
{
result.push_back(list);
}
//进行深度搜索
FindPathDFS(root->left,expectNumber,result,list);
FindPathDFS(root->right,expectNumber,result,list);
//回退
list.pop_back();
}
vector<vector<int>> FindPath(TreeNode* root,int expectNumber) {
vector<vector<int>> result;
vector<int> list;
if(root==nullptr)
return result;
FindPathDFS(root,expectNumber,result,list);
return result;//返回结果集
}
};
三、字符串的排列OJ链接
class Solution {
public:
vector<string> Permutation(string str) {
vector<string> result;
sort(str.begin(),str.end());//首先利用sort进行排序
do
{
result.push_back(str);
}while(next_permutation(str.begin(),str.end()));//利用STL中的next_permutation进行全排列
return result;
}
};
四、最小K个数OJ链接
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> result;
if(input.size()==0||k==0)
return result;
priority_queue<int,vector<int>> q;//利用大根堆的方式进行
for(int i=0;i<input.size();i++)
{
if(i<k)//将前面4个元素放入堆中
q.push(input[i]);
else
{
if(input[i]<q.top())//如果此时堆顶的数据比下一个大则出堆
{
q.pop();
q.push(input[i]);
}
}
}
//需要将最后堆中的数据放入数组中
for(int i=0;i<k;i++)
{
result.push_back(q.top());
q.pop();
}
return result;
}
};
五、连续子数组的最大和OJ链接
class Solution {
public:
int FindGreatestSumOfSubArray(vector<int> array) {
if(array.size()==0)//如果此时数组中无元素则返回0
return 0;
//子状态:f(i)中连续子数组和最大
//状态间的转移方程:dp[i]=max(dp[i-1]+array[i],array[i]);
//初始化:dp[0]=array[0];max_value=array[0];
//返回max_value;
vector<int> dp;
dp.resize(array.size(),0);
int max_value=array[0];
dp[0]=array[0];
for(int i=1;i<array.size();i++)
{
dp[i]=max(dp[i-1]+array[i],array[i]);
if(max_value<dp[i])
max_value=dp[i];
}
return max_value;
}
};
六、回文数索引 OJ链接
#include<bits/stdc++.h>
using namespace std;
bool IsPalindrome(string &s,int*start,int *end)
{
int i=0;
int j=s.size()-1;
bool result=true;
while(i<=j)
{
if(s[i]!=s[j])
{
result=false;
break;
}
i++;
j--;
}
if(start!=nullptr)//定位此时不是回文串的位置
{
*start=i;
}
if(end!=nullptr)
{
*end=j;
}
return result;
}
int main()
{
int n;
cin>>n;
while(n--)
{
string str;
cin>>str;
int start=0;
int end=str.size()-1;
if(IsPalindrome(str,&start,&end))
{
cout<<"-1"<<endl;
}
else
{
str.erase(end,1);
if(IsPalindrome(str,nullptr,nullptr))//判断是否是回文如果是回文,则删除位置后为回文串,反之如果不是则说明删除start是回文串
{
cout<<end<<endl;
}
else
{
cout<<start<<endl;
}
}
}
return 0;
}
七、把数组排成最小的数OJ链接
class Solution {
public:
static bool cmp(int x,int y)
{
string a=to_string(x);
string b=to_string(y);
return a+b<b+a;
}
string PrintMinNumber(vector<int> numbers) {
//利用sort将小的放到前面
sort(numbers.begin(),numbers.end(),cmp);
string result;
for(int i=0;i<numbers.size();i++)
{
result+=to_string(numbers[i]);
}
return result;
}
};
八、两个链表的第一个公共结点OJ链接
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
//求出两个链表的长度,让长的链表走差距步,再同步走
int GetListLength(ListNode*head)
{
int length=0;
ListNode*cur=head;
while(cur)
{
length++;
cur=cur->next;
}
return length;
}
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
int pHead1Length=0;
int pHead2Length=0;
pHead1Length=GetListLength(pHead1);
pHead2Length=GetListLength(pHead2);
int gap;
if(pHead1Length>pHead2Length)
{
gap=pHead1Length-pHead2Length;
while(gap--)
{
pHead1=pHead1->next;
}
}
else
{
gap=pHead2Length-pHead1Length;
while(gap--)
{
pHead2=pHead2->next;
}
}
while(pHead1&&pHead2)
{
if(pHead1==pHead2)
return pHead1;
pHead1=pHead1->next;
pHead2=pHead2->next;
}
return nullptr;
}
};
九、二叉树的深度OJ链接
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
// void TreeDepthHelper(TreeNode*pRoot,int cur,int&max)
// {
// if(pRoot==nullptr)//如果此时为空则将此时所到达的深度与max进行比较如果比大的话更新max,返回
// {
// if(max<cur)
// {
// max=cur;
// }
// return;
// }
// TreeDepthHelper(pRoot->left,cur+1,max);
// TreeDepthHelper(pRoot->right,cur+1,max);
// }
int TreeDepth(TreeNode* pRoot) {
//利用递归的思路进行深度遍历
// if(pRoot==nullptr)
// return 0;
// return 1+max(TreeDepth(pRoot->left),TreeDepth(pRoot->right));
// }
// if(pRoot==nullptr)
// return 0;
// int depth=0;
// int max=0;
// TreeDepthHelper(pRoot,depth,max);
// return max;
//利用队列的特点进行层序遍历
if(pRoot==nullptr)
{
return 0;
}
queue<TreeNode*> q;
q.push(pRoot);
int depth=0;
while(!q.empty())
{
depth++;
for(int i=0;i<q.size();i++)
{
TreeNode*front=q.front();
q.pop();
if(front->left)
{
q.push(front->left);
}
if(front->right)
{
q.push(front->right);
}
}
}
return depth;
}
};
十、数组中只出现一次数字OJ链接
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
//利用哈希的方式进行遍历
unordered_map<int,int> hashTable;
vector<int> v;
for(int i=0;i<data.size();i++)
{
hashTable[data[i]]++;
}
for(int i=0;i<data.size();i++)
{
if(hashTable[data[i]]==1)
{
v.push_back(data[i]);
}
}
*num1=v[0];
*num2=v[1];
}
};
十一、和为S的连续正数序列OJ链接
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
vector<vector<int>> result;//保留连续的正序列和
int low=1;
int high=2;
while(low<high)//low到high这个区间中的数相加是否是等于sum
{
int total=(low+high)*(high-low+1)/2;//利用等差数列的求和公式求出和
if(sum==total)//如果此时是100则需要将此时的low往后移动查找是否还有这样的序列
{
vector<int> v;
for(int i=low;i<=high;i++)
{
v.push_back(i);
}
result.push_back(v);
low++;
}
else if(total<sum)//如果区间总数没有达到所给的sum需要将high往后移动
{
high++;
}
else//如果此时区间总数达到了所给的sum需要就爱那个low+往后移动
{
low++;
}
}
return result;
}
};
十二、左旋转字符串OJ链接
class Solution {
public:
void LeftRotateStringHelper(string &str)//将首元素保存每一次旋转之后将首元素放在旋转之后的字符串后面
{
char temp=str[0];
int i=0;
for(i=0;i<str.size()-1;i++)
{
str[i]=str[i+1];
}
str[i]=temp;
}
string LeftRotateString(string str, int n) {
// if(str.empty())//如果此时为空直接返回空串
// return str;
// n%=str.size();//该步骤就是为了确保循环的次数是在10之内的次数
// reverse(str.begin(),str.end()-(str.size()-n));//将前n个字符进行反转
// reverse(str.begin()+n,str.end());//后面的字符进行反转
// reverse(str.begin(),str.end());//最后将所有的字符进行反转
// return str;
//利用暴力的方式进行求解
if(str.empty())
return str;
n%=str.size();
while(n--)
{
LeftRotateStringHelper(str);
}
return str;
}
};
十三、翻转单词序列OJ链接
class Solution {
public:
string ReverseSentence(string str) {
if(str.empty())
return str;
int i=0;
int j=0;
while(j<str.size())
{
if(isspace(str[j]))//如果此时为空需要将空格之前的单词进行反转操作同时需要更新i,j
{
reverse(str.begin()+i,str.begin()+j);
j++;
i=j;
}//如果此时不为空格,j往后移动寻找空格
else
{
j++;
}
}
//需要将最后一个单词进行反转操作
reverse(str.begin()+i,str.begin()+j);
//最后需要将整体进行反转操作
reverse(str.begin(),str.end());
return str;
}
};
十四、按之字形顺序打印二叉树OJ链接
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
vector<vector<int> > Print(TreeNode* pRoot) {
vector<vector<int> > result;
if(pRoot == nullptr){
return result;
}
stack<TreeNode*> st; //保存要遍历的节点
queue<TreeNode*> q; //作为临时队列来进行辅助,stack不能既用来出,有用来进
st.push(pRoot);
int dir = 1; //1. 入栈顺序从left开始. 2.入栈顺序从right开始.
vector<int> v;
while(!st.empty()){
int size = st.size();
for(int i = 0; i < size; i++){ //清空本轮stack结构,并遍历,stack本身有逆序的功能
TreeNode *curr = st.top();
st.pop();
v.push_back(curr->val);
TreeNode *first = (dir == 1)?curr->left:curr->right;
TreeNode *second = (dir == 1)?curr->right:curr->left;
//将下一轮访问顺序放入q中
if(first != nullptr)
q.push(first);
if(second != nullptr)
q.push(second);
}
//将本层符合要求的所有节点,入result
result.push_back(v);
//将下一轮访问节点入栈,进行逆序
while(!q.empty()){
st.push(q.front());
q.pop();
}
//一层遍历完毕,就要更改入栈顺序
dir = (dir == 1)? 2 : 1;
v.clear();
}
return result;
}
};
十五、二叉搜索树的第k个结点OJ链接
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param proot TreeNode类
* @param k int整型
* @return int整型
*/
int KthNode(TreeNode* proot, int k) {
// write code here
if(proot==nullptr||k==0)
return -1;
stack<TreeNode*> ST;
TreeNode*node=proot;
do
{
while(node!=nullptr)//将左子树入栈
{
ST.push(node);
node=node->left;
}
if(!ST.empty())//如果栈不为空的话
{
node=ST.top();//将栈顶元素
ST.pop();//将栈顶元素进行出栈
k--;//
if(k==0)//如果此时是第k个结点直接返回
return node->val;
}
node=node->right;//判断右子树
}while(node!=nullptr||!ST.empty());
return -1;
}
};