算法刷题日志

文章目录

    • 我在哪?
    • [AcWing 3768. 字符串删减](https://www.acwing.com/problem/content/3771/)
    • 截断数组
    • 砖块

我在哪?

算法刷题日志_第1张图片

二分查找以及字符串哈希,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. 字符串删减

算法刷题日志_第2张图片


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张图片

因为要把数组均分三份,总和一定得是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);
    }
}

砖块

算法刷题日志_第4张图片

这道题为模拟。
从第一个点开始,例如想要把它全部改为黑色:
遍历从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);
        }
    }
}

你可能感兴趣的:(算法,java,c++,数据结构)