题目列表
- 二叉树遍历非递归
- 2Sum,3Sum问题
- 最长无重复子字符串
- KMP算法
1、二叉树遍历非递归
先序
void PreOrder_Nonrecursive1(BiTree* T) //先序遍历的非递归
{
if(!T)
return ;
stack<BiTree*> s;
BiTree* curr = T;
while(curr != NULL || !s.empty())
{
while(curr != NULL)
{
cout<<curr->data<<" ";
s.push(curr);
curr = curr->lchild;
}
if(!s.empty())
{
curr = s.top();
s.pop();
curr = curr->rchild;
}
}
}
中序
void InOrderTraverse1(BiTree* T) // 中序遍历的非递归
{
if(!T)
return ;
BiTree* curr = T; // 指向当前要检查的节点
stack<BiTree*> s;
while(curr != NULL || !s.empty())
{
while(curr != NULL)
{
s.push(curr);
curr = curr->lchild;
}//while
if(!s.empty())
{
curr = s.top();
s.pop();
cout<<curr->data<<" ";
curr = curr->rchild;
}
}
}
后序
void PostOrder_Nonrecursive1(BiTree* T) // 后序遍历的非递归
{
stack<BiTree*> S;
BiTree* curr = T ; // 指向当前要检查的节点
BiTree* previsited = NULL; // 指向前一个被访问的节点
while(curr != NULL || !S.empty()) // 栈空时结束
{
while(curr != NULL) // 一直向左走直到为空
{
S.push(curr);
curr = curr->lchild;
}
curr = S.top();
// 当前节点的右孩子如果为空或者已经被访问,则访问当前节点
if(curr->rchild == NULL || curr->rchild == previsited)
{
cout<<curr->data<<" ";
previsited = curr;
S.pop();
curr = NULL;
}
else
curr = curr->rchild; // 否则访问右孩子
}
}
void PostOrder_Nonrecursive(BiTree* T) // 后序遍历的非递归 双栈法
{
stack<BiTree*> s1 , s2;
BiTree* curr ; // 指向当前要检查的节点
s1.push(T);
while(!s1.empty()) // 栈空时结束
{
curr = s1.top();
s1.pop();
s2.push(curr);
if(curr->lchild)
s1.push(curr->lchild);
if(curr->rchild)
s1.push(curr->rchild);
}
while(!s2.empty())
{
printf("%c ", s2.top()->data);
s2.pop();
}
}
2、2Sum,3Sum问题
2sum问题
Given nums = [2, 7, 2, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
方法:排序,使用左右指针,复杂度为nlogn
class Solution {
public:
vector<int> TwoSum(vector<int> &a, int num) {
vector<int> result;
sort(a.begin(), a.end());//vector中sort函数使用的是快排,时间复杂度为NlogN
int len = a.size();
int low = 0;
int high = len - 1;
while (low < high) {
if (low == high)
break;
int sum = a[low] + a[high];
if (sum < num)
low++;
else if (sum > num)
high--;
else {
result.push_back(a[low]);
result.push_back(a[high]);
low++;
high--;
}
}
for (int i = 0; i < result.size(); i++) {
cout << result[i] << endl;
}
return result;
}
};
int main() {
Solution st;
vector<int> a = {2, 5, 3, 6, 1};
st.TwoSum(a, 7);
}
3sum问题
For example, given array S = [-1, 0, 1, 2, -1, -4],
A solution set is:[ [-1, 0, 1], [-1, -1, 2]]。
方法
class Solution {
public:
vector<vector<int>> ThreeSum(vector<int> &a) {
vector<vector<int>> result;
sort(a.begin(), a.end());
int len = a.size();
for (int i = 0; i < len; i++) {
int target = -a[i];//对当前数取相反数
int low = i + 1;
int high = len - 1;
while (low < high) {
if (low == high)
break;
int sum = a[low] + a[high];
if (sum > target)
high--;
else if (sum < target)
low++;
else {
vector<int> tmp(3, 0);
tmp[0] = a[i];
tmp[1] = a[low];
tmp[2] = a[high];
result.push_back(tmp);
while (low < high && a[low] == tmp[1])//去除重复元素
low++;
while (low < high && a[low] == tmp[2])
high--;
}
}
while (i + 1 < len && a[i + 1] == a[i])//若相邻两数相等,可跳过后面那个数
i++;
}
return result;
}
};
3、最长无重复子字符串
例子:abcabcd->abc->3
#include<map>
int lengthOfLongestSubstring(string s) {
int ret = 0;
map<char, int> m;
int start = 1;
for (int i = 1; i <= s.length(); i++)
{
char c = s[i - 1];
if (m[c] >= start)//有重复字符出现时
{
start = m[c] + 1;
m[c] = i;
}
else//非重复字符时
{
m[c] = i;
ret = max(ret, i - start + 1);
}
}
return ret;
}
4、KMP算法
这里是引用
在这里插入代码片
5、动态规划
常见动态规划问题:
装配站问题、背包问题、最长公共子序列
动态规划问题四个步骤:
1、定义最优子问题
2、定义状态s[i,j]
3、定义决策、状态转换方程
4、确定边界条件
1.最长公共子序列长度
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int lcs(string str1, string str2) {
int len1 = str1.size();
int len2 = str2.size();
int dp[len1 + 1][len2 + 1];
for (int i = 0; i <= len1; i++) {
for (int j = 0; j <= len2; j++) {
if (i == 0 || j == 0)
dp[i][j] = 0;
else if (str1[i - 1] == str2[j - 1])
dp[i][j] = dp[i - 1][j - 1] + 1;
else
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
cout << dp[len1][len2] << endl;
return dp[len1][len2];
}
int main() {
string s1("13456778");
string s2("357486782");
lcs(s1, s2);
return 0;
}
2.最长公共子串长度
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int lcs2(string str1, string str2) {
int len1 = str1.size();
int len2 = str2.size();
int dp[len1 + 1][len2 + 1];
int result = 0;
for (int i = 0; i <= len1; i++) {
for (int j = 0; j <= len2; j++) {
if (i == 0 || j == 0)
dp[i][j] = 0;
else if (str1[i - 1] == str2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
result = max(dp[i][j], result);
} else
dp[i][j] = 0;
}
}
cout << result << endl;
return result;
}
int main() {
string s1("13456778");
string s2("357486782");
lcs2(s1, s2);
return 0;
}
3.最长回文串