本题解只是参考答案,思路并不唯一!!!

A题 存款利息

方法一

本题主要考察循环语句,题目较为简单,直接看代码

C语言


#include <stdio.h>
int main()
{double money_1,money_2;scanf("%lf", &money_1);money_2 = money_1;money_1 += money_1 * 4 * 0.0275; //存四年,复利计息for (int i = 0; i < 4; ++i){money_2 += money_2 * 0.0175; //加上一年的利息,单利计息}printf("%.2lf %.2lf", money_1,money_2);return 0;
}

B题 判断闰年

方法一

本题主要考察if判断,要掌握闰年的条件。
闰年条件:

  1. 能被4整除但不能被100整除
  2. 能被400整除

C语言

#include <stdio.h>
int main()
{int year, mon, day;scanf("%d-%d-%d", &year, &mon, &day);if(year % 400 == 0 || year % 4 == 0 && year % 100 != 0) //闰年条件{printf("%s", "yes");}else{printf("%s", "no");}return 0;
}

C题 acb模式

题目来源:132-pattern

前言

由于本题中 nnn 的最大值可以到 10410^4104
,因此对于一个满足 acbacbacb 模式的三元组下标 (i,j,k)(i, j, k)(i,j,k),枚举其中的 2 个下标时间复杂度为 O(n2)O(n^2)O(n2)
,很容易超出时间限制。

因此我们可以考虑枚举其中的 111 个下标,并使用合适的数据结构维护另外的 222 个下标的可能值。

方法一 枚举 c

枚举 ccc 是容易想到并且也是最容易实现的。由于 ccc 是模式中的最大值,并且其出现在 aaa 和 bbb 的中间,因此我们只需要从左到右枚举 ccc 的下标 jjj,那么:

由于 aaa 是模式中的最小值,因此我们在枚举 jjj 的同时,维护数组 a 中左侧元素 a[0..j−1]a[0..j-1]a[0..j−1] 的最小值,即为 aaa 对应的元素 a[i]a[i]a[i]。需要注意的是,只有 a[i]<a[j]a[i] < a[j]a[i]<a[j] 时,a[i]a[i]a[i] 才能作为 a 对应的元素;

由于 bbb 是模式中的次小值,因此我们可以使用一个有序集合(例如平衡树)维护数组 aaa 中右侧元素 a[j+1..n−1]a[j+1..n-1]a[j+1..n−1] 中的所有值。当我们确定了 a[i]a[i]a[i] 和 a[j]a[j]a[j] 之后,只需要在有序集合中查询严格比 a[i]a[i]a[i] 大的那个最小的元素,即为 a[k]a[k]a[k]。需要注意的是,只有 $a[k] < a[j] 时,时,时,a[k]$ 才能作为 ccc 对应的元素。

C++

#include<iostream>
#include <set>
#include <vector>
using namespace std;
class Solution {public:bool find132pattern(vector<int>& nums) {int n = nums.size();if (n < 3) {return false;}// 左侧最小值int left_min = nums[0];// 右侧所有元素multiset<int> right_all;for (int k = 2; k < n; ++k) {right_all.insert(nums[k]);}for (int j = 1; j < n - 1; ++j) {if (left_min < nums[j]) {auto it = right_all.upper_bound(left_min);if (it != right_all.end() && *it < nums[j]) {return true;}}left_min = min(left_min, nums[j]);right_all.erase(right_all.find(nums[j + 1]));}return false;}
};
int main()
{Solution sol;int n;cin >> n;vector<int> array(n);for (int i = 0; i < n; ++i){cin >> array[i];}bool res = sol.find132pattern(array);if(res){cout << "True";}else{cout << "False";}return 0;
}

Java

import java.io.*;
import java.util.*;
import java.util.TreeMap;
class Solution {public boolean find132pattern(int[] nums) {// a < c < bint n = nums.length;if (n < 3) return false;TreeMap<Integer, Integer> rightNums = new TreeMap<>();//储存当前位置右边的 <数值,个数> cint leftMin = nums[0]; // 左侧最小值 afor (int i = 2; i < n; i++) {rightNums.put(nums[i], rightNums.getOrDefault(nums[i], 0) + 1);}for (int i = 1; i < n - 1; i++) {//检查if (leftMin < nums[i]) { // a<bInteger c = rightNums.ceilingKey(leftMin + 1); //获得比a大的最小元素 c>=a+1if (c != null && c < nums[i]) { //c<breturn true; //符合情况}}//维护结构rightNums.put(nums[i + 1], rightNums.get(nums[i + 1]) - 1);if (rightNums.get(nums[i + 1]) == 0) rightNums.remove(nums[i + 1]);leftMin = Math.min(leftMin, nums[i]);}return false;}
}
public class Main {public static void main(String args[]) throws Exception {Scanner cin=new Scanner(System.in);int n = cin.nextInt();int[] arr = new int[n];for(int i =0;i<n;++i){arr[i]=cin.nextInt();}Solution sol = new Solution();if(sol.find132pattern(arr)){System.out.print("True");}else{System.out.print("False");}}
}

方法二 枚举a

如果我们从左到右枚举 aaa 的下标 iii,那么 j,kj, kj,k 的下标范围都是减少的,这样就不利于对它们进行维护。因此我们可以考虑从右到左枚举 iii。

那么我们应该如何维护 j,kj, kj,k 呢?在 acbacbacb 模式中,如果 a<ba<ba<b 并且 b<cb<cb<c,那么根据传递性,a<ca<ca<c 也是成立的,那么我们可以使用下面的方法进行维护:

