题目:
给出一个旋转矩阵,M行N列,左上角为(0,0),右下角为(M-1,N-1),从左上角开始计数,顺时针从外圈开始,外圈遍历完之后再遍历内圈,直到遍历完所有的点。
返回所有个位数为7且十位数为奇数的坐标,10 <= M,N <= 1000,当输入不合法的时候返回空数组。
输入 M,N
10 10
输出
[[7,9],[1,1],[8,2],[7,5],[4,4]]
分析:题目不难理解,剑指offer上面题目的变种,判断一下是否合法,合法就加入结果集。
但是我一直卡在70%,一开始以为是超时,后来做完看牛客才知道原来题目中说的10 <= M,N <= 1000不是输入数据的大小而是如果数据超过这个范围要返回空数组。
看来是题目做少了,没想明白门道,我还一直在想怎么会超时。
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int m = scan.nextInt();
int n = scan.nextInt();
int left = 0;
int right = n-1;
int up = 0;
int down = m-1;
int index = 1;
List<int[]> res = new ArrayList<>();
//记得判断一下数据范围
while(n >= 10 && m >= 10 && n<= 1000 && m <= 1000){
for(int i=left;i<=right;i++){
if(check(index))
res.add(new int[]{
up,i});
index++;
}
up++;
if(up > down)
break;
for(int i=up;i<=down;i++){
if(check(index))
res.add(new int[]{
i,right});
index++;
}
right--;
if(left > right)
break;
for(int i=right;i>=left;i--){
if(check(index))
res.add(new int[]{
down,i});
index++;
}
down--;
if(up > down)
break;
for(int i=down;i>=up;i--){
if(check(index))
res.add(new int[]{
i,left});
index++;
}
left++;
if(left > right)
break;
}
System.out.print('[');
for(int i=0;i<res.size();i++){
int[] tmp = res.get(i);
System.out.print('[');
System.out.print(tmp[0]);
System.out.print(',');
System.out.print(tmp[1]);
System.out.print(']');
if(i!=res.size()-1)
System.out.print(',');
}
System.out.print(']');
}
public static boolean check(int index){
if((index%10 == 7) && (((index/10)&1) == 1))
return true;
return false;
}
题目:给出一个数组,数组中的元素代表二叉树中一个节点的深度,求这个数组能够组成多少种二叉树。结果可能很大,需要mod(10^9+7)
输入 第一行为一个数组,代表元素个数,第二行为一组数据
4
0 1 2 2
分析:这道题的思路是先判断当前层有最多有多少个节点,然后看一下数组中当前层的节点个数,根据排列组合公式累乘。
解法不难,一直卡在50%,以为是溢出的问题,把所有数据改成long,还是50%,后来看牛客才知道原来输入数据可能构不成一颗二叉树,这个时候要返回0,比如有一层节点个数为0,有一层节点个数超出了上限。
看来还是题做少了,华为就喜欢搞这种奇奇怪怪的输入输出。
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] nums = new int[n];
for(int i=0;i<n;i++){
nums[i] = in.nextInt();
}
System.out.println(getRest2(nums));
}
private static long getRest2(int[] nums) {
long max = nums[0];
HashMap<Integer,Integer> map = new HashMap<>();
for(int now:nums){
map.put(now,map.getOrDefault(now,0)+1);
max = Math.max(max,now);
}
int pre = map.get(0);
if(pre != 1)
return 0;
long res = 1;
for(int i=1;i<=max;i++){
int now = map.get(i);
//判断一下非法情况
if(now == 0 || now > pre*2)
return 0;
res = res*getNum(now,pre*2)%MOD;
pre = now;
}
return res;
}
private static long getNum(int m, int n) {
long num1 = 1;
long num2 = 1;
for(long i=n-m+1;i<=n;i++){
num1=num1*i%MOD;
}
for (long i=1;i<=m;i++){
num2 = num2*i%MOD;
}
return num1/num2;
}
题目:
俄罗斯方块。给定字符串frame和brike,frame类似2202这种,表示长为4,高为2,2,0,2的方块(每个方块的单位为1,该位是2就是两个堆在一起),brike类似121,表示长为3,高为121的方块(多的那个向下)。如果一行被填充满了即可消除掉。问给定了两个字符串之后,最后剩下的最小行数是多少。
(题干来自于牛客作者zshunyi,原贴)
输入 第一行表示底部每一列的高度,第二行表示方块每一列的高度,都是向下凸的。
2202
2
输出 表示剩余的最小行数
0
分析:就模拟,听说测试用例比较弱。不过我只过了70%不知道哪里有问题。
这里贴一份大佬cuber~的代码,代码来源。
int helper(vector<int>& frame, vector<int>& brick)
{
int frame_n = frame.size(), brick_n = brick.size();
int res = 1000000;
for (int i = 0;i < frame_n - brick_n + 1;i++)
{
int max_h = 0, total_max_h;
for (int j = 0;j < brick_n;j++)
max_h = max(max_h, brick[j] + frame[i + j]);
total_max_h = max_h;
int r = 100000;
for (int j = 0;j < frame_n;j++)
{
total_max_h = max(total_max_h, frame[j]);
if (j < i)
r = min(r, frame[j]);
else if (j >= (i + brick_n))
r = min(r, frame[j]);
else
{
int tmp1 = frame[j], tmp2 = brick[j - i];
if (tmp1 + tmp2 == max_h)
r = min(r, max_h);
else
r = min(r, tmp1);
}
}
res = min(res, total_max_h - r);
}
return res;
}
int main()
{
string s1, s2;
cin >> s1 >> s2;
vector<int> frame(s1.size()), brick(s2.size());
for (int i = 0;i < s1.size();i++) frame[i] = s1[i] - '0';
for (int i = 0;i < s2.size();i++) brick[i] = s2[i] - '0';
cout << helper(frame, brick);
return 0;
}
上周华为的笔试感觉好像简单一些,可惜没能参加,那天晚上面的PCG还把我挂了,真难受。
昨天晚上5点的时候,腾讯发邮件叫我晚上8点面试,和华为笔试撞上了就调到了周五晚上。结果没想到过了一夜,先是美团发邮件说周六下午笔试,然后11点时候腾讯发邮件说周日晚上8点笔试,最后今天滴滴发邮件说周五晚上笔试。
关键是滴滴的第二批笔试都到9月中了,没办法,又联系hr改腾讯的面试时间。
淦,为什么你们都喜欢挤在一起啊,雷火这边约了明天早上面试,这次应该是hr面了吧,有道还是没消息。
秋招真难,希望晚上腾讯不要凉的太快。