NKUCS OJ Problems: Advanced Language Programming

数组:买卖股票的最佳时机

# 题目描述
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

# 样例输入输出
样例1
输入:
7 1 5 3 6 4
输出:
5
样例2
输入:
7 6 4 3 1
输出:
0
#include <bits/stdc++.h>

using std::cout; using std::cin; using std::endl;
using std::vector;

class Solution {
public:
    void run() {
        vector<int> prices;
        int prc;
        while (cin >> prc) {
            prices.push_back(prc);
        }

        int maxProfit = 0, minPrc = prices[0];
        for (auto i = prices.begin(); i != prices.end(); ++i) {
            if (*i > minPrc)
                maxProfit = std::max(maxProfit, *i - minPrc);
            else
                minPrc = *i;
        }
        cout << maxProfit;
    }
};

int main() {
    Solution().run();
    return 0;
}

无重复字符的最长子串

# 题目描述
给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度。
s由英文字母,符号,数字组成。

解释:
输入:s = ”abcabcbb”
输出:3
因为无重复字符的最长子串是“abc”,所以其长度为3

# 样例输入输出
样例
输入:
pwwkew
输出:
3
样例2
输入:
aaaa
输出:
1
#include <bits/stdc++.h>

using std::cout; using std::cin; using std::endl;
using std::string; using std::map;

class Solution {
public:
    void run() {
        string str; cin >> str;
        map<char, int> dic;
        int maxLen = 0, left = 0;
        for (int i = 0; i < (int)str.size(); ++i) {
            if (dic.find(str[i]) == dic.end() || dic[str[i]] < left) {
                // If dic doesn't have a key of str[i],
                // insert it into dic and maxLen++.
                dic[str[i]] = i;
            }
            else {
                // If dic does have a key of str[i],
                // update left (=dic[str[i]]+1) and maxLen (=i-left+1).
                left = dic[str[i]] + 1;
                dic[str[i]] = i;
            }
            maxLen = std::max(maxLen, i - left +1);
        }
        cout << maxLen;
    }
};

int main() {
    Solution().run();
    return 0;
}

函数:不死神兔问题

# 题目描述
有一对兔子,从出生后第 3 个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第 n 个月的兔子对数为多少?
输入描述:键盘输入任意一个正整数 n,n 的范围为 [1, 20]
输出描述:输出第 n 个月兔子的对数  

# 样例输入输出
样例1
输入:
1
输出:
1
样例2
输入:
2
输出:
1
样例3
输入:
3
输出:
2
样例4
输入:
4
输出:
3
#include <bits/stdc++.h>

using namespace std;

class Solution {
public:
    void run() {
        int month; cin >> month;
        int a = 0, b = 1;
        while (month > 1) {
            int tmp = a;
            a = b;
            b += tmp;
            --month;
        }
        cout << b;
    }
};

int main() {
    Solution().run();
    return 0;
}

数组元素翻转

# 题目描述
键盘随机输入 n 个整数,将这些数据保存到数组中,然后再将数组元素反转,按照格式输出数组元素。

输入描述:键盘随机输入 n 个整数输出描述:
输出描述:按照格式输出反转后数组中元素,每个元素中间使用逗号和空格隔开,整体使用中括号括起来。
例如:[60, 15, 7, 80, 12, 5]

# 样例输入输出
样例1
输入:
5 12 80 7 15 60
输出:
[60, 15, 7, 80, 12, 5]
#include <bits/stdc++.h>

using namespace std;

class Solution {
public:
    static void run() {
        vector<int> vec;
        int tmp;
        while (cin >> tmp) {
            vec.push_back(tmp);
        }
        reverse(vec.begin(), vec.end());
        for (int i = 0; i < vec.size(); ++i) {
            if (i == 0) cout << "[";
            cout << vec[i];
            if (i == vec.size()-1) cout << "]";
            else cout <<  ", ";
        }
    }
};

int main() {
    Solution::run();
    return 0;
}

计算走过的路程和反弹高度

# 题目描述
一个小球从 h 米高度自由落下,每次落地后反跳回原高度的一半再落下,求它在第 n 次落地时共经过了多少米?第 n 次返弹多高?
输入描述:输入小球下落的高度h(double型)和落地的次数n(int型)(先输入小球初始高度再输入反弹次数)
输出描述:输出小球第 n 次落地时经过的距离和第 n 次反弹的高度(保留小数点后1位)  

# 样例输入输出
样例1
输入:
100 1
输出:
100.0 50.0
样例2
输入:
100.0 3
输出:
250.0 12.5
#include <bits/stdc++.h>

using namespace std;

class Solution {
public:
    static void run() {
        double h; int n; cin >> h >> n;
        double height = h/2, sum = h;
        for (int i = 1; i < n; ++i) {
            sum += height * 2;
            height /= 2;
        }
        printf("%.1f %.1f", sum, height);
    }
};

int main() {
    Solution::run();
    return 0;
}

指针:合并两个有序链表

# 题目描述
给定两个有序数值数组,要求先按所给数值建立两个链表,链表为升序链表。将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

需要按以下结构体建立链表
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};

输入:l1=[1,2,3],l2 = [1,3,4]
输出:[1,1,2,3,4,4]

提示:输入输出的标准模式请见样例输入输出,输入时可以通过两个while循环构造两个链表,其中一行为一个链表,判断当遇到‘\n’时结束循环,链表构造完成。
提示:输出的最后一个数字后无“ ”

