2018網際網路大廠秋招程式設計通關(二)
通過上一篇的繼續學習,連結地址為:
接下來,我們繼續講解秋招筆試程式設計題,及其知識點總結。
(1)歡聚時代2018秋--------------計算重複字串長度(點選文字進入連結)
題目解析
參考答案
方法一: #include <bits/stdc++.h> using namespace std; int main(){ string s; cin >> s; int res = 0;// 最大子串長度 for(int i=0;i<s.size();++i){ //從第一個字元開始比較 for(int j=i+1;j<s.size();++j){ //遍歷整個字串 int len = 0; // 當前重複字元長度 int now = i; // 儲存當前下表 int post = j; // 儲存當前下表 while(s[now] == s[post]){ ++now; ++post; ++len; } res = max(len,res);// 最大重複字串長度 } } printf("%d\n",res); return 0; }
方法二: #include <iostream> #include <string> using namespace std; int statLen(string str, int i, int j) { int cur_len = 0; while (i < str.size() && j < str.size() && str[i] == str[j]) {// 判斷子串 i++; j++; cur_len++; } return cur_len; } int naiveLRS(string str) { int maxlen = 0; // 遍歷所有字串 for (int i = 0; i != str.size(); ++i) { int len = 0; for (int j = i + 1; j != str.size(); j++) { len = statLen(str, i, j);// 獲取子串長度 if (maxlen < len) { // 記錄最大長度 maxlen = len; } } } return maxlen; } int main() { string str; cin >> str; printf("%d", naiveLRS(str)); }
本題知識點:
(1)s.size()求出字串的長度;
(2)使用now,post儲存當前正在進行比較的下標;
(3)使用c++庫中的函式max(數字1,數字2)求出了最大值。通過res對res進行替換,每次求得的都是當前字串最大值。
(2)七牛雲2018秋招---------------Young Tableau
題目描述
Young Tableau 是滿足如下定義的二維數表:
- 所有行均為左對齊,所有行的最左端在同一列,且每一行均連續無空位;
- 從上到下每一行的列數非嚴格單調遞減;
- 每一行中的數從左到右嚴格單調遞增;
- 每一列中的數從上到下嚴格單調遞增。 請編寫一個程式,判斷一個數表是否是Young Tableau。數表的行數和列數至多為10,所有數均為正整數。
-
是Young Tableau,而1 2 3 4 5 6
和1 3 2 4 5 6
都不是。1 4 5 2 3 6
- 輸入格式:
每組測試資料包含多個測試點,輸入的第一行表示測試點的數量(至多5 組)。
每個測試點是一個二維數表,輸入中的每一行表示數表的一行,不同的數之間用一個空格隔開。 測試點之間用一個空行隔開。例如
2 1 3 4 5 6 2 7 10 8 9 2 5 8 9 7 11 10
- 輸出格式:
針對每一個測試點輸出一行,內容為true/false(全部小寫)表示是/不是Young Tableau。例如
true false
-
題目解析
- 預備知識
- 嚴格遞減表示
<
- 非嚴格遞減表示
=<
- 不定長資料表示
- 【C方式】通常使用一個定長陣列,非法數字表示行和列的結束。
- 【C++方式】使用巢狀
vector
。
- 嚴格遞減表示
本題目就是二維迴圈簡單遍歷。
參考答案
#include <iostream>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;
bool IsYoungTableau(vector<vector<int>> nums){ //定義變長陣列nums
if(nums.empty())return false;
for(int i=1;i!=nums.size();++i){
for(int j=1;j!=nums[i].size();++j){
// 右邊的數必須大於左邊的數
if (nums[i][j] < nums[i][j-1]) return false;
// 下邊的數必須大於上邊的數
if (nums[i][j] < nums[i-1][j]) return false;
}
// 當前行長度要小於等於上一行
if (nums[i].size() > nums[i-1].size()) return false;
}
return true;
}
int main(){
int n = 0;
scanf("%d\n",&n); // 這裡\n防止被cin讀入
bool res[n];
for(int i=0;i!=n;++i){
vector<vector<int> > nums;
string str; // 儲存一行資料
while(getline(cin,str,'\n')){ // 讀取一行資料
if(str.empty()) break; // 空行退出
istringstream iss(str);
int num = 0;
vector<int> temp;
while(iss >> num){ // 取出一行資料中的數字
temp.push_back(num);
}
nums.push_back(temp);
}
res[i] = IsYoungTableau(nums);
}
// 列印結果
for(int i=0;i!=n;++i){
cout << boolalpha << res[i] << endl;
}
}
本題知識點:
(1)定長陣列與變長陣列的定義;
(2)變長陣列向量儲存資料
vector<vector<int> > table;//定義一個二維變長陣列table
vector<int> row1; //定義一個一維變長陣列row1
row1.push_back(1); //向一維陣列row1中插入值
row1.push_back(3);
row1.push_back(4);
row1.push_back(5);
row1.push_back(6);
vector<int> row2;
row2.push_back(2); //向一維陣列row2中插入值
row2.push_back(7);
row2.push_back(10);
vector<int> row3; //向一維陣列row3中插入值
row3.push_back(8);
row3.push_back(9);
table.push_back(row1); //將一維陣列插入到二維陣列中
table.push_back(row2);
table.push_back(row3);
(3) 對於變長陣列而言:
table.size() //獲取有多少行
table[i].size() //獲取第i行有多少列
table[i] //獲取第i行資料
table[i][j] //獲取第i行第j列資料
(4)向量遍歷
for(int i=0;i<table.size();++i){
for(int j=0;j<table[i].size();++j){
printf("%d ",table[i][j]);
}
printf("\n");
}
(3)吉位元2018秋招------------二進位制個位不同個數(點選文字進入連結)
題目解析
-
預備知識 異或也叫半加運算,其運演算法則相當於不帶進位的二進位制加法:二進位制下用1表示真,0表示假,則異或的運演算法則為:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同為0,異為1),這些法則與加法是相同的,只是不帶進位,所以異或常被認作不進位加法。 如果a、b兩個值不相同,則異或結果為1。如果a、b兩個值相同,異或結果為0。
-
解題思路: 兩個數進行異或,統計異或後的結果的二進位制數1的個數,那麼如何統計個數呢?有如下方法:將異或的結果與其減一進行與操作,直至與後的結果為零,就是二進位制不同位數的數量。
-
例項解釋
22
和33
進行異或。
然後數一下- 十進位制數 二進位制數 a 22 10110 b 33 100001 ⊕ 55 110111 1
的個數,個數為5
。 -
參考答案
方法一:
#include <bits/stdc++.h>
using namespace std;
int main(){
int n = 0;
int m = 0;
scanf("%d%d",&n,&m);
int num = n^m;//進行異或操作
int count = 0;
while(num != 0){
if(num & 0x1) ++count; // 判斷右端第一位是不是1
num = num>>1; // 右移一位
}
printf("%d\n",count);
}
方法二:
#include <bits/stdc++.h>
using namespace std;
int main(){
int n = 0;
int m = 0;
scanf("%d%d",&n,&m);
int num = n^m;
int count = 0;
while(num != 0){
++count;
num = (num-1)#// 每次去除1位
}
printf("%d\n",count);
}
本題知識點:
(1)輸入的n,m為十進位制數,但計算機本質是以二進位制進行運算的,因此n,m可直接進行異或操作;
(2)這道題雖然程式碼很短,但思想很重要:通過(num-1)&num來統計結果值中1的個數。
(4)吉位元2018秋招-----------字母數字混合排序(點選文字進入連結)
題目解析
-
預備知識
sort(first,last)
以升序排序範圍
[first, last)
中的元素。sort(first,last,cmp)
cmp(a,b)
比較函式,a
與b
不交換返回true
(也就是想要的順序);first
與last
交換返回false
。 -
解題思路: 字元排序,判斷條件追加字母與數字的區分(字母的ASCII碼比數字大)。所以排序後的順序為:數字|字母。因此我們可以將字串數字部分進行擷取,然後將數字部分追加到字母后邊即可。
-
參考答案
方法一:
#include <bits/stdc++.h>
using namespace std;
int main(){
string s;
cin >> s;
sort(s.begin(),s.end());
int pos = 0;
for(int i=0;i<s.size();++i){
if(!('0'<=s[i] && s[i] <= '9')){
pos = i;
break;
}
}
// 擷取數字部分
string num = s.substr(0,pos);
// 擷取字母部分
string str = s.substr(pos);
cout << str+num;
return 0;
}
方法二:
#include <bits/stdc++.h>
using namespace std;
bool cmp(int a,int b){
// a 和 b一個是數字一個是字母
// '0' <= a && a <='9'
// 'a' <= b && b <='z'
if(isdigit(a) && isalpha(b)){
return false;
}
if(isdigit(b) && isalpha(a)){
return true;
}
// a 和 b都是數字或都是字母
return a < b;// 正確的順序
}
int main() {
string s;
cin >> s;
sort(s.begin(),s.end(),cmp);
cout << s;
return 0;
}
方法三:氣泡排序
#include <bits/stdc++.h>
using namespace std;
int main(){
string str;
cin >> str;
for(int i=0;i!=str.size();++i){
for(int j=0;j!=str.size()-(i+1);j++){
if((str[j] <= '9' && str[j+1] >= 'a') ||
(str[j] > str[j+1] && str[j] <= '9') ||
(str[j] > str[j+1] && str[j+1] >= 'a')){
swap(str[j],str[j+1]);
}
}
}
cout << str << "\n";
}
本題知識點:
- 從
i
擷取長度為len的
字串s.substr(i,len);
- 從
i
擷取到字串結束s.substr(i);
- 字串字典序排序
sort(s.begin(),s.end());
- 在字串後新增
n
個字元c
s.append(n,c);
- 字串連線
+
,str3 = str1+str2
- 構建一個
n
個字元c
組成的字串string(n,c)
這裡主要講的就是排序問題,我們可以看下面的例子:
- 排序函式
sort(開始位置,結束位置)
- 按照
cmp
方式排序sort(開始位置,結束位置,cmp)
sort()
預設以字典序排列字元,以升序排列數字。
- 按照字典逆序排列字串
#include <bits/stdc++.h>
using namespace std;
bool cmp(char a,char b) {
return a > b;// 正確的順序
}
int main() {
string s; // s[i]
cin >> s;
sort(s.begin(),s.end(),cmp);
cout << s;
return 0;
}
- 按照降序排列數列
#include <bits/stdc++.h>
using namespace std;
bool cmp(int a,int b){
return a > b;// 正確的順序
}
int main() {
int n = 0;
scanf("%d",&n);
int nums[n];
for(int i=0;i<n;++i){
scanf("%d",&nums[i]);
}
sort(nums,nums+n,cmp);
for(int i=0;i<n;++i){
printf("%d ",nums[i]);
}
return 0;
}
對陣列進行排序,除了氣泡排序等,這也是一個不錯的排序方式。
(5)百度2018秋招-------------字元覆蓋(點選文字進入連結)
題目解析
先對兩個字串s和t元素從大到小進行排序,然後把t
按從大到小依次替換s
中小的字元,使得到的字串s的字典序最大。
參考答案
#include <bits/stdc++.h>
using namespace std;
bool cmp(char a,char b){
return a>b; //正確的順序
}
int main(){
string s ;
cin >> s;
string t ;
cin >> t;
sort(t.begin(),t.end(),cmp);
int j =0;
for(int i =0;i<s.size();i++){
while(j<t.size()){
if(s[i] <t[j]){
s[i]=t[j];
j++;
}else{
break;
}
}
}
cout << s;
return 0;
}
本題知識點:
這道題重點在對字串通過函式cmp()進行逆向排序上,還有while()迴圈語句對替換條件的判定。相對簡單,思維嚴密就好。
(6)拼多多2018秋招------------小熊吃糖(點選文字進入連結)
題目解析
需要用到排序演算法:按戰鬥力對小熊們排序;按能填充的飢餓值對糖排序。注意
- 最終答案需要按照小熊輸入的順序進行輸出,在排序之後要記錄一下這個資訊。
- 一個小熊可能會吃多塊糖
參考答案
方法一:
#include <bits/stdc++.h>
using namespace std;
// 小熊結構體
struct Bear{
int finger; // 戰鬥力
int hunger; // 飢餓值
int id; // 編號
};
bool cmpBear(Bear a,Bear b){
return a.finger > b.finger;
}
bool cmpBearById(Bear a,Bear b){
return a.id < b.id;
}
bool cmpSugar(int a,int b){
return a > b;
}
int main() {
int n = 0;// 小熊數量
int m = 0;// 糖數
scanf("%d%d",&n,&m);
int sugars[m];
for(int i=0;i<m;++i){
scanf("%d",&sugars[i]);
}
Bear bears[n];
for(int i=0;i<n;++i){
scanf("%d%d",&bears[i].finger,&bears[i].hunger);
bears[i].id = i; // 記錄進入的順序
}
// 糖果按照大小排序
sort(sugars,sugars+m,cmpSugar);
// 小熊按照戰鬥力排序
sort(bears,bears+n,cmpBear);
for(int i=0;i<n;++i){
for(int j=0;j<m;++j){
if(sugars[j] != 0 && bears[i].hunger >= sugars[j]){
// bears[i].hunger = bears[i].hunger - sugars[j];
bears[i].hunger -= sugars[j];
sugars[j] = 0;
}
}
}
sort(bears,bears+n,cmpBearById);// 按照進入順序重新排序
for(int i=0;i<n;++i){
printf("%d\n",bears[i].hunger);
}
return 0;
}
方法二:
#include <bits/stdc++.h>
using namespace std;
// 小熊結構體
struct Bear{
int finger; // 戰鬥力
int hunger; // 飢餓值
int id; // 編號
};
struct Sugar{
int value; // 糖果數值
bool eated; // 是否被吃掉
};
bool cmpBear(Bear a,Bear b){
return a.finger > b.finger;
}
bool cmpBearById(Bear a,Bear b){
return a.id < b.id;
}
bool cmpSugar(Sugar a,Sugar b){
return a.value > b.value;
}
int main() {
int n = 0;// 小熊數量
int m = 0;// 糖數
scanf("%d%d",&n,&m);
Sugar sugars[m];
for(int i=0;i<m;++i){
scanf("%d",&sugars[i].value);
sugars[i].eated = false;
}
Bear bears[n];
for(int i=0;i<n;++i){
scanf("%d%d",&bears[i].finger,&bears[i].hunger);
bears[i].id = i; // 記錄進入的順序
}
// 糖果按照大小排序
sort(sugars,sugars+m,cmpSugar);
// 小熊按照戰鬥力排序
sort(bears,bears+n,cmpBear);
for(int i=0;i<n;++i){
for(int j=0;j<m;++j){
if(sugars[j].eated == false && bears[i].hunger >= sugars[j].value){
// bears[i].hunger = bears[i].hunger - sugars[j];
bears[i].hunger -= sugars[j].value;
sugars[j].eated = true;
}
}
}
sort(bears,bears+n,cmpBearById);// 按照進入順序重新排序
for(int i=0;i<n;++i){
printf("%d\n",bears[i].hunger);
}
return 0;
}
本題知識點:
結構體
把多個變數綁到一起的一個型別,可以把結構體看成一個多個變數組成包。
struct 結構體{
變數...
};
例如: 定義結構體
struct UserInfo{
string name;
int age;
bool sex;
};
使用
UserInfo zhangsan;
zhangsan.name = "張三";
zhangsan.age = 31;
zhangsan.sex = true;
結構體陣列
UserInfo users[n];
users[i].name
users[i].age
users[i].sex
本篇部落格就到此結束了,當然,題目還有很多,如果有興趣繼續學習的話可看緊接的下一篇部落格。
歡迎討論互動,也可關注個人微信公眾號“老凱運維”;畢竟運維工程師會開發路能夠走的更遠,開發會運維也是一個加分項。