目录
卡码网是基于ACM模式下的网站,现在许多的公司笔试都是基于这个模式下编写的,需要自己控制输入输出,以及数据结构的申明和编写。相对于力扣来说,更有挑战性,更面向就业。
1-6题 A+B问题 格式化输出问题
这个基本上是针对结果的格式化输入输出,特别简单。初学者就很容易搞定,便不再赘述。
7题 平均绩点
这里针对一行的输入有两种办法接收。 一是利用while循环,当cin读入到"\n"换行符的时候,便结束一行的读入。本题可以用另一种输入方法,利用getline函数,读取一行的全部元素,之后再进行一定的处理,本题则可以:
string str;
while (getline(cin, str)) {
// 处理
}
8题 摆平积木
这题也是十分简单,对于一组数据来说,要变成相同高度也就是将每个数变成平均数,现在要求的移动的最少积木块的数量,就可以求大于平均数的数与平均数之差的总和或者小于平均数的数与平均数之差的总和。
9题 奇怪的信
本题是分解整数的各位以及判断奇偶数。
10题 运营商活动
本题更注重的是数学思维,活动是每充值K元话费就可以获赠1元话费,赠送的话费也可以参与到奖励规则中,也就是说,如果剩余K-1元,赠送了1元话费,还可以参加K元话费赠1元的活动,会再获得1元话费。例子如下:
输入:
13 3
输出:
19
注意第三组数据「13 3」结果为什么是19呢, 13/3=4,获得4元奖励。 13%3=1,还剩下1元,4+1=5,5元继续参加奖励规则。 5/3=1,获得1元奖励。 5%3=2,剩下2元,1+2=3,3元继续参与奖励规则。 3/3=1,获得1元奖励。 3%3=0,剩下0元,1+0=1。 1元不能参与剩下奖励。所以一共可以使用的天数是 13+4+1+1=19
这里的逻辑可以拆分一下,第一次缴话费能获得的话费数目result = M + M / K,而能获得除M的额外话费是left = M / K + M % k。第二次话费活动计算,本次能获得的话费数目是原来的result加上left除以K得到的数目,即result += left / K,获得的除left的额外话费也就是 left = left / K + left % k了。最终的计算代码如下所示:
int result = M + M / K;
int left = M / K + M % K;
while (left / K != 0) {
result += left / K;
left = left / K + left % K;
}
11题 共同祖先
本题首先明确小明和小宇是有共同祖先的,那么他们离共同祖先的距离(一层关系算距离1)就彰显了他们直接的年长与否。如果小明离共同祖先的距离近,那么小明年长;相反就是小宇年长;想通的话就是兄弟。也就是说,这题可以简化成,分别从1,2开始计算向上到底的距离,对比1,2的距离长度即可。
12-13题 图形打印题
这两道题基本上没啥大的逻辑和算法可言,找规律,打印出来就行了。
14题 句子缩写
本题要注意的一点是,在cin之后有一个回车换行符,需要吸收掉,要不然第二行的数据在使用getline函数的时候会吸收不到str里面,相反是换行符被输入到str里面了。这里可以采用getchar函数来吸收换行符。其次就是判断大小写了,判断方式如下:(大写A是从65开始,小写a是从97开始。指ASCII码。)
bool isUpperCase(char c) {
return c >= 'A' && c <= 'Z';
}
bool isLowerCase(char c) {
return c >= 'a' && c <= 'z';
}
15题 神秘字符
本题只需要用insert函数,把字符串2放入字符串1的中间就行了。(删除是erase)
16题 位置互换
本题十分简单。
17题 出栈合法性
本题只需要注意到,当前元素的后续出栈元素,只要比当前元素小的都需要按照递减序列排列就行了。代码如下:
#include <iostream>
#include <vector>
using namespace std;
int check(vector<int> numbers, int index) {
vector<int> temp;
for (int i = index + 1; i < numbers.size(); i++) {
if (numbers[i] < numbers[index]) {
if (!temp.empty() && temp.back() > numbers[i]) {
temp.push_back(numbers[i]);
} else if (temp.empty()){
temp.push_back(numbers[i]);
} else if (!temp.empty() && temp.back() < numbers[i]){
return 0;
}
}
}
return 1;
}
int main() {
int N;
while (cin >> N) {
if (N == 0) { return 0;}
vector<int> numbers;
int a;
while (N--) {
cin >> a;
numbers.push_back(a);
}
int flag = 1;
for (int i = 0; i < numbers.size(); i++) {
if (check(numbers, i)) {
continue;
} else {
flag = 0;
cout << "No" << endl;
break;
}
}
if (flag) {
cout << "Yes" << endl;
}
}
return 0;
}
18题 链表的基本操作
本题考查链表的基本操作,增删查。首先就是要自己申明一个链表结构体,代码如下所示:
struct ListNode{
int val;
ListNode* next;
ListNode(int val): val(val), next(nullptr){}
};
本题初始化链表也是比较独特的,需要正向输入,反向存储链表,也就是说123输入,链表实际为321。这样的话可以采取在头部的地方加入新元素就可以完成这个操作了,代码如下:
void addHead(ListNode* node, ListNode* newNode) {
newNode->next = node->next;
node->next = newNode;
}
相关的get/delete/insert/show的操作如下所示:
void get(ListNode* node, int index) {
int count = 1;
while (node != nullptr) {
if (count == index) {
cout << node->val << endl;
return;
}
node = node->next;
count++;
}
cout << "get fail" <<endl;
return;
}
void deleteList(ListNode* node, int index) {
int count = 0;
while (node != nullptr && node->next != nullptr) {
if (count == index - 1) {
ListNode* temp = node->next;
node->next = node->next->next;
delete temp;
cout << "delete OK" << endl;
return;
}
node = node->next;
count++;
}
cout << "delete fail" <<endl;
return;
}
void insert(ListNode* node, int index, int val) {
int count = 0;
while (node != nullptr) {
if (count == index - 1) {
ListNode* newNode = new ListNode(val);
newNode->next = node->next;
node->next = newNode;
cout << "insert OK" << endl;
return;
}
node = node->next;
count++;
}
if (count < index) {
cout << "insert fail" << endl;
return;
}
}
void show(ListNode* node) {
int flag = 0;
while (node != nullptr) {
flag = 1;
cout << node->val << " ";
node = node->next;
}
if (flag == 0) {
cout << "Link list is empty" << endl;
return;
} else {
cout << endl;
return;
}
}
19题 单链表反转
可以使用快慢指针的方式,将两个指针之间的指向关系反转之后,再进行到下一对节点就行了。
代码如下:
listNode* reverse(listNode* node) {
listNode* cur = node;
listNode* pre = nullptr;
while (cur != nullptr) {
listNode* temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
return pre;
}
20题 删除重复元素
本题也可以采用快慢指针的方式,如果快指针和慢指针的元素相同了,将快指针的节点删除,然后指向删除的下一个节点,慢指针不变;相反就一起指向各自的下一个节点就行了。
ListNode* deleteRepeat(ListNode* node) {
ListNode* cur = node;
ListNode* fast = node->next;
while (fast != nullptr && cur != nullptr) {
if (cur->val == fast->val) {
ListNode* temp = fast->next;
cur->next = temp;
delete fast;
fast = temp;
} else {
cur = cur->next;
fast = fast->next;
}
}
return node;
}
总结
这算是从暑假到开学的复健,慢慢开始继续coding了。