美文网首页
右鸽的多人运动

右鸽的多人运动

作者: JalorOo | 来源:发表于2021-05-21 16:45 被阅读0次

问题

Description

众所周知,右鸽喜欢在深夜多人运动(别想歪了哈哈哈)。他对陪同运动的伙伴们的资产有着严格的要求,如果伙伴们的资产形成的序列是好序列,他才能跑步,否则只能散步。
下面给好序列下个定义:一个整数序列,存在唯一元素。即对于序列a,存在一个a[i]使得任意其他元素都不等于a[i],即a[i] != a[j] for 1 <=j<=len(a),j != i;
给出一个序列A,如果A的全部连续子序列都是好序列,才能说伙伴们的资产形成的序列是好序列,那么右鸽才能跑步,否则右鸽只能散步。

Input

输入描述:
第一行为整数n(1 <= n <= 2*10^5),表示陪同右鸽一起运动的伙伴人数。
第二行为n个整数a[i](0<=a[i] <= 10^9),描述他们的资产。

Output

输出描述:
一行字符串,如果右鸽能跑步,则输出:"paobu"
否则输出:"sanbu"

输入

5
1 2 3 2 1

输出:

paobu

思路

面对一个庞大的串(数组),我们需要拆分为左子串、右子串,

  1. 若左字串为好且右字串为好,拆分规则为中间截断。
  2. 条件1 满足再进行判断整个串为不为好。
  3. 条件1 不满足,则直接返回。

代码解释

主要是使用递归,我很想使用while来实现,无奈技术太菜,也没有时间。

首先我们定义一个判断函数,接收参数s为开始,e为结束,功能是判断从s开始到e的字符是否是为好。

private static boolean judge(int s, int e) {

描写递归出口,当只有一个字符的时候,这个字符必然等于他自己。

        if (s == e) {
            return true;
        }
        if(e == s + 1){
            return a[e] != a[s];
        }

又递归调用,判断自己的子字符串

        int end = ((e+1) / 2) < s? e :(e+1) / 2;
        int endMin = Math.min(end + 1, e);
        if (!judge(s, end) || !judge(endMin, e)) {
            return false;
        }

以上都没返回false的话,则进行自己本身的判断

        //判断整个大子串
        boolean result = true;
        Set<Integer> set = new HashSet<>();
        Map<Integer, Integer> map = new HashMap<>();
        if(flag.get(end)!=null && flag.get(e)!=null){//若开头和结尾已经有记录了
            set.addAll(flag.get(end));
            set.removeAll(flag.get(e));
            return set.size() >= 1;//则比较两个集合里面的元素是否相同
        }
        for (int i = s; i <= e; i++) {
            int b = map.get(a[i]) == null ? 0 : map.get(a[i]);
            ++b;
            map.put(a[i], b);
            set.add(a[i]);
        }
        if (set.size() < e - s + 1) {//若有重复的
            result = false;
            Set<Integer> onlyOneSet = new HashSet<>();//记录没有重复的值
            for (Integer i : set) {
                if (map.get(i) < 2) {//若存在一个数是唯一的
                    result = true;
                    onlyOneSet.add(i);
                }
            }
            if( result )
                flag.put(e,onlyOneSet);
        }else{
            flag.put(e,set);
        }
        return result;
    }

解题代码

package bird;

import java.util.*;

public class Solution {

    static int[] a;
    static Map<Integer, Set<Integer>> flag;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        a = new int[n + 1];
        flag = new HashMap<>();
        for (int i = 1; i <= n; i++) {
            a[i] = scanner.nextInt();
        }
        long  startTime = System.currentTimeMillis();
        String ans0 = "paobu";
        String ans1 = "sanbu";
        boolean j1 = judge(1, (n + 1) / 2);
        if (!j1) {
            System.out.println(ans1);
            long endTime = System.currentTimeMillis();
            System.out.println("程序运行时间:" + (endTime - startTime) + "ms");
            return;
        }
        boolean j2 = judge((n + 1) / 2 + 1, n);
        if (!j2) {
            System.out.println(ans1);
            long endTime = System.currentTimeMillis();
            System.out.println("程序运行时间:" + (endTime - startTime) + "ms");
            return;
        }
        boolean j3 = judge(1, n);
        if (!j3) {
            System.out.println(ans1);
            long endTime = System.currentTimeMillis();
            System.out.println("程序运行时间:" + (endTime - startTime) + "ms");
            return;
        }
        System.out.println(ans0);
        long endTime = System.currentTimeMillis();
        System.out.println("程序运行时间:" + (endTime - startTime) + "ms");
    }

    private static boolean judge(int s, int e) {
        if (s == e) {
            return true;
        }
        if(e == s + 1){
            return a[e] != a[s];
        }
        int end = ((e+1) / 2) < s? e :(e+1) / 2;
        int endMin = Math.min(end + 1, e);
        if (!judge(s, end) || !judge(endMin, e)) {
            return false;
        }
        //判断整个大子串
        boolean result = true;
        Set<Integer> set = new HashSet<>();
        Map<Integer, Integer> map = new HashMap<>();
        if(flag.get(end)!=null && flag.get(e)!=null){//若开头和结尾已经有记录了
            set.addAll(flag.get(end));
            set.removeAll(flag.get(e));
            return set.size() >= 1;//则比较两个集合里面的元素是否相同
        }
        for (int i = s; i <= e; i++) {
            int b = map.get(a[i]) == null ? 0 : map.get(a[i]);
            ++b;
            map.put(a[i], b);
            set.add(a[i]);
        }
        if (set.size() < e - s + 1) {//若有重复的
            result = false;
            Set<Integer> onlyOneSet = new HashSet<>();//记录没有重复的值
            for (Integer i : set) {
                if (map.get(i) < 2) {//若存在一个数是唯一的
                    result = true;
                    onlyOneSet.add(i);
                }
            }
            if( result )
                flag.put(e,onlyOneSet);
        }else{
            flag.put(e,set);
        }
        return result;
    }

    //拆分为左子串、右子串
    //若左字串为好且右字串为好,则判断整个串为不为好
    //
}

相关文章

网友评论

      本文标题:右鸽的多人运动

      本文链接:https://www.haomeiwen.com/subject/vbiwjltx.html