  • 我们使用一种数据结构维护所有遍历过的元素,它们作为 bbb 的候选元素。每当我们遍历到一个新的元素时,就将其加入数据结构中;

  • 在遍历到一个新的元素的同时,我们可以考虑其是否可以作为 ccc。如果它作为 ccc,那么数据结构中所有严格小于它的元素都可以作为 bbb,我们将这些元素全部从数据结构中移除,并且使用一个变量维护所有被移除的元素的最大值。这些被移除的元素都是可以真正作为 bbb 的,并且元素的值越大,那么我们之后找到 aaa 的机会也就越大。

那么这个「数据结构」是什么样的数据结构呢?我们尝试提取出它进行的操作:

  • 它需要支持添加一个元素;

  • 它需要支持移除所有严格小于给定阈值的所有元素;

  • 上面两步操作是「依次进行」的,即我们先用给定的阈值移除元素,再将该阈值加入数据结构中。

这就是「单调栈」。在单调栈中,从栈底到栈顶的元素是严格单调递减的。当给定阈值 xxx 时,我们只需要不断地弹出栈顶的元素,直到栈为空或者 xxx 严格小于栈顶元素。此时我们再将 xxx 入栈,这样就维护了栈的单调性。

因此,我们可以使用单调栈作为维护 bbb 的数据结构,并给出下面的算法:

  • 我们用单调栈维护所有可以作为 bbb 的候选元素。初始时,单调栈中只有唯一的元素 a[n−1]\textit{a}[n-1]a[n−1]。我们还需要使用一个变量 max_k\textit{max\_k}max_k 记录所有可以真正作为 bbb 的元素的最大值;

  • 随后我们从 n−2n-2n−2 开始从右到左枚举元素 a[i]a[i]a[i]:

    • 首先我们判断 a[i]a[i]a[i] 是否可以作为 aaa。如果 a[i]<max_ka[i] < \textit{max\_k}a[i]<max_k,那么它就可以作为 aaa,我们就找到了一组满足 acbacbacb 模式的三元组;

    • 随后我们判断 a[i]a[i]a[i] 是否可以作为 ccc,以此找出哪些可以真正作为 bbb 的元素。我们将 a[i]a[i]a[i] 不断地与单调栈栈顶的元素进行比较,如果 a[i]a[i]a[i] 较大,那么栈顶元素可以真正作为 bbb,将其弹出并更新 max_k\textit{max\_k}max_k;

    • 最后我们将 a[i]a[i]a[i] 作为 bbb 的候选元素放入单调栈中。这里可以进行一个优化,即如果 a[i]≤max_ka[i] \leq \textit{max\_k}a[i]≤max_k,那么我们也没有必要将 a[i]a[i]a[i] 放入栈中,因为即使它在未来被弹出,也不会将 max_k\textit{max\_k}max_k 更新为更大的值。

