首页 > 8.23 腾讯技术笔试题 后端开发 AC 4.5/5
头像
ShowMeTheCodee
编辑于 2020-08-24 09:38
+ 关注

8.23 腾讯技术笔试题 后端开发 AC 4.5/5

第一题 AC,比较简单的热身题:

#include <iostream>
#include <vector>
using namespace std;

typedef struct node {
  int val;
  node* next;
  node(int val) : val(val), next(NULL) {}
} node;

int main() {
  int n, k;
  cin >> n >> k;
  node* vhead = new node(0);
  node* last = vhead;
  int v;
  for (int i = 0; i < n; i++) {
    cin >> v;
    if (i + 1 == k) continue;
    last->next = new node(v);
    last = last->next;
  }
  for (node* p = vhead->next; p; p = p->next) {
    printf("%d ", p->val);
  }
  return 0;
}

第二题 AC,这里的关键在于 cmp 函数。很明显不能把所有子串找到后再排序,会爆内存。因此只能保证生成子串的时候就是按照字典序生成的:

#include <algorithm>
#include <iostream>
#include <set>
#include <string>
#include <vector>
using namespace std;

string s;
typedef pair<int, char> Item;
bool cmp(const Item &a, const Item &b) {
  if (a.second == b.second) {
    int i = a.first, j = b.first;
    while (s[i] == s[j] && i < s.length() && j < s.length()) {
      i++, j++;
    }
    if (i < s.length() && j < s.length()) {
      return s[i] < s[j];
    }
    return i < s.length();
  }
  return a.second < b.second;
}

// ac 关键在于 cmp 函数
// acab 2
int main() {
  int k;
  cin >> s >> k;
  set<string> ss;
  vector<Item> pairs(s.length());
  for (int i = 0; i < s.length(); i++) {
    pairs[i] = Item(i, s[i]);
  }
  sort(pairs.begin(), pairs.end(), cmp);
  for (int i = 0; i < pairs.size(); i++) {
    int start = pairs[i].first;
    for (int l = 1; l <= s.length() - start; l++) {
      ss.insert(s.substr(start, l));
    }
    if (ss.size() >= k) break;
    k -= ss.size();
    ss.erase(ss.begin(), ss.end());
  }
  int c = 1;
  for (std::set<string>::iterator it = ss.begin(); it != ss.end(); it++, c++) {
    if (c == k) {
      cout << *it << endl;
      return 0;
    }
  }
  return 0;
}

第三题只过了 50%。有个 bug,现在修了。不过这道题看其他同学的题解,有更优的解法。

#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;

#define IType long long
map<IType, int> ss;

int s(IType a) {
  if (ss.find(a) != ss.end()) return ss[a];
  int res = 0;
  IType n = a;
  while (n) {
    res += n % 10;
    n /= 10;
  }
  ss[a] = res;
  return res;
}

int main() {
  int t;
  cin >> t;
  while (t--) {
    IType n;
    int res = 0;
    cin >> n;
    for (IType a = 0; a <= n / 2; a++) {
      res = max(res, s(a) + s(n - a));
    }
    cout << res << endl;
  }
  return 0;
}

第四题 AC:

#include <iostream>
#include <map>
using namespace std;

int heights[5010];

int minIndex(int l, int r) {
  int res = l;
  for (int i = l + 1; i <= r; i++) {
    if (heights[i] < heights[res]) res = i;
  }
  return res;
}

// 对于每个区间的柱子,有两种情况:
// 如果不横着刷,那就每个柱子分别竖着刷
// 如果横着刷,那就按最矮的柱子的高度,下方全部横着刷掉(否则如果不刷掉,那柱子数量没变,反而增加了刷的次数)
// 横着刷完后,最矮柱子左右分成两个区间,递归。这两个区间再计算横着刷的次数时,应当把下方已经刷过的高度减掉
// 但是如果计算竖着刷的次数,那么下方被刷过的地方并不影响


// 注意这几个测试用例
// 3 4 -> 2
// 55 55 1 -> 3
// 2 2 1 2 1 -> 3
int dfs(int l, int r, int base) {
  if (l > r) return 0;
  if (l == r)
    return min(1, heights[l] - base);  // 返回:竖着刷 or 横着刷的最小值
  int idx = minIndex(l, r);
  int minHeight = heights[idx];
  int res = (minHeight - base) +          // 需要横着刷的次数
            dfs(l, idx - 1, minHeight) +  // 左面区间的最少次数
            dfs(idx + 1, r, minHeight);   // 右面区间的最少次数
  return min(r - l + 1, res);  // 返回:全部竖着刷 or 下方横着刷的最小值
}

int main() {
  int n;
  cin >> n;
  for (int i = 0; i < n; i++) cin >> heights[i];
  cout << dfs(0, n - 1, 0) << endl;
  return 0;
}

第五题 AC,这道题和 leetcode 131、132 异曲同工。两个 dp 就可以了:

#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;

bool flag[410][410]; // flag[i][j] 表示 s[i~j] 是不是回文子串
int dp[410][410];  // dp[i][j] 表示 s[i~j] 被拆分为多少个子串

int main() {
  string s;
  cin >> s;
  for (int l = 1; l <= s.length(); l++) {
    for (int i = 0; i <= s.length() - l; i++) {
      int j = i + l - 1;
      flag[i][j] = s[i] == s[j] && (i + 1 > j - 1 || flag[i + 1][j - 1]);
    }
  }
  for (int l = 1; l <= s.length(); l++) {
    for (int i = s.length() - 1; i >= 0; i--) {
      int j = i + l - 1;
      if (flag[i][j])
        dp[i][j] = 1;
      else {
        dp[i][j] = 0x7fffffff; // 这里必须手动设置为最大值
        for (int k = i; k < j; k++) {
          if (flag[i][k]) dp[i][j] = min(dp[i][j], 1 + dp[k + 1][j]);
        }
      }
    }
  }
  int q;
  cin >> q;
  while (q--) {
    int l, r;
    cin >> l >> r;
    cout << dp[l - 1][r - 1] << endl;
  }
  return 0;
}

全部评论

(3) 回帖
加载中...
话题 回帖

推荐话题

相关热帖

历年真题 真题热练榜 24小时
技术(软件)/信息技术类
查看全部

近期精华帖

热门推荐