一.数组
思路一:
1.先将输入字符转换为int数组
2.使用栈从0遍历数组,保存第i位之前可以连续降序的数值
3.使用栈从n-1遍历数组,保存第i位之后可以连续降序的数值
4.及时更新第i个位置前后存在的到达i之前连续降序的数值个数
#include <iostream>
#include <vector>
#include <sstream>
#include <stack>
#include <algorithm>
using namespace std;
vector<int> parseIntArray(string input) {//获取高度数组
vector<int> parsedArray;
stringstream ss(input.substr(1, input.length() - 2));//使用字符串流stringstream处理输入字符串,并把头尾的括号去掉
string item;
while (getline(ss, item, ',')) {//使用getline从stringstream中按逗号分割获取每个字符串元素
parsedArray.push_back(std::stoi(item));//将字符串元素转为数字
}
return parsedArray;
}
void calculateVisibleCounts(const vector<int>& heights, vector<int>& visibleCounts) {
int n = heights.size();
stack<int> stack1, stack2;
for (int i = 0; i < n; i++) {//从左往右找(相当于看第i位左边符合条件的)
visibleCounts[i] += stack1.size();//降序排列的数值,就是从当前位置起栈里的都能看到,当前位置的初始化已经加上
while (!stack1.empty() && stack1.top() <= heights[i]) {//第i位元素是否大于等于前面的元素时,把前面的元素弹出
stack1.pop(); //直到找到一个比当前元素大的值,或者栈空
} //使得栈中的元素全是按降序排列的(从底到顶)
stack1.push(heights[i]);//把当前位置加入
}
for (int i = n - 1; i >= 0; i--) {//从右往左找(相当于看第i位右边符合条件的
visibleCounts[i] += stack2.size();//同理把从右往左能看到的都加上
while (!stack2.empty() && stack2.top() <= heights[i]) {//等于的时候也要弹出,因为等于也看不见
stack2.pop();//也是形成降序排列
}
stack2.push(heights[i]);
}
}
int main() {
string buildings;
while(getline(cin, buildings)){
vector<int> heights = parseIntArray(buildings);
int n = heights.size();
vector<int> visibleCounts(n, 1);//初始化都为1,因为在第i个位置上,必然能看到第i个位置
calculateVisibleCounts(heights, visibleCounts);
cout << "[";
for (int i = 0; i < n; i++) {
cout << visibleCounts[i];
if (i < n - 1)
cout << ",";
}
cout << "]" <<endl;
}
// 输出可见建筑物数量
return 0;
}
思路:根据题意,可以把结果分成四个部分
1.打印空格(空格的数量是递减的,且最后一行不需要)
2.打印字符(相当于左侧字符,前n-1行都只需打印一个,最后一行需打印n个)
3.打印空格(属于中间空格,发现符合2*i-1的规律递增,最后一行无需打印)
4.打印字符(相当于右侧字符,第一行无需打印,2到n-1行打印一个,最后一行打印n-1个
#include<iostream>
#include<sstream>
using namespace std;
int main() {
string str;
while (getline(cin, str)) {
stringstream ss(str);
char midC;
int midI;
ss >> midC;
if (midC == '@')
break;
ss >> midI;
for (int i = 0; i < midI; i++) {
//打印空格
int midP = midI - i-1;
while (midP--)
cout << ' ';
//打印字符
int midS = midI;
if (i != midI - 1)
cout << midC;
else {
while (midS--)
cout << midC;
}
//打印空格
if (i != midI - 1 && i!=0) {
int midC1 = 2 * i-1 ;
while (midC1--)
cout << ' ';
}
//打印字符
if (i == 0) {
cout << endl;
continue;
}
int midC2 = midI;
if (i != midI - 1)
cout << midC;
else {
midC2--;
while (midC2--)
cout << midC;
}
cout << endl;
}
cout << endl;
}
return 0;
}
二.字符串
思路一:直接使用字符串流接收数据,然后赋给string
注意:使用cin获取n之后需要使用getchar() 吸收一个回车,因为第一行只需要一个n
#include<iostream>
#include<sstream>
using namespace std;
int main() {
int n;
cin>>n;
getchar();
string str;
while (n--) {
getline(cin, str);
string res;
stringstream ss(str);
string mid;
while (ss >> mid) {
//大写字母65-90 小写字母97-122
if (mid[0] - 'a' >= 0)//为小写字母
res.push_back(mid[0] - 32);
else
res.push_back(mid[0]);
}
cout << res << endl;
}
return 0;
}
思路:使用双指针把第一个字符的后半部分往后移,腾出第二个字符的位置
#include<iostream>
using namespace std;
string displayString(string& first,string& second){
int lenF=first.size();
int lenS=second.size();
first.resize(lenF+lenS);
int left=lenF-1,right=lenF+lenS-1;//相当于把后一半的字符移动到后面,腾出second的位置
while(left>=(lenF/2)){
first[right--]=first[left--];
}
for(auto it:second){
first[++left]=it;
}
return first;
}
int main(){
int n;
cin>>n;
getchar();
while(n--){
string fisrt;
getline(cin,fisrt);
string second;
getline(cin,second);
cout<<displayString(fisrt,second)<<endl;
}
return 0;
}
思路:简单的奇偶交换,使用双指针指向,然后每次递增2
#include<iostream>
using namespace std;
int main(){
int n;
cin>>n;
getchar();
while(n--){
string str;
getline(cin,str);
int i=0,j=1;
while(i<str.size()-1 && j<str.size()){
char temp=str[i];
str[i]=str[j];
str[j]=temp;
i+=2;
j+=2;
}
cout<<str<<endl;
}
return 0;
}
三.栈和队列
思路:
遍历每一个出栈的数字,遍历到i时,就判断栈中是否入栈到i。
1.还没有入栈到i,先入栈到i,此时出栈合法
2.已经入栈到i后面,判断栈顶元素是否等于出栈元素
-
等于时出栈合法
-
不等于时出栈不合法
#include<iostream>
#include<stack>
#include<sstream>
using namespace std;
int main() {
int n;
while (cin >> n) {
if (n == 0)
break;
getchar();//换到下一行
string str;
getline(cin, str);
stringstream ss(str);
int outNum, intNum = 1;//出栈和入栈下标
stack<int> st;
bool judge = true;//判断是否出栈成功
while (ss >> outNum) {
//cout << outNum << endl;
while (outNum >= intNum) {
st.push(intNum++);
}
//出栈
//cout << st.top() << endl;
if (st.top() == outNum)//当前元素可以出栈成功
st.pop();
else {//当前元素无法出栈
judge = false;
break;
}
}
if (!judge)
cout << "No" << endl;
else
cout << "Yes" << endl;
}
return 0;
}
四.链表
问题:本地编译器和运行都没问题,但是提交之后(show和delete)会多出空格
#include<iostream>
#include<string>
#include<sstream>
#include<vector>
#include<stack>
using namespace std;
struct TreeNode {
int val;
TreeNode* next;
TreeNode() {
val = 0;
next = nullptr;
}
TreeNode(int _val) {
val = _val;
next = nullptr;
}
};
TreeNode* newRoot = new TreeNode();
int List_size = 0;
string get(TreeNode* root, int index) {//获取指定位置元素
if (index > List_size)
return "get fail";
TreeNode* cur = root;
while (--index) {
if (cur->next)
cur = cur->next;
else
return "get fail";
}
return to_string(cur->val);
}
TreeNode* insert(TreeNode* root, int index, int val) {//在指定位置之前插入元素
if (index == 1) {
TreeNode* node = new TreeNode(val);
node->next = newRoot->next;
newRoot->next = node;
cout << "insert OK";
List_size++;
return node;
}
if (index <= 0 || index > List_size) {
cout << "insert fail";
return root;
}
TreeNode* node = new TreeNode(val);
TreeNode* pre = newRoot, * cur = root;
while (--index) {
if (cur->next) {
pre = cur;
cur = cur->next;
}
else {
cout << "insert fail";
return root;
}
}
node->next = pre->next;
pre->next = node;
cout << "insert OK";
List_size++;
return newRoot->next;
}
TreeNode* deleteNode(TreeNode* root, int index) {//删除指定位置的元素
if (index <= 0 || index > List_size) {
cout << "delete fail";
return root;
}
TreeNode* pre = newRoot, * cur = root;
while (--index) {
if (cur->next) {
pre = cur;
cur = cur->next;
}
else {
cout << "delete fail";
return root;
}
}
if (cur->next)
pre->next = cur->next;
else
pre->next = nullptr;
cur = nullptr;
cout << "delete OK";
List_size--;
return newRoot->next;
}
void showNodes(TreeNode* root) {//打印链表中所有元素
if (List_size == 0){
cout << "Link list is empty";
return;
}
TreeNode* cur = root;
while (cur) {
cout << cur->val;
if (cur->next)
cout << " ";
cur = cur->next;
}
}
int main() {
TreeNode* cur = newRoot;
int n, midNum;
cin >> n;
stack<int>st;
while (n--) {//初始化链表
cin >> midNum;
st.push(midNum);
}
List_size = st.size();
while (!st.empty()) {
TreeNode* node = new TreeNode(st.top());
st.pop();
cur->next = node;
cur = node;
}
getchar();//换行
cin >> n;
getchar();
int index, val;
while (n--) {
string mid;
cin >> mid;
if (mid == "get")
{
cin >> index;
cout << get(newRoot->next, index);
}
else if (mid == "insert")
{
cin >> index;
cin >> val;
newRoot->next = insert(newRoot->next, index, val);
}
else if (mid == "delete") {
cin >> index;
newRoot->next = deleteNode(newRoot->next, index);
}
else if (mid == "show") {
showNodes(newRoot->next);
}
cout << endl;
}
return 0;
}
思路:创建,递归反转
#include<iostream>
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode() {
val = 0;
next = nullptr;
}
ListNode(int _val) {
val = _val;
next = nullptr;
}
};
ListNode* newHead = new ListNode(1);
ListNode* judge(ListNode* root) {
if (root->next == nullptr) return root;
ListNode* newRoot = judge(root->next);
root->next->next = root;
root->next = nullptr;
return newRoot;
}
void display(ListNode* root) {
ListNode* cur = root;
while (cur) {
cout << cur->val;
if (cur->next)
cout << " ";
cur = cur->next;
}
}
int main() {
ListNode* cur = newHead;
int n;
while (cin >> n) {
if (n == 0) {
cout << "list is empty" << endl;
continue;
}
int midNum;
while (n--) {//构建链表
cin >> midNum;
//cout << midNum;
ListNode* node = new ListNode(midNum);
cur->next = node;
cur = node;
}
ListNode* head = newHead->next;
ListNode* n1 = head;
newHead = nullptr;
delete newHead;
//display(head);
head=judge(head);
display(head);
cout << endl;
}
return 0;
}
思路:双指针
#include<iostream>
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode() {
val = 0;
next = nullptr;
}
ListNode(int _val) {
val = _val;
next = nullptr;
}
};
void display(ListNode* root) {
ListNode* cur = root;
while (cur) {
cout << cur->val;
if(cur->next)
cout<<" ";
cur = cur->next;
}
cout << endl;
}
void deleteNode(ListNode* root) {
ListNode* p = root, * cur = root->next;
while (cur) {
if (p->val == cur->val) {
if (cur->next) {
p->next = cur->next;
cur = p->next;
}
else {
p->next = nullptr;
cur=nullptr;
}
}
else {
p = cur;
cur = cur->next;
}
}
}
int main() {
int n;
while (cin >> n) {
if (n == 0){
cout<<"list is empty";
break;
}
ListNode* head = new ListNode(0);
ListNode* pre = head;
int midNum;
while (n--) {//创建链表
cin >> midNum;
ListNode* node = new ListNode(midNum);
pre->next = node;
pre = node;
}
display(head->next);
deleteNode(head);
display(head->next);
}
return 0;
}
五.二叉树
思路一:根据前序遍历找出中间节点,然后把两个字符串切割递归遍历
#include<iostream>
#include<sstream>
using namespace std;
struct TreeNode {
char val;
TreeNode* left;
TreeNode* right;
TreeNode() {
val = 0;
left = nullptr;
right = nullptr;
}
TreeNode(int _val) {
val = _val;
left = nullptr;
right = nullptr;
}
};
TreeNode* buildTree(string& PreSort, string& MidSort) {
if (PreSort.size() == 0) return nullptr;
int midValue = PreSort[0];
TreeNode* midNode = new TreeNode(midValue);//中间节点
//找到中间节点下标
int midIndex = 0;
while (MidSort[midIndex] != midValue)
midIndex++;
//分割中序数组(左闭右开)
string leftMidSort(MidSort.begin(), MidSort.begin() + midIndex);
string rightMidSort(MidSort.begin() + midIndex + 1, MidSort.end());
//分割前序数组(左闭右开)
string leftPreSort(PreSort.begin() + 1, PreSort.begin() + leftMidSort.size() + 1);
string rightPreSort(PreSort.begin() + leftMidSort.size() + 1, PreSort.end());
midNode->left = buildTree(leftPreSort, leftMidSort);
midNode->right = buildTree(rightPreSort, rightMidSort);
return midNode;
}
void display(TreeNode* root) {
if (root == nullptr) return;
display(root->left);
display(root->right);
cout << root->val;
}
int main() {
string str;
while (getline(cin, str)) {
stringstream ss(str);
string PreSort, MidSort;
ss >> PreSort >> MidSort;
TreeNode* root = buildTree(PreSort, MidSort);
display(root);
cout << endl;
}
return 0;
}
思路:使用make_pair组合左右节点的下标对应的字符
#include<iostream>
#include<vector>
#include<unordered_map>
#include<sstream>
using namespace std;
struct TreeNode{
char val;
TreeNode*left;
TreeNode*right;
TreeNode(char _val){
val=_val;
left=nullptr;
right=nullptr;
}
};
//节点连接
TreeNode* connectTree(unordered_map<char, pair<char, char>>& nodeMap, char rootValue){
if (rootValue == '0') {
return nullptr;
}
TreeNode* root = new TreeNode(rootValue);
int leftChild = nodeMap[rootValue].first;
int rightChild = nodeMap[rootValue].second;
root->left = connectTree(nodeMap, leftChild);
root->right =connectTree(nodeMap, rightChild);
return root;
}
//遍历
void predisplay(TreeNode*root){
if(root==nullptr) return;
cout<<root->val;
predisplay(root->left);
predisplay(root->right);
}
void middisplay(TreeNode*root){
if(root==nullptr) return;
middisplay(root->left);
cout<<root->val;
middisplay(root->right);
}
void lastdisplay(TreeNode*root){
if(root==nullptr) return;
lastdisplay(root->left);
lastdisplay(root->right);
cout<<root->val;
}
int main(){
int n;
cin >> n;
unordered_map<char, pair<char, char>> nodeMap;
// 先保存输入的数据
vector<char> index = vector<char>(n + 1, '0'); //保存坐标
vector<vector<int>> nums = vector<vector<int>>(n + 1, vector<int>(2, 0));
for (int i = 1; i <= n; i++) {
cin >> index[i] >> nums[i][0] >> nums[i][1];
}
// 生成二叉树
for (int i = 1; i <= n; i++) {
nodeMap[index[i]] = make_pair(index[nums[i][0]], index[nums[i][1]]);
}
TreeNode*root=connectTree(nodeMap, index[1]);
predisplay(root);
cout<<endl;
middisplay(root);
cout<<endl;
lastdisplay(root);
cout<<endl;
return 0;
}
思路一:截取区间创建二叉树,遍历二叉树获取高度
#include<iostream>
using namespace std;
struct TreeNode {
char val;
TreeNode* left;
TreeNode* right;
TreeNode() :val(0), left(nullptr), right(nullptr) {};
TreeNode(int _val) :val(_val), left(nullptr), right(nullptr) {};
};
TreeNode* buildTree(string& strPre, string& strMid) {
if (strPre.size() == 0) return nullptr;
int midValue = strPre[0];
int midIndex = 0;//获取中间节点的下标
while (strMid[midIndex] != midValue)
midIndex++;
//创建中间节点
TreeNode* root = new TreeNode(midValue);
if (strPre.size() == 1) return root;
//分割中序
string leftMid(strMid.begin(), strMid.begin() + midIndex);
string rightMid(strMid.begin() + midIndex+1, strMid.end());
strPre.erase(strPre.begin());
//分割前序
string leftPre(strPre.begin(), strPre.begin() + leftMid.size());
string rightPre(strPre.begin() + leftMid.size(), strPre.end());
root->left = buildTree(leftPre, leftMid);
root->right = buildTree(rightPre, rightMid);
return root;
}
int heightMax = 0;
void sumheight(TreeNode* root, int height) {
if (root == nullptr) return;
heightMax = max(height, heightMax);
sumheight(root->left, height + 1);
sumheight(root->right, height + 1);
}
int main() {
int n;
while (cin >> n) {
int midn = n;
string strPre, strMid;
char mid;
while (n--) {
cin >> mid;
strPre.push_back(mid);
}
while (midn--) {
cin >> mid;
strMid.push_back(mid);
}
TreeNode* root = buildTree(strPre, strMid);
sumheight(root, 1);
cout << heightMax << endl;
}
return 0;
}