面试笔试算法-欧拉计划
面试笔试算法-二分专题
面试笔试算法-Oj刷题
面试笔试算法-LeetCode刷题
面试笔试算法-STL的使用
面试笔试算法之排列组合与搜索走地图问题
目录结构
欧拉计划
题目1:3或5的倍数
解题技巧:
蓝色框表示3的倍数、绿框是5的倍数、黄框是重复项
利用等差数列分别求出3的倍数的和、5的倍数和相加然后减去重复项15的倍数和
即得结果。时间复杂度为O(1)
#include<iostream>
using namespace std;
int main(int argc, char *grav[])
{
/* 第一种简单的方法,直接判断是否是3和5的倍数进行输出
int ans = 0;
for (int i = 1; i < 1000; i++) {
if (i % 3 == 0 || i % 5 == 0) {
ans += i;
}
}
cout << ans << endl;
*/
// 利用上述技巧编程
int t3 = (3 + 999) * 333 / 2;
int t5 = (5 + 995) * 199 / 2;
int t15 = (15 + 990) * 66 / 2;
cout << t3 + t5 - t15 << endl;
return 0;
}
题目2:偶裴波那锲数
解题思路
只需要三个变量来回循环利用计可!不断更新a、b、c的值
代码演示
#include<iostream>
using namespace std;
int main(int argc, char *grav[])
{
int a = 1, b = 1, c = 2, ans = 0;
while (c <= 4000000) {
if (c % 2 == 0) {
ans += c;
}
c = b + c;
a = b;
b = c - b;
}
cout << ans << endl;
return 0;
}
题目4:最大回文数乘积
解题技巧
首先定义一个临时的变量t用来存储反转后的数字
通过while循环来进行取余求模进行反转
如果t与原始的数据相等则是回文数
#include<iostream>
using namespace std;
int func(int x) {
int t = 0, row = x;
while (x) {
t = t * 10 + x % 10;
x /= 10;
}
return t == row;
}
int main(int argc, char *grav[])
{
int ans = 0;
for (int i = 100; i < 1000; i++) {
for (int j = i; j < 1000; j++) {
int t = i * j;
if (func(t)) {
ans = max(ans, t);
}
}
}
cout << ans << endl;
return 0;
}
题目6:平方的和与和的平方之差
比较基础,直接计算
#include<iostream>
using namespace std;
int main(int argc, char *grav[])
{
int sum = 0, psum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
psum += i * i;
}
cout << sum * sum - psum << endl;
return 0;
}
题目8:连续数字最大乘积(滑动窗口法)
思路
- 首先将数据复制,保存在本地为字符串
检查复制后的格式:删掉空格、换行
读入时用数组存储,读取每位时需转换为数字(- ‘0’)- 滑动窗口法
静态窗口:固定窗口大小
动态窗口:一般称为双指针- 解法:
使用滑动窗口法——静态窗口
只需考虑窗口进的数和出的数,可以减少运算次数
出:除以
进:乘以
注意值是否为0
数据中的关键是对0的处理,首先定义一个0的计数器zero_cnt,进入滑动窗口时:为0时,zero_cnt++,不更新结果,不是0,则乘以原有数的成绩,相反,出滑动窗口时,为0时,zero_cnt–,不是0,原有结果除以要出去的数,当zero_cnt 等于0时,更新答案。
#include<iostream>
using namespace std;
char num[1005];
long long ans, zero_cnt, now = 1;
int main(int argc, char *grav[])
{
cin >> num;
for (int i = 0; i < 1000; i++) {
if (i < 13) {
now *= num[i] - '0';
} else {
if (num[i] == '0') {
zero_cnt++;
} else {
now *= num[i] - '0';
}
if (num[i - 13] == '0') {
zero_cnt--;
} else {
now /= num[i - 13] - '0';
}
}
if (!zero_cnt) {
ans = max(ans, now);
}
}
cout << ans << endl;
return 0;
}
- 前13位不含0,可以直接计算now
- 注意窗口内0的情况
❗定义一个0的计数器 - ❌是否可以碰见0就将乘积变为1?
不行,需要存除除0以外数的乘积 - ❌是否可以将0直接变为1?可以减少判断次数,只需要对进来的值判断0
但这样是不可以的,因为有可能不满13位的两个0之间的数很大
比如11022340111111111111111111
执行时报错:floating point exception
除以0了可能会导致该错误
错误地估计了上界,9^13肯定超过了int类型的上界,所以使用long long
题目11:方阵中的最大乘积(方向数组)
思路
如上图所示:通过一个简单的矩阵推算出方向数组的八个方向,上(-1, 0)、下(1,0)、左(0,-1)、右(0,1)、右上(-1,1)、右下(1,1)、左下(1,-1)、左上(-1,-1)。
- 计算某个数各个方向的连续4个数的乘积最大值
计算问题:为了避免重复,只需要计算连续的4个方向进行计算。
边界问题:1、判断边界;2、边界补0(至少三圈0)
#include<iostream>
using namespace std;
int dirx[4] = {
0, 1, 1, 1};
int diry[4] = {
1, 1, 0, -1};
int num[30][30], ans;
int main(int argc, char *grav[])
{
for (int i = 5; i < 25; i++) {
for (int j = 5; j < 25; j++) {
cin >> num[i][j];
}
}
for (int i = 5; i < 25; i++) {
for (int j = 5; j < 25; j++) {
// 遍历四个方向
for (int k = 0; k < 4; k++) {
int t = num[i][j];
// 四个方向的延伸的四个数
for (int l = 1; l < 4; l++) {
int x = i + dirx[k] * l;
int y = j + diry[k] * l;
t *= num[x][y];