1. 程式人生 > >2018網際網路大廠秋招程式設計通關(二)

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 是滿足如下定義的二維數表:

  1. 所有行均為左對齊,所有行的最左端在同一列,且每一行均連續無空位;
  2. 從上到下每一行的列數非嚴格單調遞減;
  3. 每一行中的數從左到右嚴格單調遞增;
  4. 每一列中的數從上到下嚴格單調遞增。 請編寫一個程式,判斷一個數表是否是Young Tableau。數表的行數和列數至多為10,所有數均為正整數。
  • 1 2 3 
    4 5 
    6 
    
    是Young Tableau,而
    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
    
  • 題目解析

  • 預備知識
    • 嚴格遞減表示<
    • 非嚴格遞減表示=<
    • 不定長資料表示
      1. 【C方式】通常使用一個定長陣列,非法數字表示行和列的結束。
      2. 【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的個數,那麼如何統計個數呢?有如下方法:將異或的結果與其減一進行與操作,直至與後的結果為零,就是二進位制不同位數的數量。

  • 例項解釋

    1. 2233進行異或。
    - 十進位制數 二進位制數
    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)&num;// 每次去除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)比較函式,ab不交換返回true(也就是想要的順序);firstlast交換返回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秋招------------小熊吃糖(點選文字進入連結)

題目解析

需要用到排序演算法:按戰鬥力對小熊們排序;按能填充的飢餓值對糖排序。注意

  1. 最終答案需要按照小熊輸入的順序進行輸出,在排序之後要記錄一下這個資訊。
  2. 一個小熊可能會吃多塊糖

參考答案

方法一:
#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

本篇部落格就到此結束了,當然,題目還有很多,如果有興趣繼續學習的話可看緊接的下一篇部落格。

歡迎討論互動,也可關注個人微信公眾號“老凱運維”;畢竟運維工程師會開發路能夠走的更遠,開發會運維也是一個加分項。