  • 在枚举完所有的元素后,如果仍未找到满足 acb 模式的三元组,那就说明其不存在。

C语言

#include<stdio.h>
#define bool int
#define false 0
#define true 1
bool find132pattern(int* nums, int numsSize) {int n = numsSize;int candidate_k[n], top = 0;candidate_k[top++] = nums[n - 1];int max_k = INT_MIN;for (int i = n - 2; i >= 0; --i) {if (nums[i] < max_k) {return true;}while (top && nums[i] > candidate_k[top - 1]) {max_k = candidate_k[--top];}if (nums[i] > max_k) {candidate_k[top++] = nums[i];}}return false;
}
int main()
{int n;scanf("%d",&n);int array[10000000];for(int i=0; i<n; ++i){scanf("%d",array+i);}bool ans = find132pattern(array,n);if(ans) printf("True");else printf("False");return 0;
}

C++

#include<vector>
#include<iostream>
class Solution {public:bool find132pattern(vector<int>& nums) {int n = nums.size();stack<int> candidate_k;candidate_k.push(nums[n - 1]);int max_k = INT_MIN;for (int i = n - 2; i >= 0; --i) {if (nums[i] < max_k) {return true;}while (!candidate_k.empty() && nums[i] > candidate_k.top()) {max_k = candidate_k.top();candidate_k.pop();}if (nums[i] > max_k) {candidate_k.push(nums[i]);}}return false;}
};
int main()
{Solution sol;int n;cin >> n;vector<int> array(n);for (int i = 0; i < n; ++i){cin >> array[i];}bool res = sol.find132pattern(array);if(res){cout << "True";}else{cout << "False";}return 0;
}

Java

import java.io.*;
import java.util.*;
import java.util.TreeMap;
class Solution {public boolean find132pattern(int[] nums) {int n = nums.length;Deque<Integer> candidateK = new LinkedList<Integer>();candidateK.push(nums[n - 1]);int maxK = Integer.MIN_VALUE;for (int i = n - 2; i >= 0; --i) {if (nums[i] < maxK) {return true;}while (!candidateK.isEmpty() && nums[i] > candidateK.peek()) {maxK = candidateK.pop();}if (nums[i] > maxK) {candidateK.push(nums[i]);}}return false;}
}
public class Main {public static void main(String args[]) throws Exception {Scanner cin=new Scanner(System.in);int n = cin.nextInt();int[] arr = new int[n];for(int i =0;i<n;++i){arr[i]=cin.nextInt();}Solution sol = new Solution();if(sol.find132pattern(arr)){System.out.print("True");}else{System.out.print("False");}}
}

D题 方形星系

题目来源:spiral-matrix-ii

方法一:模拟

模拟矩阵的生成。按照要求,初始位置设为矩阵的左上角,初始方向设为向右。若下一步的位置超出矩阵边界,或者是之前访问过的位置,则顺时针旋转,进入下一个方向。如此反复直至填入 n2n^2n2
个元素。

记 matrix\textit{matrix}matrix 为生成的矩阵,其初始元素设为 000。由于填入的元素均为正数,我们可以判断当前位置的元素值,若不为 000,则说明已经访问过此位置。

C语言

#include<stdio.h>
int** generateMatrix(int n, int* returnSize, int** returnColumnSizes) {int maxNum = n * n;int curNum = 1;int** matrix = malloc(sizeof(int*) * n);*returnSize = n;*returnColumnSizes = malloc(sizeof(int) * n);for (int i = 0; i < n; i++) {matrix[i] = malloc(sizeof(int) * n);memset(matrix[i], 0, sizeof(int) * n);(*returnColumnSizes)[i] = n;}int row = 0, column = 0;int directions[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};  // 右下左上int directionIndex = 0;while (curNum <= maxNum) {matrix[row][column] = curNum;curNum++;int nextRow = row + directions[directionIndex][0], nextColumn = column + directions[directionIndex][1];if (nextRow < 0 || nextRow >= n || nextColumn < 0 || nextColumn >= n || matrix[nextRow][nextColumn] != 0) {directionIndex = (directionIndex + 1) % 4;  // 顺时针旋转至下一个方向}row = row + directions[directionIndex][0];column = column + directions[directionIndex][1];}return matrix;
}
int main(){int n;scanf("%d",&n);int size,columnSizes;int** matrix = generateMatrix(m,&size,&columnSizes);for(int i=0;i<size;++i){for(int j=0;j<columnSizes;++j){if(j>0) printf(" ");printf("%d",matrix[i][j]);}printf("\n");}return 0;
}

C++

#include<vector>
#include<iostream>
using namespace std;
class Solution {public:vector<vector<int>> generateMatrix(int n) {int maxNum = n * n;int curNum = 1;vector<vector<int>> matrix(n, vector<int>(n));int row = 0, column = 0;vector<vector<int>> directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};  // 右下左上int directionIndex = 0;while (curNum <= maxNum) {matrix[row][column] = curNum;curNum++;int nextRow = row + directions[directionIndex][0], nextColumn = column + directions[directionIndex][1];if (nextRow < 0 || nextRow >= n || nextColumn < 0 || nextColumn >= n || matrix[nextRow][nextColumn] != 0) {directionIndex = (directionIndex + 1) % 4;  // 顺时针旋转至下一个方向}row = row + directions[directionIndex][0];column = column + directions[directionIndex][1];}return matrix;}
};
int main()
{int n;cin>>n;Solution sol;vector<vector<int>> matrix = sol.generateMatrix(n);for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if(j>0) cout<<" ";cout<<matrix[i][j];}cout<<endl;}return 0;
}

