简单算法题 矩阵复用

[编程题] 手串

时间限制:1秒

空间限制:65536K

作为一个手串艺人,有金主向你订购了一条包含n个杂色串珠的手串——每个串珠要么无色,要么涂了若干种颜色。为了使手串的色彩看起来不那么单调,金主要求,手串上的任意一种颜色(不包含无色),在任意连续的m个串珠里至多出现一次(注意这里手串是一个环形)。手串上的颜色一共有c种。现在按顺时针序告诉你n个串珠的手串上,每个串珠用所包含的颜色分别有哪些。请你判断该手串上有多少种颜色不符合要求。即询问有多少种颜色在任意连续m个串珠中出现了至少两次。


输入描述:
第一行输入n,m,c三个数,用空格隔开。(1 <= n <= 10000, 1 <= m <= 1000, 1 <= c <= 50) 接下来n行每行的第一个数num_i(0 <= num_i <= c)表示第i颗珠子有多少种颜色。接下来依次读入num_i个数字,每个数字x表示第i颗柱子上包含第x种颜色(1 <= x <= c)


输出描述:
一个非负整数,表示该手链上有多少种颜色不符需求。

输入例子1:
5 2 3
3 1 2 3
0
2 2 3
1 2
1 3

输出例子1:
2

例子说明1:
第一种颜色出现在第1颗串珠,与规则无冲突。
第二种颜色分别出现在第 1,3,4颗串珠,第3颗与第4颗串珠相邻,所以不合要求。
第三种颜色分别出现在第1,3,5颗串珠,第5颗串珠的下一个是第1颗,所以不合要求。
总计有2种颜色的分布是有问题的。 
这里第2颗串珠是透明的。

这是头条的笔试题,难度不高,但是这个题型在头条笔试中经常考,就是考察一个矩阵集合的复用。

当你到达下一个矩阵的时候,需要剔除原矩阵的第一行,加上矩阵下面的第一行


3 1 2 3
0
2 2 3
1 2
1 3

可以视为

111

000

011

010

001

简单记录下就能做出来


代码

import java.util.Scanner;

public class toutiao_test_2 {
    public static void main(String args[]) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();//连续m        int c = scanner.nextInt();//一共c种颜色

        //5 2 3

        //3 1 2 3
        //0
        //2 2 3
        //1 2
        //1 3

        byte[][] a = new byte[n][c];

        for (int i = 0; i < n; i ++) {
            int num = scanner.nextInt();
            for (int j = 0; j < num; j ++) {
                int color = scanner.nextInt();
                a[i][color - 1] = 1;
            }
        }

//        1 1 1
//        0 0 0
//        0 1 1
//        0 1 0
//        0 0 1

        byte[] result = new byte[c];//记录已重复的颜色

        //计算0m-1的累加
        int[] record = new int[c];//记录数组,记录每个位置的总数
        for (int i = 0; i < m; i ++) {
            for (int j = 0; j < c; j ++) {
                if (result[j] == 0) {//只有0才需要计算,不然已经就失败了
                    if (a[i][j] == 1) {//这个位上如果
                        record[j] += 1;
                        if (record[j] >= 2) {
                            result[j] = 1;
                        }
                    }
                }
            }
        }

        for (int i = 1; i < n; i ++) {
            //remove start
            byte[] start = a[i - 1];
            for (int j = 0; j < c; j ++) {
                if (result[j] == 0) {
                    if (start[j] == 1) {
                        record[j] -= 1;
                    }
                }
            }
            
            //add end
            byte[] end = a[(i - 1 + m)%n];
            for (int j = 0; j < c; j ++) {
                if (result[j] == 0) {
                    if (end[j] == 1) {
                        record[j] += 1;
                        if (record[j] >= 2) {
                            result[j] = 1;
                        }
                    }
                }
            }
        }

        int count = 0;
        for (int i = 0; i < c; i ++) {
            if (result[i] == 1) {
                count ++;
            }
        }

        System.out.print(count);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值