恭喜发现宝藏!微信搜索公众号【TechGuide】回复公司名,解锁更多新鲜好文和互联网大厂的笔经面经。
作者@TechGuide【全网同名】
点赞再看,养成习惯,您动动手指对原创作者意义非凡🤝
第一题:礼品盒分配
题目:
小美做饼干,有AB两种,做成礼盒卖,每个礼盒三个饼干,且至少包含一个A 和 一个B。现在给你A和B的数量,问最多可以做多少礼盒?
思路:
分析了一下,礼盒的数量为(A,B,(A+B)/3)三者的最小值。
代码
CPP版本
int main() {
int T;
cin >> T;
int x;
int y;
while (T--) {
cin >> x >> y;
int ans = min({(x+y)/3, x ,y});
cout << ans << endl;
}
return 0;
}
// 微信公众号关注TechGuide 实时题库 闪电速递
Java版本
import java.util.Scanner;
public class Q1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
for (int i = 0; i < N; i++) {
int x = sc.nextInt();
int y = sc.nextInt();
System.out.println(getCount(x,y));
}
}
public static int getCount(int A,int B){
//假设能做x盒,那么 x<=A x<=B 且 3x<=A+B
int x = (A+B)/3;
x = Math.min(x,A);
x = Math.min(x,B);
return x;
}
}
// 微信公众号关注TechGuide 实时题库 闪电速递
第二题:实验结果
题目:
小美做实验,有一个纸带上有若干个数字,在纸带上选择一个位置k,k是分割点(比如k选3,那么左边是123,右边是456),k左边大于等于0的点为异常点,k右边小于等于0的点为异常点。
现在给一个纸带,不给k,问你最乐观情况下异常点最少个数为多少(选哪个k异常点最少吧)
思路:
用前缀数组,记录每个点左边的异常点,再从右边计算异常点回来,每次左右异常点个数相加,取最小一个。
题解
CPP版本
int main() {
int N;
cin >> N;
vector<int> nums;
int sum = 0;
int num;
int mis = 0;
for (int i=0; i<N; ++i) {
cin >> num;
if (num == 0) {
++mis;
}
else {
nums.push_back(num);
sum += num;
}
}
// 微信公众号关注TechGuide 实时题库 闪电速递
int mis1 = INT_MAX;
int preSum = 0;
int n = nums.size();
for (int i=0; i<n; ++i) {
int p1 = (i + preSum) / 2;
int p2 = ((n-i) - (sum - preSum)) / 2;
preSum += nums[i];
mis1 = min(mis1,p1+p2);
}
mis1 = min(mis1, (n-preSum)/2);
cout << mis1+mis<<endl;
}
Java版本
import java.util.Scanner;
public class Q2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int arr[] = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = sc.nextInt();
}
System.out.println(minException(arr));
}
// 微信公众号关注TechGuide 实时题库 闪电速递
public static int minException(int arr[]){
int n = arr.length;
int ans = Integer.MAX_VALUE;
int leftException[] = new int[n];
leftException[0] = 0;
for(int i = 1; i < n; i++){
leftException[i] = leftException[i-1];
if(arr[i-1]>=0){
leftException[i]++;
}
}
// printArr("leftException",leftException);
int rightException = 0;
for(int i = n-1; i>=0; i--){
if(arr[i]<=0) rightException++;
ans = Math.min(ans,leftException[i]+rightException);
}
return ans;
}
public static void printArr(String str ,int arr[]){
System.out.println(str);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+"\t");
}
System.out.println();
}
}
第三题:翻转石头
题目
小美有n个魔法石,每个魔法石有正反两个数字,一开始全部正面朝上,魔法石要激活需要有一半以上的魔法石数字相同,问你把魔法石激活的最小翻牌次数(把魔法石从正面变反面)
每个魔法石有两面,分为正面和反面,正面有一个数字,反面有一个数字。然后一开始魔法石全部正面朝上。魔法石要激活,要魔法石中有相同数字的魔法石数量超过一半才可以。然后你可以对魔法石进行翻面,问最少翻多少次能激活魔法石。
思路
计每个牌出现的数量,因为能出现一半以上的最多四种吧,然后去遍历能出现一半以上的数量,然后去扣掉正面牌上这个数的数量,就是需要翻牌的数量。然后找最小
代码
CPP版本
#include <iostream>
#include <algorithm>
#include <vector>
#include <limits.h>
#include <unordered_map>
using namespace std;
// 翻石头
int main() {
int N;
cin >> N;
vector<long long> nums1(N);
vector<long long> nums2(N);
unordered_map<long long, int> map1;
unordered_map<long long, int> map0;
long long num;
for (int i=0; i<N; ++i) {
cin >> num;
map1[num]++;
nums1[i] = num;
}
map0 = map1;
for (int i=0; i<N; ++i) {
cin >> num;
nums2[i] = num;
if (nums1[i] != num) {
map0[num]++;
}
}
int ret = INT_MAX;
int target = (N+1)>>1;
for (auto& item : map0) {
if (item.second < target) continue;
int have = map1[item.first];
if (have >= target) {
ret = 0;
break;
}
else {
ret = min(ret, target-have);
}
}
ret = ret==INT_MAX? -1 : ret;
cout << ret << endl;
return 0;
}
// 微信公众号关注TechGuide 实时题库 闪电速递
Java版本
import java.util.HashMap;
import java.util.HashSet;
import java.util.Scanner;
public class Q3 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int up[] = new int[n];
int down[] = new int[n];
for (int i = 0; i < n; i++) {
up[i] = sc.nextInt();
}
for (int i = 0; i < n; i++) {
down[i] = sc.nextInt();
}
System.out.println(minOps(n,up,down));
}
// 微信公众号关注TechGuide 实时题库 闪电速递
public static int minOps(int n, int[] up, int[] down){
HashMap<Integer,Integer> allMap = new HashMap<>();
HashMap<Integer,Integer> upMap = new HashMap<>();
//先统计个数
for (int i = 0; i < n; i++) {
//两面相同统计一次
allMap.put(up[i],allMap.getOrDefault(up[i],0)+1);
if(up[i]!=down[i]){
allMap.put(down[i],allMap.getOrDefault(down[i],0)+1);
}
upMap.put(up[i],upMap.getOrDefault(up[i],0)+1);
}
int target = n%2==0?n/2:n/2+1;
int ans = n+1;
for (Integer key : allMap.keySet()) {
if(allMap.get(key)>=target){
ans = Math.min(ans,upMap.getOrDefault(key,0)>=target?0:target-upMap.getOrDefault(key,0));
}
}
return ans==n+1?-1:ans;
}
}
第四题:分割训练集和测试集
题目:
按顺序给你一堆训练集(只有类别编号),就是给了一个数组,然后每个类别中,前(类别数据个数)/2向上取整为训练集,后面的是测试集,让我们按顺序拆分
思路:
计数拆分
代码
CPP版本
#include <iostream>
#include <algorithm>
#include <vector>
#include <limits.h>
#include <unordered_map>
using namespace std;
// 分割训练集 和 测试集
ostream& operator<<(ostream& os, vector<int>& nums) {
for (int num : nums) {
os << num << " ";
}
os << endl;
return os;
}
int main() {
int N;
int m;
cin >> N >> m;
unordered_map<int,int> map;
vector<int> nums(N);
vector<int> train;
vector<int> test;
int num;
for (int i=0; i<N; ++i) {
cin >> num;
map[num]++;
nums[i] = num;
}
for (auto& item : map) {
item.second = (item.second+1) / 2;
}
for (int i=0; i<N; ++i) {
if (map[nums[i]] > 0) {
train.push_back(i+1);
map[nums[i]]--;
}
else {
test.push_back(i+1);
}
}
cout << train << test;
return 0;
}
// 微信公众号关注TechGuide 实时题库 闪电速递
Java版本
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Q4 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
int cnt[] = new int[k+1];
int arr[] = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
cnt[arr[i]]++;
}
int order[] = new int[k+1];//表示k当前访问的个数
List<Integer> train = new ArrayList<>();
List<Integer> test = new ArrayList<>();
for (int i = 0; i < n; i++) {
order[arr[i]]++;
if(order[arr[i]] <= (cnt[arr[i]]%2==0?cnt[arr[i]]/2:cnt[arr[i]]/2+1)){
train.add(i+1);
}
else{
test.add(i+1);
}
}
for (int i = 0; i < train.size()-1; i++) {
System.out.print(train.get(i)+" ");
}
if(train.size()>0)
System.out.println(train.get(train.size()-1));
else{
System.out.println();
}
for (int i = 0; i < test.size()-1; i++) {
System.out.print(test.get(i)+" ");
}
if(test.size()>0) System.out.println(test.get(test.size()-1));
else System.out.println();
}
}
// 微信公众号关注TechGuide 实时题库 闪电速递
第五题:第K个数字
题目:
初始字符串为MetTuan,每次对字符串做 str = str + str.reverse() + "wow"的操作,无限循环。后面给你一个k,问你位置k的字符为什么。
思路
找规律
无限循环后 是 str+str.reverse()+"wowwow"的无限循环
代码
CPP版本
#include <iostream>
#include <algorithm>
#include <vector>
#include <limits.h>
#include <unordered_map>
#include "string"
using namespace std;
//f(s) = s + r(s) + "wow";
string orgin = "MeiTuannauTieMwow";
char getNth(long long k, vector<long long>& cnt) {
if (k <= 7) return orgin[k-1];
int i = cnt.size()-1;
for ( ; i>=0; --i) {
if (k > cnt[i]) break;
}
k -= cnt[i];
if (k <= cnt[i]) {
long long idx = cnt[i] - k + 1;
return getNth(idx, cnt);
}
else {
k -= cnt[i];
if (k == 1) return 'w';
if (k == 2) return 'o';
if (k == 3) return 'w';
}
}
int main() {
vector<long long> cnt(55);
cnt[0] = 7;
for (int i=1; i<cnt.size(); ++i) {
cnt[i] = cnt[i-1]*2 + 3;
}
int N;
cin >> N;
long long k;
while (N--) {
cin >> k;
char c = getNth(k,cnt);
cout << c << endl;
}
return 0;
}
// 微信公众号关注TechGuide 实时题库 闪电速递
Java版本
import java.util.Scanner;
public class Q5 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
String str = "MeiTuan";
str = str + (new StringBuilder(str).reverse().toString())+"wowwow";
for (int i = 0; i < T; i++) {
long pos = sc.nextLong()-1;
pos = pos % str.length();
System.out.println(str.charAt((int)pos));
}
}
// 微信公众号关注TechGuide 实时题库 闪电速递
public static String function(String str){
return str + (new StringBuilder(str).reverse().toString()) + "wow";
}
/*
s
s fs wow
(s fs wow) (wow s fs) wow
[(s fs wow) (wow s fs) wow][wow (s fs) wow wow (s fs)] wow
{[(s fs wow) (wow s fs) wow][wow (s fs) wow wow (s fs)] wow} {wow s fs wow wow s fs wow wow s fs wow wow sfs w
*/
}