Java

import java.util.Scanner;
class Solution {public int[][] generateMatrix(int n) {int[][] matrix = new int[n][n];int index = 1;int row = 0, col = 0;final int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};int directionIndex = 0;while (index <= n * n) {matrix[row][col] = index;int newRow = row + directions[directionIndex][0];int newCol = col + directions[directionIndex][1];if (newRow < 0 || newRow >= n || newCol < 0 || newCol >= n || matrix[newRow][newCol] != 0) {++directionIndex;directionIndex %= 4;}row += directions[directionIndex][0];col += directions[directionIndex][1];++index;}return matrix;}
}
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);Solution solution = new Solution();int n = in.nextInt();int[][] matrix = solution.generateMatrix(n);for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if(j>0) System.out.print(" ");System.out.print(matrix[i][j]);}System.out.print("\n");}}
}

方法二:按层模拟

可以将矩阵看成若干层,首先填入矩阵最外层的元素,其次填入矩阵次外层的元素,直到填入矩阵最内层的元素。

定义矩阵的第 kk 层是到最近边界距离为 kk 的所有顶点。例如,下图矩阵最外层元素都是第 11 层,次外层元素都是第 22 层,最内层元素都是第 33 层。

[[1, 1, 1, 1, 1, 1],
[1, 2, 2, 2, 2, 1],
[1, 2, 3, 3, 2, 1],
[1, 2, 3, 3, 2, 1],
[1, 2, 2, 2, 2, 1],
[1, 1, 1, 1, 1, 1]]
对于每层,从左上方开始以顺时针的顺序填入所有元素。假设当前层的左上角位于 (top,left)(\textit{top}, \textit{left})(top,left),右下角位于 (bottom,right)(\textit{bottom}, \textit{right})(bottom,right),按照如下顺序填入当前层的元素。

从左到右填入上侧元素,依次为 (top,left)(\textit{top}, \textit{left})(top,left) 到 (top,right)(\textit{top}, \textit{right})(top,right)。

从上到下填入右侧元素,依次为 (top+1,right)(\textit{top} + 1, \textit{right})(top+1,right) 到 (bottom,right)(\textit{bottom}, \textit{right})(bottom,right)。

如果 left<right\textit{left} < \textit{right}left<right 且 top<bottom\textit{top} < \textit{bottom}top<bottom,则从右到左填入下侧元素,依次为 (bottom,right−1)(\textit{bottom}, \textit{right} - 1)(bottom,right−1) 到 (bottom,left+1)(\textit{bottom}, \textit{left} + 1)(bottom,left+1),以及从下到上填入左侧元素,依次为 (bottom,left)(\textit{bottom}, \textit{left})(bottom,left) 到 (top+1,left)(\textit{top} + 1, \textit{left})(top+1,left)。

填完当前层的元素之后,将 left\textit{left}left 和 top\textit{top}top 分别增加 111,将 right\textit{right}right 和 bottom\textit{bottom}bottom 分别减少 111,进入下一层继续填入元素,直到填完所有元素为止。

C语言

#include<stdio.h>
int** generateMatrix(int n, int* returnSize, int** returnColumnSizes) {int num = 1;int** matrix = malloc(sizeof(int*) * n);*returnSize = n;*returnColumnSizes = malloc(sizeof(int) * n);for (int i = 0; i < n; i++) {matrix[i] = malloc(sizeof(int) * n);memset(matrix[i], 0, sizeof(int) * n);(*returnColumnSizes)[i] = n;}int left = 0, right = n - 1, top = 0, bottom = n - 1;while (left <= right && top <= bottom) {for (int column = left; column <= right; column++) {matrix[top][column] = num;num++;}for (int row = top + 1; row <= bottom; row++) {matrix[row][right] = num;num++;}if (left < right && top < bottom) {for (int column = right - 1; column > left; column--) {matrix[bottom][column] = num;num++;}for (int row = bottom; row > top; row--) {matrix[row][left] = num;num++;}}left++;right--;top++;bottom--;}return matrix;
}
int main(){int n;scanf("%d",&n);int size,columnSizes;int** matrix = generateMatrix(m,&size,&columnSizes);for(int i=0;i<size;++i){for(int j=0;j<columnSizes;++j){if(j>0) printf(" ");printf("%d",matrix[i][j]);}printf("\n");}return 0;
}

