算法刷题日志-爱代码爱编程
我在哪?
二分查找以及字符串哈希,mid之后的答案都是合法的,此题寻找的是最小的K值,所以check的话 如果mid是true的话,那就把r变为mid,反之 l=mid+1,这题就是寻找最小长度下不重复的字符串,所以不等于1的时候就返回FALSE;
import java.util.*;
public class Main {
static int n;
static String s;
public static boolean check (int mid ){
Map<String,Integer> map = new HashMap<>();
int max=0;
for(int i=0;i<=n-mid;i++) {
String t = s.substring(i, mid + i);
if(map.get(t)==null)map.put(t,1);
else map.put(t,map.get(t)+1);
max = Math.max(max,map.get(t));
if(max!=1)return false;
}
return true;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n=sc.nextInt();
s=sc.next();
int l =0,r=n;
while(l<r){
int mid = l+((r-l)>>1);
if(check(mid))r=mid;
else l=mid+1;
}
System.out.println(l);
}
}
AcWing 3768. 字符串删减
import java.util.Scanner;
public class Main {
static final int N = 110;
static char[] s = new char[N];
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int n = in.nextInt();
s = in.next().toCharArray();
int res = 0;
for (int i = 0; i < n; i ++){
if (s[i] != 'x') continue;
int j = i + 1;
while (j < n && s[j] == 'x') j ++;
res += Math.max(j-i-2, 0);
i = j;
}
System.out.println(res);
}
}
截断数组
因为要把数组均分三份,总和一定得是3的倍数
遍历前缀和数组,边扫描边记录哪些地方可以切第一刀,哪些地方可以切第二刀。如果位置j可以切第二刀,那么它与前面第一刀进行组合,就可以切成三部分。
import java.util.*;
public class Main{
static int N = 100010;
static int n, m;
static long res;
static int[] a = new int[N];
static int[] s = new int[N];
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
for (int i = 1; i <= n; i ++) a[i] = scan.nextInt();
for (int i = 1; i <= n; i ++) s[i] = s[i - 1] + a[i];
if (s[n] % 3 != 0 || n < 3)
{
System.out.println(0);
return;
}
int dex = s[n] / 3;
for (int i = 1; i < n; i ++)
{
//不能调换这两个if判断的原因是,如果当前tot等于perSum和perSum*2时(比如0特判等),就会出现在同一位自加
//一旦出现自加,那么可以理解为中间那个截断元素个数为0,这是不可能的
if (s[i] == dex * 2) res += m;
if (s[i] == dex) ++ m;
}
System.out.println(res);
}
}
砖块
这道题为模拟。
从第一个点开始,例如想要把它全部改为黑色:
遍历从1~n的每个点,如果这个点是白色,那么把它和它后面那个反转颜色。
若遍历完后最后一个点仍然不匹配,那么全部改为黑色就是一种不可行的方案。白色同理。
如果黑色不匹配的话还可以用白色,若白色也不匹配则无解。
import java.util.*;
public class Main{
static int n;
public static void update(char[] s, int i){
if (s[i] == 'B') s[i] = 'W';
else s[i] = 'B';
}
public static boolean check(char[] s, char c){
int[] res = new int[3 * n];
char[] tem = new char[n];
for (int i = 0; i < n; i ++) tem[i] = s[i];
int k = 0;
for (int i = 0; i + 1 < n; i ++){
if (tem[i] != c){
update(tem, i);
update(tem, i+1);
res[k ++] = i;
}
}
if (tem[n-1] != tem[0]) return false;
System.out.println(k);
//砖块编号是从1开始的所以需要加一
for (int i = 0; i < k; i ++) System.out.print((res[i]+1) + " ");
if (k != 0) System.out.println();
return true;
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int T = scan.nextInt();
while (T -- > 0){
n = scan.nextInt();
char[] s = scan.next().toCharArray();
if (!check(s, 'W') && !check(s, 'B')) System.out.println(-1);
}
}
}