目录
一、前言
共四题、一题来自某个厂的前端夏令营笔试、三体来自leetcode周赛
二、题目和代码解答(都是C)
1、数组元素去重
题目要求很简单、就是输入数组然后输出去除重复的元素的新数组。
我本来想用C++来做但是发现了一些问题,要求的输入中是含有 ',' 这样的标点符号的,外加我本人c++太拉了,所以最终还是用了c语言完成
这道题的一个难点在于原地去重(tps:命题人没说要不要原地、经我自己的检验是要的)
如果不用原地去重,不妨可以使用一个排序将数组重新排序,然后比较相邻间元素是否相等即可。
以下是原地去重的C代码
#include<stdio.h>
#include<stdlib.h>
#define N 10000
int main(void)
{
int nums[N], len = 0, x;
while (scanf("%d", &x))
{
nums[len++] = x;
// 嵌套循环遍历看新添加的是否已经和前面的数字重叠
for (int i = 0; i < len - 1; i++)
{
// 如果重叠了就将长度减1,并跳出循环
if (nums[i] == nums[len - 1])
{
--len;
break;
}
}
// 每次输入数字后面跟着逗号,如果没有则证明输入结束、跳出循环
if (getchar() != ',')
{
break;
}
}
for (int i = 0; i < len - 1; i++)
{
// 带逗号输出
printf("%d,", nums[i]);
}
printf("%d\n", nums[len - 1]);
return 0;
}
2、三除数
就是给你一个整数n,如果n恰好用三个正除数,返回true,否则返回false。
链接https://leetcode-cn.com/problems/three-divisors/submissions/
解题思路
周赛第一题(装个*,这不是有hand就ok?)直接枚举,但是也可以做一下优化,比如枚举的范围,由于是除数,所以直接遍历到给定数的一半即可。另外考虑什么时候有三除数,就是三个因数、即除了1和数本身还有一个数,显然这个数的二次根式。
bool isThree(int n){
int b = 0;
for(int i = 2; i <= n/2; i ++)
{
if(n % i == 0)
{
if(i * i == n)
{
b = 1;
}
else
{
b = 0;
break;
}
}
}
if(b)
{
return true;
}
return false;
}
3、你可以工作的最大周数
给你 n 个项目,编号从 0 到 n - 1 。同时给你一个整数数组 milestones ,其中每个 milestones[i] 表示第 i 个项目中的阶段任务数量。
你可以按下面两个规则参与项目中的工作:
每周,你将会完成 某一个 项目中的 恰好一个 阶段任务。你每周都 必须 工作。
在 连续的 两周中,你 不能 参与并完成同一个项目中的两个阶段任务。
一旦所有项目中的全部阶段任务都完成,或者仅剩余一个阶段任务都会导致你违反上面的规则,那么你将 停止工作 。注意,由于这些条件的限制,你可能无法完成所有阶段任务。
返回在不违反上面规则的情况下你 最多 能工作多少周。
链接https://leetcode-cn.com/problems/maximum-number-of-weeks-for-which-you-can-work/
解题思路
我所想到的思路其实是先将数组排序、然后统计除最大的数外的元素和然后与最大元素比较,如果和值比最大数大等于则返回总和值,理由是在实际操作中最大数是影响最终的周数的主要原因。一种常见的操作是最大数起手,然后与第二大的做反复横跳消减,重复这个操作。
以下是代码
int cmp(const void* a, const void* b)
{
return *(int*)a - *(int*)b;
}
long long numberOfWeeks(int* milestones, int milestonesSize){
if(milestonesSize == 1)
{
return 1;
}
int len = milestonesSize, *n = milestones;
qsort(n, len, sizeof(int), cmp);
int b = 0;
long long sum = 0;
for(int i = 0; i < len; i ++)
{
if(i == len - 1)
{
if(sum >= n[i])
{
b = 1;
}
}
sum += n[i];
}
if(b)
{
return sum;
}
return 2 * (sum - n[len - 1]) + 1;
}
4、收集足够苹果的最小花园周长
这道题,作者实现了从0的突破,以前从来没有做出第三题的,有点小泪目。
给你一个用无限二维网格表示的花园,每一个 整数坐标处都有一棵苹果树。整数坐标 (i, j) 处的苹果树有 |i| + |j| 个苹果。
你将会买下正中心坐标是 (0, 0) 的一块 正方形土地 ,且每条边都与两条坐标轴之一平行。
给你一个整数 neededApples ,请你返回土地的 最小周长 ,使得 至少 有 neededApples 个苹果在土地 里面或者边缘上。
|x| 的值定义为:
如果 x >= 0 ,那么值为 x
如果 x < 0 ,那么值为 -x
链接:https://leetcode-cn.com/problems/minimum-garden-perimeter-to-collect-enough-apples/
解题思路
其实就是规律,当然这个规律要放到每一层去解读
这里就不推了。。。。(有点懒,困了)
long long minimumPerimeter(long long neededApples){
long long c = 0, sum = 0, l;
long long n = neededApples;
for(int i = 0; ; ++ i)
{
l = 2 * (i + 1);
c = 4 * l;
sum += 6 *l + 6 * l * i;
if(sum >= n)
{
break;
}
}
return c;
}