C++

#include<vector>
#include<iostream>
using namespace std;
class Solution {public:vector<vector<int>> generateMatrix(int n) {int num = 1;vector<vector<int>> matrix(n, vector<int>(n));int left = 0, right = n - 1, top = 0, bottom = n - 1;while (left <= right && top <= bottom) {for (int column = left; column <= right; column++) {matrix[top][column] = num;num++;}for (int row = top + 1; row <= bottom; row++) {matrix[row][right] = num;num++;}if (left < right && top < bottom) {for (int column = right - 1; column > left; column--) {matrix[bottom][column] = num;num++;}for (int row = bottom; row > top; row--) {matrix[row][left] = num;num++;}}left++;right--;top++;bottom--;}return matrix;}
};
int main()
{int n;cin>>n;Solution sol;vector<vector<int>> matrix = sol.generateMatrix(n);for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if(j>0) cout<<" ";cout<<matrix[i][j];}cout<<endl;}return 0;
}

Java

import java.util.Scanner;
class Solution {public int[][] generateMatrix(int n) {int num = 1;int[][] matrix = new int[n][n];int left = 0, right = n - 1, top = 0, bottom = n - 1;while (left <= right && top <= bottom) {for (int column = left; column <= right; column++) {matrix[top][column] = num;num++;}for (int row = top + 1; row <= bottom; row++) {matrix[row][right] = num;num++;}if (left < right && top < bottom) {for (int column = right - 1; column > left; column--) {matrix[bottom][column] = num;num++;}for (int row = bottom; row > top; row--) {matrix[row][left] = num;num++;}}left++;right--;top++;bottom--;}return matrix;}
}
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);Solution solution = new Solution();int n = in.nextInt();int[][] matrix = solution.generateMatrix(n);for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if(j>0) System.out.print(" ");System.out.print(matrix[i][j]);}System.out.print("\n");}}
}

E题 乾坤挪移

方法一 假装移动数组

每次输出数组时,都从第 iii 位输出,需要输出 nnn 个元素,可以利用取模运算符获得正确的下标

C语言

#include <stdio.h>
#include <malloc.h>
int main()
{int n;scanf("%d", &n);int* array = (int*)malloc(sizeof(int) * n); //动态创建一个n个元素的数组for (int i = 0; i < n; ++i){scanf("%d", array + i);}for (int i = 0; i < n; ++i){for (int j = i; j < i+n; ++j){if (j > i) printf(" ");printf("%d", array[j % n]);}printf("\n");}free(array); //释放arrayarray = NULL;return 0;
}

C++

#include <iostream>
#include <vector>
using namespace std;int main()
{int n;cin >> n;vector<int> array(n);for (int i = 0; i < n; ++i){cin >> array[i];}for (int i = 0; i < n; ++i){for (int j = i; j < i+n; ++j){if (j > i) cout << " ";cout << array[j % n];}cout << endl;}return 0;
}

Java

import java.util.Scanner;
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n;n = in.nextInt();int[] array = new int[n];for (int i = 0; i < n; i++) {array[i] = in.nextInt();}for (int i = 0; i < n; i++) {for (int j = i; j < i + n; j++) {if (j > i) System.out.print(" ");System.out.print(array[j % n]);}System.out.print("\n");}}
}

F题 下一个更小元素

题目来源:next-greater-element-ii

方法一:单调栈 + 循环数组

我们可以使用单调栈解决本题。单调栈中保存的是下标,从栈底到栈顶的下标在数组 nums\textit{nums}nums 中对应的值是单调不升的。

每次我们移动到数组中的一个新的位置 iii,我们就将当前单调栈中所有对应值小于 nums[i]\textit{nums}[i]nums[i] 的下标弹出单调栈,这些值的下一个更大元素即为 nums[i]\textit{nums}[i]nums[i](证明很简单:如果有更靠前的更大元素,那么这些位置将被提前弹出栈)。随后我们将位置 iii 入栈。

但是注意到只遍历一次序列是不够的,例如序列 [2,3,1][2,3,1][2,3,1],最后单调栈中将剩余 [3,1][3,1][3,1],其中元素 [1][1][1] 的下一个更大元素还是不知道的。