# 样例输入输出
样例1
输入:
1 2 4
1 3 4
输出:
1 1 2 3 4 4
#include <bits/stdc++.h>

using namespace std;

typedef struct ListNode {
    int val;
    ListNode *next;
    ListNode(): val(0), next(nullptr) {}
    ListNode(int x, ListNode* next= nullptr) : val(x), next(next) {}
} ListNode;

class Solution {
public:
    static void run() {
        // Handle input stream.
        string str, strNum;
        getline(cin, str);
        stringstream ss(str);
        vector<int> vec1, vec2;
        while (getline(ss, strNum, ' '))  // Let vec1 store elements of list1.
            vec1.push_back(stoi(strNum));
        getline(cin, str);
        stringstream ss2(str);
        while (getline(ss2, strNum, ' '))  // Let vec2 store elements of list2.
            vec2.push_back(stoi(strNum));

        // Initialize two linked lists.
        ListNode list1[vec1.size()];
        ListNode list2[vec2.size()];
        for (int i = 0; i < vec1.size(); ++i)
            list1[i] = ListNode(vec1[i]);
        for (int i = 0; i < vec1.size() - 1; ++i)
            list1[i].next = &list1[i+1];
        for (int i = 0; i < vec2.size(); ++i)
            list2[i] = ListNode(vec2[i]);
        for (int i = 0; i < vec2.size() - 1; ++i)
            list2[i].next = &list2[i+1];

        // Combine two linked lists;
        ListNode* p1 = &list1[0]; ListNode* p2 = &list2[0];
        auto head = ListNode(-1); ListNode* p3 = &head;
        while (p1 && p2) {
            if (p1->val <= p2->val) { p3->next = p1; p1 = p1->next; p3 = p3->next; }
            else { p3->next = p2; p2 = p2->next; p3 = p3->next; }
        }
        if (p1) p3->next = p1;
        if (p2) p3->next = p2;

        ListNode* res = (&head)->next;
        for (; res; res = res->next)
            { cout << res->val; if (res->next) cout << " "; }

    }
};


int main () {
    Solution::run();
    return 0;
}

指针:验证回文串

# 题目描述
给定一个字符串,验证它是否是回文串,回文字符串就是正向和反向看完全相同的字符串,只考虑字母和数字字符,不考虑标点符号,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。

示例 :
输入: "A man, a plan, a canal: Panama"
输出: true
解释:"amanaplanacanalpanama" 是回文串
示例 :
输入: "race a car"
输出: false
解释:"raceacar" 不是回文串

提示:可以先对字符串进行处理,去除标点符号将大写字母全部转换为小写

# 样例输入输出
样例1
输入:
A man, a plan, a canal: Panama
输出:
true
样例2
输入:
race a car
输出:
false
#include <bits/stdc++.h>

using namespace std;

class Solution {
public:
    static void run() {
        string str; cin >> str;
        // Handle the input string.
        for (auto i = str.begin(); i != str.end(); ) {
            if (!isalpha(*i)) { i = str.erase(i); continue; }
            if (isupper(*i)) *i = static_cast<char>(tolower(*i));
            i = i + 1;
        }

        // Judge whether str is palindrome or not.
        for (int i = 0, j = static_cast<int>(str.size()) - 1; i != j && i - 1 != j ; ++i, --j) {
            if (str[i] == str[j]) continue;
            else { cout << "false" << endl; return; }
        }
        cout << "true" << endl;
    }
};

int main () {
    Solution::run();
    return 0;
}

放大位图

# 题目描述
位图(bitmap),亦称为点阵图像或栅格图像,是由称作像素(图片元素)的单个点组成的。这些点可以进行不同的排列和染色以构成图样。当放大位图时,可以看见赖以构成整个图像的无数单个方块。扩大位图尺寸的效果是增大单个像素,从而使线条和形状显得参差不齐。然而,如果从稍远的位置观看它,位图图像的颜色和形状又显得是连续的。
现在请你设计一个程序将原来n*n的图像放大k倍。

例如,将2*2的点阵放大2倍
1	0
0	1
经过放大后新的点阵为
1	1	0	0
1	1	0	0
0	0	1	1
0	0	1	1
输出样例的每个数字后用空格隔开

# 样例输入输出
样例1
输入:
2 2
1 0
0 1
输出:
1 1 0 0
1 1 0 0
0 0 1 1
0 0 1 1
#include <bits/stdc++.h>

using namespace std;

class Solution {
public:
    static void run() {
        int n, k; cin >> n >> k;
        vector<vector<int>> matrix(n, vector<int>(n));
        vector<vector<int>> ret;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++)
                cin >> matrix[i][j];
        }

        for (int i = 0; i < n; i++) {
            vector<int> tmp(n * k);
            for (int j = 0; j < n; j++) {
                for (int kk = 0; kk < k; kk++) {
                    tmp[j * k + kk] = matrix[i][j];
                }
            }
            for (int kk = 0; kk < k; kk++)
                ret.push_back(tmp);
        }
        for (const auto & vec : ret) {
            for (const auto & i : vec)
                cout << i << " ";
            cout << endl;
        }
    }
};

int main () {
    Solution::run();
    return 0;
}

批量注册用户

# 题目描述
小明想要尝试注册多个用户名,用户名的规则如下:
用户名长度不能少于6位,不能多于12位;用户名必须由字母(大小写均可)构成;同一个用户名不能被重复注册;
请你编写一个程序判断小明的n个用户名是否创建成功。
如果创建成功输出:registration complete。
如果长度不合法输出:illegal length。
若长度不合法且字符也不合法输出:illegal length。
如果字符不合法输出:illegal charactor。
如果用户名已存在输出:acount existed。

