题目1:给定一个数组数组的每一个位置代表一个分值,同时给定同样长度的数组每个位置都是 0 或 1 代表分值数组对应位置是否能获取 (1 可以,0 不行), 给定整形 k 代表可以叫醒 k 分钟,即从任意位置开始连续 k 个位置的分值都可以加上,而不管对应位置是否为 1 或 0,在只能叫醒一次时求可以获得的分值的最大值
输入: n,k 代表数组长度,和叫醒一次能醒的时间 n 个数代表各个时间的分值 n 个数,都是 0 或 1 代表该时间是否清醒,1 清醒,0 不清醒 输出: 可以获得的最大分值利用滑动窗口的方式计算最大值,窗口大小为 k,一开始在窗口中为数组前 k 个数,窗口开始向后移动,此时如果左边出窗口的分值对应清醒位置为 0 则要剪去这个分数。
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
int len = in.nextInt();
int wake = in.nextInt();
int[] score = new int[len], wakeTime = new int[len];
for(int i = 0;i < len;i++){
score[i] = in.nextInt();
}
for(int i = 0;i < len;i++){
wakeTime[i] = in.nextInt();
}
System.out.println(solve(wake,score,wakeTime));
}
in.nextInt();
}
private static int solve(int wake, int[] score, int[] wakeTime) {
int max = 0;
int i = 0;
//初始前k个分值在窗口中
for(;i < wake && i < score.length;i++){
max += score[i];
}
int tmp = max;
//其实这里循环到score.length - k即可,即最后一个分值进入窗口
for(;i < score.length;i++){
//如果左边出窗口元素对应位置为0要减去这个分值
if(wakeTime[i - wake] == 0){
tmp -= score[i - wake];
}
//当前进入位置本身为1,说明不管在不在窗口都要加上
//这里max是当前最大值,而tmp是窗口当前情况最大值
if(wakeTime[i] == 1){
max += score[i];
}
tmp += score[i];
max = Math.max(tmp ,max);
}
return max;
}
}
题目2:有 n 个学生站成一排,每个学生有一个能力值,牛牛想从这 n 个学生中按照顺序选取 k 名学生,要求相邻两个学生的位置编号的差不超过 d,使得这 k 个学生的能力值的乘积最大,你能返回最大的乘积吗?
输入描述: 每个输入包含 1 个测试用例。每个测试数据的第一行包含一个整数 n (1 <= n <= 50),表示学生的个数,接下来的一行,包含 n 个整数,按顺序表示每个学生的能力值 ai(-50 <= ai <= 50)。接下来的一行包含两个整数,k 和 d (1 <= k <= 10, 1 <= d <= 50)。 输出描述 输出一行表示最大的乘积 输入例子: 3 7 4 7 2 50 输出例子: 49
import java.util.Scanner;
public class ComputeMaxProductDP {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int n = 0, k = 0, d = 0;
int[] array = null;
while (cin.hasNextInt()) {
n = cin.nextInt();
array = new int[n];
for (int i = 0; i < n; i++) {
array[i] = cin.nextInt();
}
k = cin.nextInt();
d = cin.nextInt();
}
System.out.println(computeMaxProduct(array, k, d));
}
static long max(long a, long b) {
return a > b ? a : b;
};
static long min(long a, long b) {
return a < b ? a : b;
};
private static long computeMaxProduct(int[] array, int k, int d) {
long dpMax[][] = new long[array.length][k];
long dpMin[][] = new long[array.length][k];
// dpMax[i][j] 表示以数组元素A【i】作结尾时, 序列长度为j+1的最大乘积结果
for (int i = 0; i < array.length; i++) {
// 最大乘积序列长度为1 时, a[i] 作为结尾元素时, 乘积序列的结果就是它本身
dpMax[i][0] = array[i];
dpMin[i][0] = array[i];
}
// 状态转移方程是 dpMax[i][j] = max(dpMax[i-1][j-1]* A[i], dpMin[i-d][j-1] *
// A[i])
// Tip: 一定注意, dpMax[i][j] 的含义是乘积序列长度为 j+1 时 A【i】 为最后一个元素时, 能够找到的最大乘积结果。使用 j+1 的原因是因为数组下标从 0 开始, 如果用 j 表示长度, 那么j=0 位置的元素是无意义的, 该位置的空间会被浪费
long maxSoFar = Long.MIN_VALUE;
for (int j = 1; j < k; j++) {// 开始计算乘积序列长度大于1 的情况
for (int i = j ; i < array.length; i++) {
// 长度为 j+1 时, 结尾元素 i 的位置至少要从 j 开始找起, 以保证从a[0] 到 a[j] 至少有 j+1 个元素。
dpMax[i][j] = Long.MIN_VALUE;
dpMin[i][j] = Long.MAX_VALUE;
for (int x = 1; x <= d && (i - x) >= j - 1; x++) {
// 倒数第二个元素的位置为 i-x , 下标i-x 至少需要大于等于j-1
long resMax = max(dpMax[i - x][j - 1] * array[i], dpMin[i - x][j - 1] * array[i]);
long resMin = min(dpMax[i - x][j - 1] * array[i], dpMin[i - x][j - 1] * array[i]);
if (resMax > dpMax[i][j])
dpMax[i][j] = resMax;
if (resMin < dpMin[i][j])
dpMin[i][j] = resMin;
}
}
}
// 最后一个元素的位置从 k-1 找起,遍历一下已经计算好的DP 表格, 获得最终解
for (int i = k-1; i < array.length; i++) {
if (dpMax[i][k-1] > maxSoFar) {
maxSoFar = dpMax[i][k-1];
}
}
return maxSoFar;
}
}
题目3:给定一个 n 行 m 列的地牢,其中 '.' 表示可以通行的位置,'X' 表示不可通行的障碍,牛牛从 (x0 , y0 ) 位置出发,遍历这个地牢,和一般的游戏所不同的是,他每一步只能按照一些指定的步长遍历地牢,要求每一步都不可以超过地牢的边界,也不能到达障碍上。地牢的出口可能在任意某个可以通行的位置上。牛牛想知道最坏情况下,他需要多少步才可以离开这个地牢。
输入描述:
每个输入包含 1 个测试用例。每个测试用例的第一行包含两个整数 n 和 m(1 <= n, m <= 50),表示地牢的长和宽。接下来的 n 行,每行 m 个字符,描述地牢,地牢将至少包含两个 '.'。接下来的一行,包含两个整数 x0, y0,表示牛牛的出发位置(0 <= x0 < n, 0 <= y0 < m,左上角的坐标为 (0, 0),出发位置一定是 '.')。之后的一行包含一个整数 k(0 < k <= 50)表示牛牛合法的步长数,接下来的 k 行,每行两个整数 dx, dy 表示每次可选择移动的行和列步长(-50 <= dx, dy <= 50)
输出描述:
输出一行一个数字表示最坏情况下需要多少次移动可以离开地牢,如果永远无法离开,输出 -1。以下测试用例中,牛牛可以上下左右移动,在所有可通行的位置.上,地牢出口如果被设置在右下角,牛牛想离开需要移动的次数最多,为3次。
输入例子: 3 3 ... ... ... 0 1 4 1 0 0 1 -1 0 0 -1 输出例子: 3bfs。当存在 ‘.’ 的位置没有访问,输出 - 1。
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 50 + 5;
struct que {
int x, y;
int step;
que() {}
que(int _x, int _y, int _step) {
this -> x = _x;
this -> y = _y;
this -> step = _step;
}
};
int n, m;
char tmap[maxn][maxn];
int sx, sy;
int k;
int dx[maxn], dy[maxn];
void input() {
for(int i = 0; i < n; ++i) {
scanf("%s", tmap[i]);
}
scanf("%d%d", &sx, &sy);
scanf("%d", &k);
for(int i = 0; i < k; ++i) {
scanf("%d%d", &dx[i], &dy[i]);
}
}
bool check(int x, int y) {
return (x >= 0 && x < n && y >= 0 && y < m && tmap[x][y] == '.');
}
int bfs() {
queue q;
q.push(que(sx, sy, 0));
bool vis[maxn][maxn];
memset(vis, false, sizeof(vis));
vis[sx][sy] = true;
int ans = 0;
while(!q.empty()) {
que p = q.front(); q.pop();
ans = max(ans, p.step);
for(int i = 0; i < k; ++i) {
int xx = p.x + dx[i];
int yy = p.y + dy[i];
if(!vis[xx][yy] && check(xx, yy)) {
vis[xx][yy] = true;
q.push(que(xx, yy, p.step + 1));
}
}
}
for(int i = 0; i < n; ++i) {
for(int j = 0; j < m; ++j) {
if(tmap[i][j] == '.' && vis[i][j] == false) {
return -1;
}
}
}
return ans;
}
void solve() {
printf("%d\n", bfs());
}
int main() {
while(scanf("%d%d", &n, &m) != EOF) {
input();
solve();
}
return 0;
}
题目4:输入一个整数 n,求从 1 到 n 这 n 个整数的十进制表示中 1 出现的次数。
例如输入 12,从 1 到 12 这些整数中包含 1 的数字有 1,10,11 和 12,1 一共出现了 5 次。
#include "string.h"
#include "stdlib.h"
int NumberOf1(const char* strN);
int PowerBase10(unsigned int n);
/
// Find the number of 1 in an integer with radix 10
// Input: n - an integer
// Output: the number of 1 in n with radix
/
int NumberOf1BeforeBetween1AndN_Solution2(int n){
if(n <= 0)
return 0;
// convert the integer into a string
char strN[50];
sprintf(strN, "%d", n);
return NumberOf1(strN);
}
/
// Find the number of 1 in an integer with radix 10
// Input: strN - a string, which represents an integer
// Output: the number of 1 in n with radix
/
int NumberOf1(const char* strN){
if(!strN || *strN < '0' || *strN > '9' || *strN == '\0')
return 0;
int firstDigit = *strN - '0';
unsigned int length = static_cast<unsigned int>(strlen(strN));
// the integer contains only one digit
if(length == 1 && firstDigit == 0)
return 0;
if(length == 1 && firstDigit > 0)
return 1;
// suppose the integer is 21345
// numFirstDigit is the number of 1 of 10000-19999 due to the first digit
int numFirstDigit = 0;
// numOtherDigits is the number of 1 01346-21345 due to all digits
// except the first one
int numOtherDigits = firstDigit * (length - 1) * PowerBase10(length - 2);
// numRecursive is the number of 1 of integer 1345
int numRecursive = NumberOf1(strN + 1);
// if the first digit is greater than 1, suppose in integer 21345
// number of 1 due to the first digit is 10^4. It's 10000-19999
if(firstDigit > 1)
numFirstDigit = PowerBase10(length - 1);
// if the first digit equals to 1, suppose in integer 12345
// number of 1 due to the first digit is 2346. It's 10000-12345
else if(firstDigit == 1)
numFirstDigit = atoi(strN + 1) + 1;
return numFirstDigit + numOtherDigits + numRecursive;
}
/
// Calculate 10^n
/
int PowerBase10(unsigned int n){
int result = 1;
for(unsigned int i = 0; i < n; ++ i)
result *= 10;
return result;
}
题目5:输入两个整数序列。其中一个序列表示栈的 push 顺序,判断另一个序列有没有可能是对应的 pop 顺序。为了简单起见,我们假设 push 序列的任意两个整数都是不相等的。
比如输入的 push 序列是 1、2、3、4、5,那么 4、5、3、2、1 就有可能是一个 pop 系列。因为可以有如下的 push 和 pop 序列:push 1,push 2,push 3,push 4,pop,push 5,pop,pop,pop,pop,这样得到的 pop 序列就是 4、5、3、2、1。但序列 4、3、5、1、2 就不可能是 push 序列 1、2、3、4、5 的 pop 序列。
#include
/
// Given a push order of a stack, determine whether an array is possible to
// be its corresponding pop order
// Input: pPush - an array of integers, the push order
// pPop - an array of integers, the pop order
// nLength - the length of pPush and pPop
// Output: If pPop is possible to be the pop order of pPush, return true.
// Otherwise return false
/
bool IsPossiblePopOrder(const int* pPush, const int* pPop, int nLength){
bool bPossible = false;
if(pPush && pPop && nLength > 0)
{
const int *pNextPush = pPush;
const int *pNextPop = pPop;
// ancillary stack
std::stack<int> stackData;
// check every integers in pPop
while(pNextPop - pPop < nLength)
{
// while the top of the ancillary stack is not the integer
// to be poped, try to push some integers into the stack
while(stackData.empty() || stackData.top() != *pNextPop)
{
// pNextPush == NULL means all integers have been
// pushed into the stack, can't push any longer
if(!pNextPush)
break;
stackData.push(*pNextPush);
// if there are integers left in pPush, move
// pNextPush forward, otherwise set it to be NULL
if(pNextPush - pPush < nLength - 1)
pNextPush ++;
else
pNextPush = NULL;
}
// After pushing, the top of stack is still not same as
// pPextPop, pPextPop is not in a pop sequence
// corresponding to pPush
if(stackData.top() != *pNextPop)
break;
// Check the next integer in pPop
stackData.pop();
pNextPop ++;
}
// if all integers in pPop have been check successfully,
// pPop is a pop sequence corresponding to pPush
if(stackData.empty() && pNextPop - pPop == nLength)
bPossible = true;
}
return bPossible;
}
题目6:给定一个大小为 n 的数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。
说明: 要求算法的时间复杂度为 O (n),空间复杂度为 O (1)。 示例 1: 输入: [3,2,3] 输出: [3] 示例 2: 输入: [1,1,1,3,3,2,2,2] 输出: [1,2]摩尔投票法的基本思想很简单,在每一轮投票过程中,从数组中找出一对不同的元素,将其从数组中删除。这样不断的删除直到无法再进行投票,如果数组为空,则没有任何元素出现的次数超过该数组长度的一半。如果只存在一种元素,那么这个元素则可能为目标元素。 由于数组中出现次数超过 13 的数字最多只可能为两个,所以记录两个数字 n1、n2,以及他们出现的次数 c1、c2,遍历数组并做以下操作: 若当前两数字出现则把对应的次数加 1; 若其中一个出现次数为 0,则把当前数字赋给出现次数为 0 的数字,并将其出现次数置为 1; 若当前数字不同于任何一个数字,则将两数字的出现次数都减 1 最后得到两个数字以及他们出现的次数,再遍历一遍数组记录他们的出现次数,若大于 n3 则加入到结果中。
1 import java.util.ArrayList;
2 import java.util.List;
3
4 class Solution {
5 public List majorityElement(int[] nums) {
6 List res=new ArrayList();
7 if(nums==null||nums.length==0) return res;
8 int n1=nums[0],n2=0,c1=1,c2=0;
9 for(int i=1;i
10 if(nums[i]==n1) c1++;
11 else if(nums[i]==n2) c2++;
12 else if(c1==0){
13 n1=nums[i];
14 c1++;
15 }else if(c2==0){
16 n2=nums[i];
17 c2++;
18 }else{
19 c1--;
20 c2--;
21 }
22 }
23 c1=c2=0;
24 for(int i=0;i
25 if(nums[i]==n1) c1++;
26 else if(nums[i]==n2) c2++;
27 }
28 if(c1>nums.length/3) res.add(n1);
29 if(c2>nums.length/3) res.add(n2);
30 return res;
31 }
32 }
题目7:小易有一个长度为 n 的整数序列,a_1,...,a_n。然后考虑在一个空序列 b 上进行 n 次以下操作:
1、将 a_i 放入 b 序列的末尾
2、逆置 b 序列
小易需要你计算输出操作 n 次之后的 b 序列。
输入描述:
输入包括两行,第一行包括一个整数n(2 ≤ n ≤ 2*10^5),即序列的长度。
第二行包括n个整数a_i(1 ≤ a_i ≤ 10^9),即序列a中的每个整数,以空格分割。
输出描述:
在一行中输出操作n次之后的b序列,以空格分割,行末无空格。
输入例子 1:
4
1 2 3 4
输出例子 1:
4 2 1 3
import java.util.Scanner;
public class Main1 {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int size = cin.nextInt();
int[] nums = new int[size];
for (int i = 0; i < size; i++) {
nums[i] = cin.nextInt();
}
get2(nums);
}
public static void get2(int[] nums) {
int n = nums.length;
//便于测试,由于空格不可见,所以调试时候可以使用*替代空格
String space =" ";
if (n % 2 == 0) {
for (int i = n - 1; i > 0; i = i - 2) {
System.out.print(nums[i] + space);
}
// 1 2 3 4 5
for (int i = 0; i < n; i = i + 2) {
System.out.print(nums[i]);
if (i != n - 2) {
System.out.print(space);
}
}
} else {
for (int i = n - 1; i >= 0; i = i - 2) {
System.out.print(nums[i] + space);
}
// 1 2 3 4 5
for (int i = 1; i < n; i = i + 2) {
System.out.print(nums[i]);
if (i != n - 2) {
System.out.print(space);
}
}
}
}
}
题目8:牛牛和 15 个朋友玩打土豪分田地的游戏,牛牛决定让你来分田地,地主的田地可以看成是一个矩形,每个位置有一个价值。分割田地的方法是横竖各切三刀,分成 16 份,作为领导干部,牛牛总是会选择其中总价值最小的一份田地,作为牛牛最好的朋友,你希望牛牛取得的田地的价值和尽可能大,你知道这个值最大可以是多少吗?
输入描述:
每个输入包含 1 个测试用例。每个测试用例的第一行包含两个整数 n 和 m (1 <= n,m <= 75),表示田地的大小,接下来的 n 行,每行包含 m 个 0-9 之间的数字,表示每块位置的价值。
输出描述:
输出一行表示牛牛所能取得的最大的价值。
输入例子:
4 4
3 3 3 2
3 2 3 3
3 3 3 2
2 3 2 3
输出例子
2
#include
#include
#include
#include
#include
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
const int N = 10010;
char str[100];
int a[110][110];
int sum[110][110], n, m;
int calc(int x, int y, int i, int j){
return sum[x][y] - sum[x][j] - sum[i][y] + sum[i][j];
}
bool judge(int x){
for (int i = 1; i <= m - 3; i++)
{
for (int j = i + 1; j <= m - 2; j++)
{
for (int k = j + 1; k <= m - 1; k++)
{
int last = 0, cnt = 0;
for (int r = 1; r <= n; r++){
int s1 = calc(r, i, last, 0);
int s2 = calc(r, j, last, i);
int s3 = calc(r, k, last, j);
int s4 = calc(r, m, last, k);
if (s1 >= x && s2 >= x && s3 >= x && s4 >= x){
last = r; cnt++;
}
printf("i = %d j = %d k = %d last = %d\n",i, j, k, last);
}
if (cnt >= 4)return true;
}
}
}
return false;
}
int main(){
while (scanf("%d%d", &n, &m) > 0){
for (int i = 1; i <= n; i++){
scanf("%s", str + 1);
for (int j = 1; j <= m; j++){
a[i][j] = str[j] - '0';//这样输入连续的数字到数组,先输入到字符串
}
}
for (int i = 0; i <= n; i++){
for (int j = 0; j <= m; j++){
cout << a[i][j] << " ";
}
cout << endl;
}
cout << endl;
memset(sum, 0, sizeof sum);
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m; j++){
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j];
}
}
for (int i = 0; i <= n; i++){
for (int j = 0; j <= m; j++){
cout << sum[i][j] << " ";
}
cout << endl;
}
int l = 0, r = sum[n][m], ans = 0;
while (l <= r){
int m = (l + r) >> 1;
if (judge(m)){
l = m + 1;
ans = m;
}
else r = m - 1;
}
printf("%d\n", ans);
}
}
★星标
我们,不错过与你相关的每条消息
计算机视觉常见面试题型介绍及解答
第一期 | 第二期 | 第三期 | 第四期 | 第五期 |
第六期 | 第七期 | 第八期 | 第九期 | 第十期 | 第11期
腾讯算法工程师笔试真题介绍及解析汇总合集
第一期 | 第二期 | 第三期 | 第四期 | 第五期
阿里算法岗位最新编程题介绍及解析
第一期 | 第二期 | 第三期 | 第四期 | 第五期
第六期 | 第七期
华为研发工程师编程题型介绍及解析
第一期 | 第二期 | 第三期 | 第四期 | 第五期 |
第六期 | 第七期 | 第八期 | 第九期 | 第十期 |
字节跳动校招研发岗位笔试编程题型介绍及解析
第一期 | 第二期 | 第三期 | 第四期 | 第五期
第六期 | 第七期 | 第八期 | 第九期 | 第十期
网易算法工程师笔试编程题型介绍及解析
第一期