一个朴素的思想是,我们可以把这个循环数组「拉直」,即复制该序列的前 n−1n-1n−1 个元素拼接在原序列的后面。这样我们就可以将这个新序列当作普通序列,用上文的方法来处理。

而在本题中,我们不需要显性地将该循环数组「拉直」,而只需要在处理时对下标取模即可。

C语言

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int* nextGreaterElements(int* nums, int numsSize, int* returnSize) {*returnSize = numsSize;if (numsSize == 0) {return NULL;}int* ret = malloc(sizeof(int) * numsSize);memset(ret, -1, sizeof(int) * numsSize);int stk[numsSize * 2 - 1], top = 0;for (int i = 0; i < numsSize * 2 - 1; i++) {while (top > 0 && nums[stk[top - 1]] > nums[i % numsSize]) {ret[stk[top - 1]] = nums[i % numsSize];top--;}stk[top++] = i % numsSize;}return ret;
}
int main()
{int n;scanf("%d", &n);int* array = malloc(sizeof(int) * n);for (int i = 0; i < n; ++i){scanf("%d", array+i);}int len;int* ans = nextGreaterElements(array, n, &len);for (int i = 0; i < n; ++i){if (i > 0) printf(" ");printf("%d", ans[i]);}return 0;
}

C++

#include <iostream>
#include <vector>
#include <stack>
using namespace std;
class Solution {public:vector<int> nextGreaterElements(vector<int>& nums) {int n = nums.size();vector<int> ret(n, -1);stack<int> stk;for (int i = 0; i < n * 2 - 1; i++) {while (!stk.empty() && nums[stk.top()] > nums[i % n]) {ret[stk.top()] = nums[i % n];stk.pop();}stk.push(i % n);}return ret;}
};
int main()
{int n;cin >> n;Solution sol;vector<int> array(n);for (int i = 0; i < n; ++i){cin >> array[i];}auto ans = sol.nextGreaterElements(array);for (int i = 0; i < ans.size(); ++i){if (i > 0) cout << " ";cout << ans[i];}return 0;
}

Java

import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;class Solution {public int[] nextGreaterElements(int[] nums) {int n = nums.length;int[] ret = new int[n];Arrays.fill(ret, -1);Deque<Integer> stack = new LinkedList<Integer>();for (int i = 0; i < n * 2 - 1; i++) {while (!stack.isEmpty() && nums[stack.peek()] > nums[i % n]) {ret[stack.pop()] = nums[i % n];}stack.push(i % n);}return ret;}
}
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n = in.nextInt();int[] array = new int[n];for (int i = 0; i < n; i++) {array[i] = in.nextInt();}Solution sol = new Solution();int[] ans = sol.nextGreaterElements(array);for (int i = 0; i < n; i++) {if (i > 0) System.out.print(" ");System.out.print(array[i]);}}
}

G题 求解高次方程

方法一:二分查找

通过求导可得该函数在 [20,50][20,50][20,50] 上是单调递增函数,则设f(x0)=0f(x_0)=0f(x0​)=0,有x<x0,f(x)<f(x0)x<x_0, f(x)<f(x_0)x<x0​,f(x)<f(x0​)或x>x0,f(x)>f(x0)x>x_0, f(x)>f(x_0)x>x0​,f(x)>f(x0​),函数图像如图

可得在这一区间内,函数值是从小到大有序的,可以使用二分查找找到特定值

C

