编程之旅-Day41

目录

Day41-学习内容:

1.剑指Offer

面试题28:对称二叉树

面试题37:序列化二叉树

        2.华为机试题

例1:句子逆序

例2:字符串的字典序排列

例3:求int型正整数在内存中存储时1的个数


1.剑指Offer

面试题28:对称二叉树

题目描述:请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

思路:递归和遍历

代码:

扫描二维码关注公众号,回复: 6122740 查看本文章
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.csdn.net/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++除法,分两种情况,一是操作数都是整型,那么运算结果也是整型,会舍去小数部分,相当于取(整型)商.二是有一个操作数为浮点数,运算结果就会保留小数部分,此时才算真正的除法.

猜你喜欢

转载自blog.csdn.net/linyuhan3232/article/details/89631471