# 样例输入输出
样例1
输入:
5
1
abcd
abcdef
abcdef
abc1ef
输出:
illegal length
illegal length
registration complete
acount existed
illegal charactor

只要长度不合法 -> illegal length
长度合法 但是字符不合法 -> illegal charactor
用户名存在 -> acount existed

#include <bits/stdc++.h>

using namespace std;

class Solution {
public:
    static void run() {
        int n; cin >> n;
        vector<string> inputStr(n);
        set<string> st;
        for (int i = 0; i < n; i++)
            cin >> inputStr[i];

        for (int i = 0; i < n; i++) {
            if (inputStr[i].size() < 6 || inputStr[i].size() > 12) { cout << "illegal length" << endl; continue; }
            bool flag = false;
            for (const auto & chr : inputStr[i]) {
                if ((chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z'))
                    continue;
                cout << "illegal charactor" << endl; flag = true; break;
            }
            if (flag) continue;
            if (st.find(inputStr[i]) == st.end()) { cout << "registration complete" << endl; st.insert(inputStr[i]); }
            else cout << "acount existed" << endl;
        }
    }
};

int main () {
    Solution::run();
    return 0;
}

类与对象的定义

# 题目描述
要求设计一个立方体类(Cube)

成员变量有:长(length)、宽(width)、高(height),都为int类型;

成员方法有:输入输出函数、获取表面积的方法(getArea),获取体积的方法(getVolume)。

输入描述:输入立方体的长、宽、高

输出描述:输出立方体的长、宽、高、面积、体积

要求:长宽高均为整数类型,输入/输出的各项之间使用空格隔开。

# 样例输入输出
样例1
输入:
3 4 5
输出:
3 4 5 94 60
#include <bits/stdc++.h>

using namespace std;

class Cube {
private:
    int length, width, height;

public:
    void Input() {
        cin >> length >> width >> height;
    }

    int getArea() {
        return (length * width + width * height + height * length) * 2;
    }

    int getVolume() {
        return length * width * height;
    }

    void Output() {
        cout << length << " " << width << " " << height << " " << getArea() << " " << getVolume() << endl;
    }
};

int main () {
    auto cube = Cube();
    cube.Input();
    cube.Output();
    return 0;
}

类和对象:删除链表的重复节点

# 题目描述
给定一个随机长度的数值数组,要求构造成链表并删除其中有重复的元素,使每个元素只出现一次。返回删除好的链表。按输入顺序,删除第一次之后出现的结点,按原顺序返回

输入描述:输入一系列数值,不一定有序

输出描述:删除重复结点后的链表。

# 样例输入输出
样例1
输入:
1 5 3 1 9
输出:
1 5 3 9
#include <bits/stdc++.h>

using namespace std;

typedef struct Node {
    int val;
    Node * next;
    Node(int x) : val(x), next(nullptr) {}
    Node(int x, Node * n) : val(x), next(n) {}
} Node;

class Solution {
private:
    set<int> se;

public:
    void Run() {
        // Prepare numbers of link list.
        string str; getline(cin, str);
        stringstream ss(str);
        string subStr;
        vector<int> vec;
        while (getline(ss, subStr, ' '))
            vec.push_back(stoi(subStr));

        // Use set to erase repeated elements.
        Node * head = new Node(-1);
        Node * p = head;
        for (const auto & i : vec) {
            if (se.find(i) != se.end()) continue;
            se.insert(i);
            p->next = new Node(i);
            p = p->next;
        }
        for (Node * i = head; i->next != nullptr; i = i->next)
            cout << i->next->val << " ";
    }
};

int main () {
    Solution().Run();
    return 0;
}

类和对象:运算符重载

# 题目描述
定义一个日期类Date,包含年、月、日三个数据成员,请实现重载自增运算符(++),实现日期的自增。

输入描述:2020 11 11,对应年,月,日
输出描述:2020 年11月12日,对应明天的年,月,日
需要注意特殊情况比如(月末,年末,平年,闰年判断)例如:
输入:2020 12 31
输出:2021年1月1日

# 样例输入输出
样例1
输入:
2021 12 11
输出:
2021年12月12日
#include <bits/stdc++.h>

using namespace std;

class Date {
private:
    int year;
    int month;
    int day;
    vector<int> mon30 = {4, 6, 9, 11};
    vector<int> mon31 = {1, 3, 5, 7, 8, 10};

    void dateCheck() {
        // Special Case: 2月份 闰年 平年
        if (month == 2) {
            if ((year % 100 == 0 && year % 400 == 0) || (year % 4 == 0)) {
                if (day > 29) { month++; day %= 29; return; }
            } else {
                if (day > 28) { month++; day %= 28; return; }
            }
        }
        // Special Case: 31天的月份 30天的月份
        if (month == 12) {
            if (day > 31) { year++; month = 1; day %= 31; return; }
        }
        if (find(mon30.begin(), mon30.end(), month) != mon30.end()) {
            if (day > 30) { month++; day %= 30; return; }
        }
        if (find(mon31.begin(), mon31.end(), month) != mon31.end()) {
            if (day > 31) { month++; day %= 31; return; }
        }
    }

public:
    Date(int y, int m, int d) : year(y), month(m), day(d) {}

    void operator++(int) {
        day++;
        dateCheck();
    }

    void Print() const {
        cout << year << "年" << month << "月" << day << "日" << endl;
    }
};

int main() {
    int y, m, d; cin >> y >> m >> d;
    Date dt = Date(y, m, d);
    dt++;
    dt.Print();

    return 0;
}

类和对象:对象数组

# 题目描述
构建一个Book类,有4个私有数据成员:书名、作者、qu和price(均为int型),将qu进行初始化,
同时price被始化为qu的10倍。建立一个有5个元素的对象数组,顺序显示每个对象数组中元素的信息;
定义对象指针,通过指针访问对象数组,逆序显示对象数组中元素的信息。书名、作者、qu的信息从键盘输入

输入描述: 5个对象数组元素的值 
输出描述: 顺序显示对象数组中各对象的值 ,各参数中间以空格隔开
				 逆序显示对象数组中各对象的值 ,各参数中间以空格隔开

# 样例输入输出
## 样例1
输入:
C语言程序设计 苏小红 2
C++程序设计 刘丽华 3
Python机器学习 范淼 4
数据结构与算法 徐凤生 3
大话数据结构 程杰 2
输出:
书名:C语言程序设计 作者:苏小红 价格:20
书名:C++程序设计 作者:刘丽华 价格:30
书名:Python机器学习 作者:范淼 价格:40
书名:数据结构与算法 作者:徐凤生 价格:30
书名:大话数据结构 作者:程杰 价格:20
使用指针逆序显示的结果为
书名:大话数据结构 作者:程杰 价格:20
书名:数据结构与算法 作者:徐凤生 价格:30
书名:Python机器学习 作者:范淼 价格:40
书名:C++程序设计 作者:刘丽华 价格:30
书名:C语言程序设计 作者:苏小红 价格:20
#include <bits/stdc++.h>

using namespace std;

class Book {
private:
    string name;
    string author;
    int qu;
    int price;

public:
    Book(string nm, string auth, int qu) : name(std::move(nm)), author(std::move(auth)), qu(qu), price(qu*10) {}

    void Print() const {
        cout << "书名:" << name << " " << "作者:" << author << " " << "价格:" << price << endl;
    }
};

int main() {
    vector<Book> books;
    for (int i = 0; i < 5; i++) {
        string name;
        string author;
        int qu;
        cin >> name >> author >> qu;
        books.emplace_back(name, author, qu);
    }

    // Print out 5 books.
    for (const auto & book : books)
        book.Print();
    reverse(books.begin(), books.end());
    cout << "使用指针逆序显示的结果为" <<  endl;
    for (const auto & book : books)
        book.Print();

    return 0;
}

类和对象:多继承

# 题目描述
1、定义日期“Date”类,类中包含数据成员年、月、日,成员函数包括构造函数(只有带参的构造函数),设置日期函数,显示日期函数
2、定义时间“Time”类,数据成员包括时、分、秒。成员函数的要求与date类相同
3、定义日期时间型“Date_Time”类
⑴公有继承Date类及Time类;
⑵不增加数据成员;
⑶增加日期时间处理成员函数,包括初始化日期时间、设置日期时间、显示日期时间等。
4、每个类都要求重载>> 和<<运算符用于对日期时间的输入和输出
5.对Date_Time,重载>运算符,用于判断两个时间大小。
6. 编写main()函数进行测试。在主函数中,输入两个Date_Time类的数据,对两个日期时间进行比较,输出较小的一个。

# 样例输入输出
样例1
输入:
2022 4 16 18 30 31 2022 4 16 18 30 35
输出:
2022-4-16 18:30:31
#include <bits/stdc++.h>

using namespace std;

class Date {
public:
    int year;
    int month;
    int day;

public:
    Date(int y, int m, int d) : year(y), month(m), day(d) {};

    friend ostream & operator<<(ostream & output, const Date & date) {
        output << to_string(date.year) + "-" + to_string(date.month) + "-" + to_string(date.day);
        return output;
    }

    friend istream & operator>>(istream & input, Date & date) {
        input >> date.year >> date.month >> date.day;
        return input;
    }
};

class Time {
public:
    int hour;
    int minute;
    int second;

public:
    Time(int h, int m, int s) : hour(h), minute(m), second(s) {};

    friend ostream & operator<<(ostream & output, const Time & time) {
        output << to_string(time.hour) + ":" + to_string(time.minute) + ":" + to_string(time.second);
        return output;
    }

    friend istream & operator>>(istream & input, Time & time) {
        input >> time.hour >> time.minute >> time.second;
        return input;
    }
};

class Date_Time : public Date, public Time {
public:
    Date_Time() : Date(0, 0, 0), Time(0, 0, 0) {}
    Date_Time(int y, int m, int d, int h, int min, int s) : Date(y, m, d), Time(h, min, s) {}

    friend ostream & operator<<(ostream & output, const Date_Time & dateTime) {
        output << to_string(dateTime.year) + "-" + to_string(dateTime.month) + "-" + to_string(dateTime.day);
        output << " ";
        output << to_string(dateTime.hour) + ":" + to_string(dateTime.minute) + ":" + to_string(dateTime.second);
        return output;
    }

    friend istream & operator>>(istream & input, Date_Time & dateTime) {
        input >> dateTime.year >> dateTime.month >> dateTime.day;
        input >> dateTime.hour >> dateTime.minute >> dateTime.second;
        return input;
    }

    bool operator>(Date_Time & time2) {
        if (this->year < time2.year) return false;
        else if (this->year > time2.year) return true;
        if (this->month < time2.month) return false;
        else if (this->month > time2.month) return true;
        if (this->day < time2.day) return false;
        else if (this->day > time2.day) return true;
        if (this->hour < time2.hour) return false;
        else if (this->hour > time2.hour) return true;
        if (this->minute < time2.minute) return false;
        else if (this->minute > time2.minute) return true;
        if (this->second < time2.second) return false;
        else if (this->second > time2.second) return true;
        return false;
    }
};

int main() {
    Date_Time dateTime1, dateTime2;
    cin >> dateTime1 >> dateTime2;
    if (dateTime1 > dateTime2)
        cout << dateTime2;
    else
        cout << dateTime1;
    return 0;
}

类和对象:继承与派生

# 题目描述
把描述直角坐标系上的一个点类作为基类,派生出描述一条直线的类和描述一个三角形的类。定义成员函数求出两点间的距离和三角形的面积。点的坐标均为int型
提示:先定义描述点 的类Point;类Line继承自Point类,一个直线有两个端点,所以他在点类的基础上新增一组点的坐标(x2,y2);三角形类 Triangle  再直线的基础上再新增一组点的坐标(x3,y3)求出三角形的面积。具体要求如下
(1)定义点类Point
保护数据成员 x1,y1
共有构造函数Point(int x1,int  y1)用于初始化x1,y1
(2)定义直线类Line
保护数据成员x2,y2
共有构造函数Line ( int x1,int  y1 ,int x2,int y2)用于初始化x2,y2,以及父类x1,y1
(3)定义三角形Triangle
私有数据成员 x3,y3
私有数据成员 area
共有构造函数Triangle( int x1,int  y1 ,int x2,int y2,int x3 ,int y3) 用于初始化x3,y3 以及父类x1,y1,x2,y2
void area():求三角形面积的功能函数
void print():输出三个点的坐标和面积

输入描述:输入6个int型数值(x1,y1,x2,y2,x3,y3)
输出描述:第一行输出三个点的坐标,第二行输出面积

# 样例输入输出
样例1
输入:
1 1 4 1 4 5
输出:
(1,1)(4,1)(4,5)
6
#include <bits/stdc++.h>

using namespace std;

class Point {
protected:
    int x1, y1;

public:
    Point(int x, int y) : x1(x), y1(y) {}
};

class Line : protected Point {
protected:
    int x2, y2;

public:
    Line(int x1, int y1, int x2, int y2) : Point(x1, y1), x2(x2), y2(y2) {}
};

class Triangle : private Line {
private:
    int x3, y3;
    double area;

public:
    Triangle(int x1, int y1, int x2, int y2, int x3, int y3) : Line(x1, y1, x2, y2), x3(x3), y3(y3), area(0) {}

    void calcArea() {
        area = abs((x1*y2 - x2*y1) + (x2*y3 - x3*y2) + (x3*y1 - x1*y3)) / 2.0;
    }

    void print() {
        cout << "(" + to_string(x1) + "," + to_string(y1) + ")";
        cout << "(" + to_string(x2) + "," + to_string(y2) + ")";
        cout << "(" + to_string(x3) + "," + to_string(y3) + ")" << endl;
        cout << area << endl;
    }
};

int main() {
    int x1, y1, x2, y2, x3, y3;
    cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
    auto triangle = Triangle(x1, y1, x2, y2, x3, y3);
    triangle.calcArea();
    triangle.print();
    return 0;
}

重载运算符练习

# 题目描述
定义一个RMB类Money,包括元角分三个数据成员,重载运算符'+'和'-',实现货币的加减运算。

# 例如:
输入一组元角分:
2 3 4
3 7 3
输出:
和:6元0角7分
差:-1元3角9分
#include <bits/stdc++.h>

using namespace std;

class RMB {
protected:
    int money;

public:
    explicit RMB(int mon) : money(mon) {}

    RMB operator+(const RMB & rmb) const {
        auto ret = RMB(money + rmb.money);
        return ret;
    }

    RMB operator-(const RMB & rmb) const {
        auto ret = RMB(money - rmb.money);
        return ret;
    }

    void print() const {
        if (money >= 0)
            cout << money / 100 << "元" << (money % 100) / 10 << "角" << money % 10 << "分";
        else {
            int monTemp = -money;
            cout << "-" << monTemp / 100 << "元" << (monTemp % 100) / 10 << "角" << monTemp % 10 << "分";
        }
    }
};

int main() {
    int a, b, c;
    vector<RMB> rmbs;
    for (int i = 0; i < 2; i++) {
        cin >> a >> b >> c;
        rmbs.emplace_back(RMB(a*100 + b*10 + c));
    }
    auto res1 = rmbs[0] + rmbs[1];
    auto res2 = rmbs[0] - rmbs[1];
    cout << "和:"; res1.print(); cout << endl;
    cout << "差:"; res2.print(); cout << endl;
    return 0;
}

继承

# 题目描述
以点(Point)类为基类,重新定义圆类(Circle)。在圆类中实现一个 isPointerInCircle方法,该方法传入一个点类对象,判断点和圆的关系,并在该方法中输出。

点类(Point):
        成员变量:x轴坐标(int x)  y轴坐标(int y)
圆类(Circle)继承自点类(Point),以Point为圆心:
        成员变量: 半径(double radius)
        成员方法:判断点和圆关系的方法(isPointerInCircle)
点和圆的关系(最终输出为以下三种关系之一):
        点在圆外
        点在圆上
        点在圆内

输入描述:
0 0
1 1 1.0
(第一行为要判断的点的横纵坐标,第二行前两个参数为圆的圆心坐标,第三个参数为圆的半径)
输出描述:
点在圆外

# 样例输入输出
样例1
输入:
0 0
1 1 1.0
输出:
点在圆外
#include <bits/stdc++.h>

using namespace std;

class Point {
public:
    int x;
    int y;
    Point(int a, int b) : x(a), y(b) {}
};

class Circle : public Point {
public:
    double radius;

public:
    Circle(int a, int b, double c) : Point(a, b), radius(c) {}

    void isPointerInCircle(const Point & p) const {
        double distance = sqrt(pow(fabs(x - p.x), 2) + pow(fabs(y - p.y), 2));
        if (distance - radius > DBL_EPSILON)
            cout << "点在圆外";
        else if (distance - radius >= 0 && distance - radius <= DBL_EPSILON)
            cout << "点在圆上";
        else
            cout << "点在圆内";
    }
};

int main() {
    int pX, pY; cin >> pX >> pY; auto p = Point(pX, pY);
    double r; cin >> pX >> pY >> r; auto circle = Circle(pX, pY, r);
    circle.isPointerInCircle(p);
    return 0;
}

继承组合

# 题目描述
声明Teacher(教师)类为基类,数据成员包括:姓名,性别。成员函数为构造析构函数
Professor(教授)类为Teacher类的派生类。
另有一个BirthDate(生日)类,数据成员包含year,month,day等数据成员。可以将教授的生日信息加入到Professor类的声明中作为Professor的对象成员。
在主函数中,定义Professor类对象时给定初始值,然后给定一个新的BirthDate类对象,更新原对象中的生日数据并输出。

输入描述:
第一行依次输入构造Professor对象的各项初始数据
第二行输入为新的BirthDate对象的数值
输出描述
更新原有的professor对象的birthday数据并输出

# 样例输入输出
样例1
输入:
zhangsan M 1999 7 14
2001 5 21
输出:
name: zhangsan
sex: M
birthdate: 2001/5/21
#include <bits/stdc++.h>

using namespace std;

class Teacher {
public:
    string name;
    string gender;

public:
    Teacher(string & n, string & g) : name(n), gender(g) {}
};

class BirthDate {
public:
    int year;
    int month;
    int day;
    BirthDate(int y, int m, int d) : year(y), month(m), day(d) {}
};

class Professor : public Teacher {
public:
    BirthDate bd;
    Professor(string & n, string & g, int y, int m, int d) :
            Teacher(n, g), bd(BirthDate(y, m, d)) {}

    void print() const {
        cout << "name: " << name << endl;
        cout << "sex: "  << gender << endl;
        cout << "birthdate: " << bd.year << "/" << bd.month << "/" << bd.day << endl;
    }
};

int main() {
    string n, g; int y, m, d;
    cin >> n >> g >> y >> m >> d; auto prof = Professor(n, g, y, m, d);
    cin >> y >> m >> d; prof.bd = BirthDate(y, m, d);
    prof.print();
    return 0;
}

多重继承

# 题目描述
分别定义Teacher(教师)类和Cadre(干部)类,采用多重继承方式由这两个类派生出新类Teacher_Cadre(教师兼干部)类。要求:
1、Teacher类中包含数据成员 姓名、年龄、性别、职称(title)。
2、Cadre类中包含数据成员 姓名、年龄、性别、职务(post)。
3、Teacher_Cadre类中还包含数据成员工资(wages)。
4.两个基类中的姓名、年龄、性别 数据成员用相同的名字,在引用这些数据成员时,指定作用域。
5、在派生类Teacher_Cadre 的成员函数show 中调用Teacher类中的display 函数,输出姓名、年龄、性别、职称,然后再用cout语句输出职务与工资。

输入描述:
输入3个教师兼干部内容分别构造3个类
输出描述:
输出工资最高的一位教师兼干部的各项信息

# 样例输入输出
样例1
输入:
zhangsan 30 M teacher assistent 3456.2
lisi 34 M professor assistent 4589.5
wangwu 56 M professor manager 8569.5
输出:
name: wangwu
age: 56
sex: M
title: professor
post: manager
wage: 8569.5
#include <bits/stdc++.h>

using namespace std;

class Teacher {
public:
    string name;
    string gender;
    int age;
    string title;

public:
    Teacher(string & n, string & g, int age, string & t) :
        name(n), gender(g), age(age), title(t) {}

    void display() const {
        cout << "name: " << name << endl;
        cout << "age: "  << age << endl;
        cout << "sex: "  << gender << endl;
        cout << "title: "<< title << endl;
    }
};

class Cadre {
public:
    string name;
    string gender;
    int age;
    string post;
    Cadre(string & n, string & g, int age, string & p) :
        name(n), gender(g), age(age), post(p) {}
};

class Teacher_Cadre : public Teacher, public Cadre {
public:
    double wages;

public:
    Teacher_Cadre(string & n, string & g, int age, string & t, string & p, double w) :
        Teacher(n, g, age, t), Cadre(n, g, age, p), wages(w) {}

    void show() const {
        this->Teacher::display();
        cout << "post: " << post << endl;
        cout << "wage: " << wages << endl;
    }
};

int main() {
    vector<Teacher_Cadre> people;
    string n, g, t, p; int age; double wage;
    for (int i = 0; i < 3; i++) {
        cin >> n >> age >> g >> t >> p >> wage;
        people.emplace_back(Teacher_Cadre(n, g, age, t, p, wage));
    }
    // Find the highest wage.
    int ind = 0; double highest = people[0].wages;
    for (int i = 0; i < people.size(); i++) {
        if (highest < people[i].wages) {
            highest = people[i].wages;
            ind = i;
        }
    }
    people[ind].show();
    return 0;
}

多态性

# 题目描述
完成以下代码,实现简单的计算器功能。
定义一个BaseCalculator类,包括数据成员m_A,m_B,定义成员函数为虚函数getResult(),在基类中无需实现。
定义AddCalculator,SubCalculator,MultiplicationCalculator ,DivisionCalculator为加、减、乘、除四种计算器类,继承自BaseCalculator类,并在每个类中实现getResult()方法进行不同类型的运算。
在主函数中定义一个BaseCalculator类型的指针,分别指向四种不同计算功能的四各类对象进行输出。
输入描述:输入两个整形数字m_A,m_B
输出描述:
第一行为加法结果
第二行为减法结果
第三行为乘法结果
第四行为除法结果

# 样例输入输出
样例1
输入:
6 2
输出:
8
4
12
3
#include <bits/stdc++.h>

using namespace std;

class BaseCalculator {
protected:
    int m_A;
    int m_B;
public:
    BaseCalculator(int a, int b) : m_A(a), m_B(b) {}
    virtual int getResult() {}
};

class AddCalculator : public BaseCalculator {
public:
    AddCalculator(int i, int i1) : BaseCalculator(i, i1) {}

    int getResult() override {
        return m_A + m_B;
    }
};

class SubCalculator : public BaseCalculator {
public:
    SubCalculator(int i, int i1) : BaseCalculator(i, i1) {}

    int getResult() override {
        return m_A - m_B;
    }
};

class MultiplicationCalculator : public BaseCalculator {
public:
    MultiplicationCalculator(int i, int i1) : BaseCalculator(i, i1) {}

    int getResult() override {
        return m_A * m_B;
    }
};

class DivisionCalculator : public BaseCalculator {
public:
    DivisionCalculator(int i, int i1) : BaseCalculator(i, i1) {}

    int getResult() override {
        return m_A / m_B;
    }
};

int main() {
    int a, b; cin >> a >> b;
    BaseCalculator * baseCalc;
    baseCalc = new AddCalculator(a, b);
    cout << baseCalc->getResult() << endl;

    baseCalc = new SubCalculator(a, b);
    cout << baseCalc->getResult() << endl;

    baseCalc = new MultiplicationCalculator(a, b);
    cout << baseCalc->getResult() << endl;

    baseCalc = new DivisionCalculator(a, b);
    cout << baseCalc->getResult() << endl;
}

虚函数

# 题目描述
写一个程序,定义抽象基类Shape,由他派生出3个派生类:Circle(圆类),Rectangle(矩形),Triangle(三角形)。用虚函数分别计算几种图形的面积,并求他们的和。

输入描述:
第一行为圆的半径
第二行为矩形的长,宽
第三行为三角形的底和高

输出描述:
第一行为圆形的面积
第二行为矩形的面积
第三行为三角形的面积
第四行为三个图形面积和

# 样例输入输出
样例2
输入:
2
3 4
6 8
输出:
Circlearea=12.56
Rectanglearea=12
Trianglearea=24
Area sum=48.56
#include <bits/stdc++.h>

using namespace std;

class Shape {
public:
    double circleRadius{};
    double recWidth{}, recHeight{};
    double triBase{}, triHeight{};

public:
    virtual double getCircleArea() {};

    virtual double getRecArea() {};

    virtual double getTriArea() {};
};

class Circle : virtual public Shape {
public:
    double getCircleArea() override {
        return 3.14 * circleRadius * circleRadius;
    }
};

class Rectangle : virtual public Shape {
public:
    double getRecArea() override {
        return recWidth * recHeight;
    }
};

class Triangle : virtual public Shape {
public:
    double getTriArea() override {
        return 0.5 * triBase * triHeight;
    }
};

int main() {
    auto circle = new Circle();
    cin >> circle->circleRadius;

    auto rectangle = new Rectangle();
    cin >> rectangle->recWidth >> rectangle->recHeight;

    auto triangle = new Triangle();
    cin >> triangle->triBase >> triangle->triHeight;

    cout << "Circlearea=" << circle->getCircleArea() << endl;
    cout << "Rectanglearea=" << rectangle->getRecArea() << endl;
    cout << "Trianglearea=" << triangle->getTriArea() << endl;
    cout << "Area sum=" << circle->getCircleArea() + rectangle->getRecArea() + triangle->getTriArea() << endl;
}

字符串A

# 题目描述
利用指针实现复制一个字符串的指定位数成为一个新的字符串 。例如样例输入输出中helloNKCS中,N为第6个字符,从N开始复制N及之后的NKCS作为新字符串。

输入描述:
第一行输入 复制开始的位置  ,第二行输入一个字符串

输出描述:
从开始位置截取之后的字符串作为新字符串并输出

# 样例输入输出
样例1
输入:
6
helloNKCS
输出:
NKCS
#include <bits/stdc++.h>

using namespace std;

class Solution {
public:
    static void run() {
        int ind; cin >> ind;
        string s; cin >> s;
        for (int i = ind-1; i < s.length(); i++) {
            cout << s[i];
        }
    }
};

int main() {
    Solution::run();
}

类和对象B

# 题目描述
分别定义Teacher(教师)类和Cadre(干部)类,采用多重继承方式由这两个类派生出新类Teacher_Cadre(教师兼干部)类。要求:
1、Teacher类中包含数据成员 姓名、年龄、性别、职称(title)。
2、Cadre类中包含数据成员 姓名、年龄、性别、职务(post)。
3、Teacher_Cadre类中还包含数据成员工资(wages)。
4.两个基类中的姓名、年龄、性别 数据成员用相同的名字,在引用这些数据成员时,指定作用域。
5、在派生类Teacher_Cadre 的成员函数show 中调用Teacher类中的display 函数,输出姓名、年龄、性别、职称,然后再用cout语句输出职务与工资。

输入描述:
输入3个教师兼干部内容分别构造3个类
输出描述:
输出工资最低的一位教师兼干部的各项信息,中间以空格分开

# 样例输入输出
样例1
输入:
zhangsan 30 M teacher assistent 3456.2
lisi 34 M professor assistent 4589.5
wangwu 56 M professor manager 8569.5
输出:
zhangsan 30 M teacher assistent 3456.2
#include <bits/stdc++.h>

using namespace std;

class Teacher {
public:
    string name;
    string gender;
    int age;
    string title;

public:
    Teacher(string & n, string & g, int age, string & t) :
            name(n), gender(g), age(age), title(t) {}

    void display() const {
//        cout << "name: " << name << endl;
//        cout << "age: "  << age << endl;
//        cout << "sex: "  << gender << endl;
//        cout << "title: "<< title << endl;
        cout << name << " " << age << " " << gender << " " << title << " ";
    }
};

class Cadre {
public:
    string name;
    string gender;
    int age;
    string post;
    Cadre(string & n, string & g, int age, string & p) :
            name(n), gender(g), age(age), post(p) {}
};

class Teacher_Cadre : public Teacher, public Cadre {
public:
    double wages;

public:
    Teacher_Cadre(string & n, string & g, int age, string & t, string & p, double w) :
            Teacher(n, g, age, t), Cadre(n, g, age, p), wages(w) {}

    void show() const {
        this->Teacher::display();
//        cout << "post: " << post << endl;
//        cout << "wage: " << wages << endl;
        cout << post << " " << wages << endl;
    }
};

int main() {
    vector<Teacher_Cadre> people;
    string n, g, t, p; int age; double wage;
    for (int i = 0; i < 3; i++) {
        cin >> n >> age >> g >> t >> p >> wage;
        people.emplace_back(Teacher_Cadre(n, g, age, t, p, wage));
    }
    // Find the highest wage.
    int ind = 0; double lowest = people[0].wages;
    for (int i = 0; i < people.size(); i++) {
        if (lowest > people[i].wages) {
            lowest = people[i].wages;
            ind = i;
        }
    }
    people[ind].show();
    return 0;
}

数组排序

# 题目描述
编写程序完成以下功能:
由键盘输入一系列数字组成一个数组,将改串数字从小到大进行排序操作,输出排好序的数组。

输入描述:
键盘随意输入一串数字
输出描述:
将输入的数字排序后进行输出。

# 样例输入输出
样例1
输入:
4 7 2 6 0 3 5 7 9
输出:
0 2 3 4 5 6 7 7 9
#include <bits/stdc++.h>

using namespace std;

class Solution {
public:
    static void run() {
        vector<int> vec;
        int temp;
        while (cin >> temp) {
            vec.push_back(temp);
        }
        sort(vec.begin(), vec.end(), less<int>());
        for (int i = 0; i < vec.size(); i++) {
            cout << vec[i];
            if (i != vec.size()-1) cout << " ";
        }
    }
};

int main() {
    Solution::run();
}

附加题

# 题目描述
编写程序实现以下功能:
两两交换链表中的相邻节点,例如一个链表长度为4,1,2位节点进行交换,3,4位节点进行交换,输出交换后的链表。
1->2->3->4
变换为:
2->1->3->4

输入描述:
输入一系列数字代表一个链表
输出描述:
两两翻转后输出

# 样例输入输出
样例1
输入:
1 2 3 4
输出:
2 1 4 3
#include <bits/stdc++.h>

using namespace std;

typedef struct Node {
    int val;
    Node * next;
    Node() : val(0), next(nullptr) {}
    explicit Node(int v) : val(v), next(nullptr) {}
    explicit Node(int v, Node * n) : val(v), next(n) {}
} Node;

class Solution {
public:
    static void run() {
        // 根据输入构建链表
        Node * head = new Node(-1);
        int temp;
        Node * h = head;
        while (cin >> temp) {
            Node * node = new Node(temp);
            h->next = node;
            h = h->next;
        }

        // 两两交换相邻结点
        h = head;
        while (h && h->next) {
            // 后面两个结点都存在时进行翻转
            if (h->next && h->next->next) {
                Node * node1 = h->next;
                Node * node2 = h->next->next;

                node1->next = node2->next;
                h->next = node2;
                node2->next = node1;
            }
            h = h->next->next;
        }

        // 打印输出
        h = head->next;
        while (h) {
            cout << h->val;
            if (h->next != nullptr) cout << " ";
            h = h->next;
        }
    }
};

int main() {
    Solution::run();
}