#include <stdio.h>
#include <math.h>inline double f(const double x)
{// f(x)=x^4+70*x^3-4175*x^2+15750*x-275625;return pow(x, 4) + 70 * pow(x, 3) - 4175 * pow(x, 2) + 15750 * x - 275625;
}
double binarySearch(double left, double right)
{int i = 1;const double delta = 0.000000000001;double mid;while (left < right){mid = (left + right) / 2;double val = f(mid);//cout <<i <<" "<< "f(" << mid << ")= " << val << endl;if (-delta <= val && val <= delta){return mid;}else if (val < -delta){left = mid + delta;}else{right = mid - delta;}++i;}return mid;
}int main()
{double ans = binarySearch(20.0, 50.0);printf("%.6lf", ans);return 0;
}

C++

#include <iostream>
#include <math.h>
#include <iomanip>
using namespace std;
inline double f(double x){// f(x)=x^4+70*x^3-4175*x^2+15750*x-275625;return pow(x, 4) + 70 * pow(x, 3) - 4175 * pow(x, 2) + 15750 * x - 275625;
}
double binarySearch(double left, double right){int i = 1;double delta = 0.000000000001;double mid;while (left<right){mid = (left + right) / 2;double val = f(mid);//cout <<i <<" "<< "f(" << mid << ")= " << val << endl;if(-delta <= val && val <= delta){return mid;}else if(val<-delta){left = mid + delta;}else{right = mid - delta;}++i;}return mid;
}
int main(){double ans = binarySearch(20.0, 50.0);//格式控制 fixed 小数表示,setprecision(n)保留n位小数cout << setiosflags(ios::fixed) << setprecision(6) << ans;return 0;
}

H题 存在重复元素

题目来源:contains-duplicate

方法一:排序

在对数字从小到大排序之后,数组的重复元素一定出现在相邻位置中。因此,我们可以扫描已排序的数组,每次判断相邻的两个元素是否相等,如果相等则说明存在重复的元素。
但是时间复杂度为nlog⁡(n)n\log(n)nlog(n),会超时。

C

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define scanf scanf_s
int cmp(const void* _a, const void* _b) {int a = *(int*)_a, b = *(int*)_b;return a - b;
}
bool containsDuplicate(int* nums, int numsSize) {qsort(nums, numsSize, sizeof(int), cmp);for (int i = 0; i < numsSize - 1; i++) {if (nums[i] == nums[i + 1]) {return true;}}return false;
}
int main()
{int n;scanf("%d", &n);int* array = malloc(sizeof(int) * n);for (int i = 0; i < n; ++i){scanf("%d", array + i);}if (containsDuplicate(array, n))printf("true");elseprintf("false");free(array);return 0;
}

C++

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Solution {public:bool containsDuplicate(vector<int>& nums) {sort(nums.begin(), nums.end());int n = nums.size();for (int i = 0; i < n - 1; i++) {if (nums[i] == nums[i + 1]) {return true;}}return false;}
};
int main()
{int n;cin >> n;vector<int> array(n);for (int i = 0; i < n; ++i){cin >> array[i];}Solution sol;if (sol.containsDuplicate(array)) cout << "true";else cout << "false";return 0;
}

Java

import java.util.Arrays;
import java.util.Scanner;class Solution {public boolean containsDuplicate(int[] nums) {Arrays.sort(nums);int n = nums.length;for (int i = 0; i < n - 1; i++) {if (nums[i] == nums[i + 1]) {return true;}}return false;}
}
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n = in.nextInt();int[] array = new int[n];for (int i = 0; i < n; i++) {array[i] = in.nextInt();}Solution sol = new Solution();if(sol.containsDuplicate(array)) System.out.print("true");else System.out.print("false");}
}

方法二:哈希表

对于数组中每个元素,我们将它插入到哈希表中。如果插入一个元素时发现该元素已经存在于哈希表中,则说明存在重复的元素。

C++

