目录
面试题28:对称二叉树
1.剑指Offer
面试题28:对称二叉树
题目描述:请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
思路:递归和遍历
代码:
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{
return isSymmetricalCore(pRoot,pRoot);
}
bool isSymmetricalCore(TreeNode* pRoot1,TreeNode* pRoot2){
if(pRoot1==nullptr&&pRoot2==nullptr){
return true;
}
if(pRoot1==nullptr||pRoot2==nullptr){
return false;
}
if(pRoot1->val!=pRoot2->val){
return false;
}
return isSymmetricalCore(pRoot1->left,pRoot2->right)&&isSymmetricalCore(pRoot1->right,pRoot2->left);
}
};
面试题37:序列化二叉树
题目描述:请实现两个函数,分别用来序列化和反序列化二叉树
思路:前序遍历+递归
代码:
class Solution {
public:
char* Serialize(TreeNode *root) {
if(root==nullptr) return NULL;
string str;
Serialize(root,str);
char *res=new char[str.length()+1];
int i=0;
for(;i<str.length();i++){
res[i]=str[i];
}
res[i]='\0';
return res;
}
void Serialize(TreeNode *root,string &str){
if(root==nullptr){
str+='#';
return;
}
string r=to_string(root->val);
str+=r;
str+=',';
Serialize(root->left,str);
Serialize(root->right,str);
}
TreeNode* Deserialize(char *str) {
if(str==NULL) return NULL;
TreeNode* res=Deserialize(&str);
return res;
}
TreeNode* Deserialize(char **str) {
if(**str=='#'){
++(*str);
return NULL;
}
int number=0;
while((**str)!='\0'&&(**str)!=','){
number=number*10+((**str)-'0');
++(*str);
}
TreeNode* root=new TreeNode(number);
if(**str=='\0'){
return root;
}
else{
++(*str);
}
root->left=Deserialize(str);
root->right=Deserialize(str);
return root;
}
};
2.华为机试题
例1:句子逆序
题目描述:
将一个英文语句以单词为单位逆序排放。例如“I am a boy”,逆序排放后为“boy a am I”
所有单词之间用一个空格隔开,语句中除了英文字母外,不再包含其他字符
接口说明
/**
* 反转句子
*
* @param sentence 原句子
* @return 反转后的句子
*/
public String reverse(String sentence);
输入描述:
将一个英文语句以单词为单位逆序排放。
输出描述:
得到逆序的句子
示例1
输入
I am a boy
输出
boy a am I
代码:
方法1:reverse函数,先整体反转再局部反转
#include <iostream>
#include <algorithm> #reverse函数需要包含的头文件
using namespace std;
int main(){
string str;
while(getline(cin,str)){
reverse(str.begin(),str.end());
string::iterator left=str.begin();
for(string::iterator iter=str.begin();iter!=str.end()+1;iter++){
if(iter==str.end()||*iter==' '){
reverse(left,iter);
left=iter+1;
}
}
cout << str << endl;
}
return 0;
}
方法2:stringstream
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main(){
string s;
while(getline(cin,s)){
stringstream ss(s);
string res="",tmp;
while(ss>>tmp){
if(res==""){
res=tmp;
}
else{
res=tmp+" "+res;
}
}
cout << res << endl;
}
return 0;
}
方法3:逆序扫描,保存每个单词,遇到空格就输出前面的单词
#include <iostream>
#include <string>
using namespace std;
int main(){
string str;
while(getline(cin,str)){
int len=str.length();
string tmp;
for(int i=len-1;i>=0;i--){
if(str[i]!=' '){
tmp=str[i]+tmp;
}
else{
cout << tmp << ' ';
tmp.clear();
}
}
cout << tmp << endl; //注意要删除最后一个单词
}
return 0;
}
解析:1.字符串翻转,使用algorithm中的reverse函数,必须使用迭代器,错误用法:reverse(str[left],str[i])!!!
2.stringstream包含在#include<sstream>头文件中,常用于做数据转换,
参考:https://www.cnblogs.com/wuchanming/p/3906176.html
3.首先介绍string。
string 是 C++ 提供的字符串类,和 C 类型的字符串相比,除了有不限长度的优点外,还有其他许多方便的功能,其可以看成类似STL里vector数组的一种容器,可以方便的进行数据的增删改查,并可以进行排序、交换与遍历。要使用 string, 必须包含头文件string,并包含std命名空间:
要输出str的单个字符,可以与传统C的字符串一样采用下标运算str[i]的形式,也可以采用成员函数(str.at(i))的形式,不同的是[]运算不会检查索引i是否越界,而at()函数会检查,使用无效时会抛出out_of_range异常。
同时,string类型的字符串是不以‘\0’结尾的,因此若str有三个字符,传统C语言的字符串的str[3]是字符‘\0’,但是string类型的只能到str[2],str[3]是没有定义的,而str. at(3)会提示越界奔溃。
参考:https://blog.youkuaiyun.com/shs1992shs/article/details/83051298
例2:字符串的字典序排列
题目描述:
给定n个字符串,请对n个字符串按照字典序排列。
输入描述:
输入第一行为一个正整数n(1≤n≤1000),下面n行为n个字符串(字符串长度≤100),字符串中只含有大小写字母。
输出描述:
数据输出n行,输出结果为按照字典序排列的字符串。
示例1
输入
9
cap
to
cat
card
two
too
up
boat
boot
输出
boat
boot
cap
card
cat
to
too
two
up
代码:
方法1:string str[1000],冒泡法
#include <iostream>
#include <string>
using namespace std;
int main(){
int n;
string str[1000];
while(cin>>n){
for(int i=0;i<n;i++){
cin >> str[i];
}
for(int i=0;i<n-1;i++){
for(int j=0;j<n-1-i;j++){
if(str[j]>str[j+1]){
string tmp=str[j];
str[j]=str[j+1];
str[j+1]=tmp;
}
}
}
for(int i=0;i<n;i++){
cout<<str[i]<<endl;
}
}
return 0;
}
方法2:vector<string>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
int n;
vector<string> v;
while(cin>>n){
while(n--){
string tmp;
cin>>tmp;
v.push_back(tmp);
}
sort(v.begin(),v.end());
for(vector<string>::iterator iter=v.begin();iter!=v.end();++iter){
cout<<*iter<<endl;
}
}
return 0;
}
例3:求int型正整数在内存中存储时1的个数
题目描述:
输入一个int型的正整数,计算出该int型数据在内存中存储时1的个数。
输入描述:
输入一个整数(int类型)
输出描述:
这个数转换成2进制后,输出1的个数
示例1
输入
5
输出
2
代码:
#include <iostream>
using namespace std;
int main(){
int n;
while(cin>>n){
int cnt=0;
while(n){
n=n&(n-1); //判断二进制中1的个数
cnt++;
}
cout << cnt << endl;
}
return 0;
}
#include <iostream>
using namespace std;
int main(){
int n;
while(cin>>n){
int cnt=0; //一定要初始化
while(n){
if(n%2){
cnt++;
}
n=n/2;
}
cout << cnt << endl;
}
return 0;
}
解析:
1.数字在内存中 ,被转化为二进制。
例如7表示为0111
n&(n-1) 即(0111)&(0110)== 0110 就是 n去除了最后一个1 ;
几个1 就可以在几次内 去除几个1;
2.c++除法,分两种情况,一是操作数都是整型,那么运算结果也是整型,会舍去小数部分,相当于取(整型)商.二是有一个操作数为浮点数,运算结果就会保留小数部分,此时才算真正的除法.