文章目录
- IO优化
- [1. 点击消除(AB5)](#1. 点击消除(AB5))
- [2. 数组中两个字符串的最小距离](#2. 数组中两个字符串的最小距离)
- [3. dd爱框框](#3. dd爱框框)
- [4. 除2](#4. 除2)
- [5. 腐烂的苹果(NC398)](#5. 腐烂的苹果(NC398))
- [6. 大数乘法(NC 10)](#6. 大数乘法(NC 10))
IO优化
Scanner和System.out需要频繁刷新缓冲区,当数据量很大时,即使解题思路是对的,也可能导致超时。需要自定义快速读入。
java
import java.util.*;
import java.io.*;
public class Main {
public static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
public static Read in = new Read();
public static void main(String[] args) {
//code
out.close();
}
}
public class Read {
StringTokenizer st = new StringTokenizer("");
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String next() throws IOException {
while ((!st.hasMoreTokens())){
st = new StringTokenizer(bf.readLine());
}
return st.nextToken();
}
String nextLine() throws IOException {
return bf.readLine();
}
int nextInt() throws IOException {
return Integer.parseInt(next());
}
long nextLong() throws IOException {
return Long.parseLong(next());
}
double nextDouble() throws IOException{
return Double.parseDouble(next());
}
}
1. 点击消除(AB5)
题目描述

解题思路
如果利用栈来实现,需要先把所有字符出栈,再逆序,可以借助StringBuilder模拟栈结构,进行尾插和尾删,最终剩余的就是结果。
代码实现
java
import java.util.*;
public class Main1{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
char[] arr = in.nextLine().toCharArray();
StringBuilder sb = new StringBuilder();
int i = 0;
while(i<arr.length){
if(sb.isEmpty())
sb.append(arr[i]);
else{
char tmp = sb.charAt(sb.length()-1);
if(tmp==arr[i])
sb.deleteCharAt(sb.length()-1);
else
sb.append(arr[i]);
}
i++;
}
if(sb.isEmpty())
System.out.println(0);
else
System.out.println(sb.toString());
}
}
2. 数组中两个字符串的最小距离
题目描述

解题思路
动态规划:从左向右遍历,dp[i]表示在左边另一个字符串的最近距离。
定义两个指针prev1 prev2,分别记录两个指定字符串最近一次出现的下标.
注意: 对于Scanner在 nextInt()/next() 之后,紧接着用nextLine()读取整行时,需要加in.nextLine(); 来清换行。对于自定义的高速IO不需要特殊操作
代码实现
java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
String str1 = in.next();
String str2 = in.next();
String[] strs = new String[n];
for(int i = 0;i<n;i++)
strs[i] = in.next();
int prev1 = -1;
int prev2 = -1;
int ans = Integer.MAX_VALUE;
for(int i = 0;i<n;i++){
if(strs[i].equals(str1)){
if(prev2!=-1)
ans = Math.min(ans,i-prev2);
prev1 = i;
}
if(strs[i].equals(str2)){
if(prev1!=-1)
ans = Math.min(ans,i-prev1);
prev2 = i;
}
}
if(prev1==-1 || prev2==-1)
System.out.println(-1);
else
System.out.println(ans);
}
}
3. dd爱框框
题目描述

解题思路
滑动窗口:
- 进窗口
- 判断是否符合条件 同时更新结果
- 出窗口
代码实现
java
import java.util.*;
import java.io.*;
public class Main {
static Read in = new Read();
static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
public static void main(String[] args) throws IOException{
int n = in.nextInt();
int x = in.nextInt();
int[] arr = new int[n+1];
for(int i = 1;i<=n;i++){
arr[i] = in.nextInt();
}
int l = 1;
int r = 1;
int len = Integer.MAX_VALUE;
int ansl = 0;
int ansr = 0;
int sum = 0;
while(r<=n){
sum+=arr[r];
while(sum>=x){
if(r-l+1<len){
len = r - l + 1;
ansl = l;
ansr = r;
}
sum-=arr[l++];
}
r++;
}
out.println(ansl+" "+ansr);
out.close();
}
}
class Read{
StringTokenizer st = new StringTokenizer("");
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String next() throws IOException{
while(!st.hasMoreTokens()){
st = new StringTokenizer(bf.readLine());
}
return st.nextToken();
}
String nextLine() throws IOException{
return bf.readLine();
}
int nextInt() throws IOException{
return Integer.parseInt(next());
}
long nextLong() throws IOException{
return Long.parseLong(next());
}
double nextDouble() throws IOException{
return Double.parseDouble(next());
}
}
4. 除2
题目描述

解题思路
贪心+堆:利用大根堆,每次取出最大的偶数,砍半,如果还是偶数则放入堆中
代码实现
java
import java.util.*;
import java.io.*;
public class Main{
static Read in = new Read();
static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
public static void main(String[] args)throws IOException{
int n = in.nextInt();
int k = in.nextInt();
long[] arr = new long[n];
long sum = 0;
PriorityQueue<Long> heap = new PriorityQueue<Long>((a,b)->Long.compare(b,a));
for(int i =0;i<n;i++){
arr[i] = in.nextLong();
sum+=arr[i];
if(arr[i]%2==0){
heap.offer(arr[i]);
}
}
while(k>0 && !heap.isEmpty()){
long tmp = heap.poll();
tmp /= 2;
sum-=tmp;
if(tmp%2==0)
heap.offer(tmp);
k--;
}
out.println(sum);
out.close();
}
}
class Read{
StringTokenizer st = new StringTokenizer("");
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String next() throws IOException{
while(!st.hasMoreTokens()){
st = new StringTokenizer(bf.readLine());
}
return st.nextToken();
}
String nextLine() throws IOException{
return bf.readLine();
}
int nextInt()throws IOException{
return Integer.parseInt(next());
}
long nextLong()throws IOException{
return Long.parseLong(next());
}
double nextDouble()throws IOException{
return Double.parseDouble(next());
}
}
5. 腐烂的苹果(NC398)
题目描述

解题思路
多源BFS+最短路径
与常规的最短路径不同,对于多源BFS来说,最后一个节点也会向外扫描,多记一步,最终结果应该-1
代码实现
java
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param grid int整型ArrayList<ArrayList<>>
* @return int整型
*/
public int rotApple (ArrayList<ArrayList<Integer>> _grid) {
// write code here
int ret = 0;
int m = _grid.size();
int n = _grid.get(0).size();
int[][] grid = new int[m][n];
Queue<int[]> queue = new LinkedList<>();
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
grid[i][j] = _grid.get(i).get(j);
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 2) {
queue.offer(new int[] {i, j});
}
}
}
while (!queue.isEmpty()) {
ret++;
int sz = queue.size();
for (int i = 0; i < sz; i++) {
int[] top = queue.poll();
int ii = top[0];
int jj = top[1];
for (int k = 0; k < 4; k++) {
int x = ii + dx[k];
int y = jj + dy[k];
if(x>=0 && x<m && y>=0 && y<n && grid[x][y] == 1){
grid[x][y] = 2;
queue.offer(new int[]{x,y});
}
}
}
}
for (int i = 0; i < m ; i++) {
for (int j = 0; j < n; j++)
if (grid[i][j] == 1)
return -1;
}
return ret-1;
}
}
6. 大数乘法(NC 10)
题目描述

解题思路
模拟:无进位相加
- 先将两个字符串从个位开始逐位相乘,把每一位的乘积累加到结果数组的对应位置 :第
i位 × 第j位,结果落在i+j位; - 再从低位到高位统一处理进位,生成逆序的结果字符串;
- 最后反转字符串,得到最终的乘积结果。
代码实现
java
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串 第一个整数
* @param t string字符串 第二个整数
* @return string字符串
*/
public String solve (String s, String t) {
// write code here
if(s.equals("0") || t.equals("0"))
return "0";
StringBuilder ret = new StringBuilder();
char[] ss = s.toCharArray();
char[] tt = t.toCharArray();
int m = ss.length;
int n = tt.length;
int[] arr = new int[m+n-1];
for(int i = 0;i<m;i++){
for(int j = 0;j<n;j++){
int n1 = ss[m-1-i] - '0';
int n2 = tt[n-1-j] - '0';
arr[i+j] += n1*n2;
}
}
int r = 0;
int k = 0;
while(k<m+n-1 || r!=0){
if(k<m+n-1)
r+=arr[k++];
ret.append(r%10);
r/=10;
}
return ret.reverse().toString();
}
}