#include<iostream>
#include<vector>
#include<set>
#include<unordered_set>
using namespace std;
class Solution {public:bool containsDuplicate(vector<int>& nums) {//使用stl的setunordered_set<int> hash;for (auto& elem : nums){auto res = hash.insert(elem);if (!res.second) return true;}return false;}
};int main() {int n;cin >> n;vector<int> vect(n);for (int i = 0; i < n; ++i) {scanf("%d", &vect[i]);//cin >> vect[i];}Solution sol;if (sol.containsDuplicate(vect)) {cout << "true";}else {cout << "false";}return 0;
}

Java

import java.util.*;
class Solution {public boolean containsDuplicate(int[] nums) {Set<Integer> set = new HashSet<Integer>();for (int x : nums) {if (!set.add(x)) {return true;}}return false;}
}
public class Main{public static void main(String[] args){Scanner in = new Scanner(System.in);int n = in.nextInt();int[] array = new int[n];for(int i=0;i<n;++i){array[i]=in.nextInt();}Solution sol = new Solution();if(sol.containsDuplicate(array)) System.out.print("true");else System.out.print("false");}
}

2021财院ACM选拔赛题解相关推荐

  1. 北京信息科技大学第十三届程序设计竞赛暨ACM选拔赛题解

    北京信息科技大学第十三届程序设计竞赛暨ACM选拔赛题解 A lzh的蹦床 B 所谓过河 C 旅行家问题1 D 旅行家问题2 E 小菲和Fib数列 F 好玩的音乐游戏 G ranko的手表 H 字母收集 ...

  2. 江西理工大学南昌校区acm选拔赛题解

    第一题略 第二题 #include<stdio.h> int main() {int a1,a2,a3,b1,b3,b2,c1,c2,c3,n,sum,d1,d2,d3,i;scanf(& ...

  3. 北京信息科技大学第十二届程序设计竞赛暨ACM选拔赛题解

    A 爱丽丝的人偶(一) 链接:https://ac.nowcoder.com/acm/contest/8755/A 题目描述 爱丽丝有个人偶,每个人偶的身高依次是 现在她要将这个人偶摆成一排. 但是人 ...

  4. 2018年北京信息科技大学第十届程序设计竞赛暨ACM选拔赛题解

    链接:https://www.nowcoder.com/acm/contest/118/A 来源:牛客网 PUBG 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语 ...

  5. python解acm题_2020年常熟理工学院第一届线上ACM选拔赛题解(Python版)

    这个题目是4140: Trojke的一个扩展,在这个题目里由于可以匹配的棋子很多,我们应该想的是去遍历这个棋盘的所有线.这就是格点问题:从(0,0)到(x,y)的线段,经过的格点数目是gcd(x,y) ...

  6. 北京信息科技大学第十三届程序设计竞赛暨ACM选拔赛(重现赛)题解

    题目链接: 北京信息科技大学第十三届程序设计竞赛暨ACM选拔赛(重现赛)_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ大学ACM校赛新生赛是面向ACM/ICPC/CCP ...

  7. 2021年ACM竞赛班训练(六)题解

    2021年ACM竞赛班训练(六)题解 ==Problem A 逆元== 题目描述 输入 输出 题目分析 代码 ==Problem B&C 五一假期前最后一题&女神的考验== 题目描述 ...

  8. 重庆师范大学第一届ACM选拔赛

    下面的题解不会给出题目所以在开头放出比赛链接传送门 本场比赛大部分都是模板题,但是任有记录的必要性 重庆师范大学第一届ACM选拔赛 不一样的食物链 有趣的求和 统计患病人数 皮皮想拜师 爱玩游戏的To ...

  9. 一个预告|恭喜斯科特·阿伦森获得2021年ACM计算奖

    国际计算机协会(ACM)4月15日宣布,斯科特·阿伦森因对量子计算的开创性贡献荣获2021年ACM计算奖. ACM计算奖用以表彰处于职业生涯中早期.其贡献具有根本且广泛的影响的计算机科学家.ACM主席 ...

最新文章

  1. R语言dataframe数据列中的缺失值NA的个数统计实战:特定数据列的NA值统计、所有特征的NA值统计
  2. jQuery扩展---$.extend和$.fn.extend
  3. Linux操作系统下/etc/hosts文件配置方法
  4. 嵌入式c语言为什么变量定义在前面,嵌入式C语言数据类型和变量详解
  5. vue 中的el表达式_Vue中vue.filter()的使用方法介绍(过滤)
  6. cordova自定义android插件,Cordova 自定义插件(Android版本)
  7. vue-resource全攻略
  8. c++中的new_怎么在java中创建一个自定义的collector
  9. java 百度账号注册界面_基于百度AI使用H5实现调用摄像头进行人脸注册、人脸搜索功能(Java)...
  10. 需求分析的初稿出来了
  11. 隐藏我的电脑中的多余图标
  12. linux识别设备插槽,你如何确定linux计算机的CPU插槽类型?
  13. 临渊慕鱼,不如退而结网!
  14. 边缘计算以及kubeedge概念的通俗解释
  15. CCF所有领域best paper合集!发顶会论文必看!中国计算机学会推荐会议的Best paper~
  16. LeetCode 739. 每日温度(java实现)
  17. 逻辑地址和物理地址的相互转换
  18. Shell按关键字删除重复行
  19. element-ui el-table 表格疯狂抖动
  20. Contour Integral

热门文章

  1. Android Studio修改工程项目编码,修正运行程序乱码问题
  2. 增量式编码器c语言,关于增量式编码器编程指导及使用方法的介绍
  3. w7电脑蓝屏怎么解决_电脑蓝屏怎么解决win7
  4. SQL小挑战——第3期(电影院选择连续座位)
  5. 光环:研发云搭建及人才梯队建设——姚冬
  6. LM2596开关电源 多路开关电源 DC-DC降压电源 固定/可调输出 原理图和PCB
  7. 青龙面板安装搭建详细教程
  8. maximo跟java_Maximo7.5远程调用maximo的手动输入节点工作流
  9. IT行业前景真的好吗_转IT学什么语言好?
  10. 用AI进行工业质检的方案详解!