2018互联网大厂秋招编程通关(二)

通过上一篇的继续学习,链接地址为:

https://blog.csdn.net/chao199512/article/details/83713409

接下来,我们继续讲解秋招笔试编程题,及其知识点总结。

(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

本篇博客就到此结束了,当然,题目还有很多,如果有兴趣继续学习的话可看紧接的下一篇博客。

欢迎讨论互动,也可关注个人微信公众号“老凯运维”;毕竟运维工程师会开发路能够走的更远,开发会运维也是一个加分项。

猜你喜欢

转载自blog.csdn.net/chao199512/article/details/83715369