zoukankan      html  css  js  c++  java
  • Contest 152

    2019-09-01 20:59:55

    总体感受:最近几次参加contest发现自己的水平还是严重的不够,尤其是在处理一些异常情况的时候,遇到TLE,MLE如何有效的进行Debug是需要去锻炼的。

    注意点:

    1)TLE,首先可以通过加上特殊判断进行解决,这个需要在实际的问题中考虑好特殊的情况,过滤掉明显不符合的解;其次可以考虑是否可以使用位运算来进行状态压缩,同时降低时间复杂度。

    2)1e9 + 7不要使用long / double去规避,目前有的方法有加法每次取mod,或者使用bigInteger。

    3)时间把握不够,每次写到第三题就没什么时间了。

    • 1177. Can Make Palindrome from Substring

    问题描述:

    问题求解:

    解法一:没有考虑到k >= 13的时候直接返回True的特殊情况,导致TLE。加上特判,可以过。但是问题是这个解法的最差时间复杂度是O(mn)。

        public List<Boolean> canMakePaliQueries(String s, int[][] queries) {
            List<Boolean> res = new ArrayList<>();
            char[] chs = s.toCharArray();
            for (int[] q : queries) {
                res.add(helper(chs, q[0], q[1], q[2]));
            }
            return res;
        }
    
        private boolean helper(char[] chs, int s, int e, int k) {
            if (k >= 13) return true;
            Set<Character> set = new HashSet<>();
            for (int i = s; i <= e; i++) {
                char c = chs[i];
                if (!set.add(c)) set.remove(c);
            }
            return set.size() / 2 <= k;
        }

    解法二:比较好的解法是维护一个前缀和,记录前缀的字符出现的次数,之后在查询的时候就不需要再遍历s了,时间复杂度可以降到O(m)。

        public List<Boolean> canMakePaliQueries(String s, int[][] queries) {
            List<Boolean> ans = new ArrayList<>(); 
            int[][] cnt = new int[s.length() + 1][26];
            for (int i = 0; i < s.length(); ++i) {
                cnt[i + 1] = cnt[i].clone(); // copy previous sum.
                ++cnt[i + 1][s.charAt(i) - 'a'];
            }
            for (int[] q : queries) {
                int sum = 0; 
                for (int i = 0; i < 26; ++i) {
                    sum += (cnt[q[1] + 1][i] - cnt[q[0]][i]) % 2;
                }
                ans.add(sum / 2 <= q[2]);
            }
            return ans;
        }
    • 1178. Number of Valid Words for Each Puzzle

    问题描述:

     

    问题求解:

    解法一:BF,TLE。

        public List<Integer> findNumOfValidWords(String[] words, String[] puzzles) {
            List<Integer> res = new ArrayList<>();
            int n = words.length;
            int m = puzzles.length;
            int[][] freqw = new int[n][26];
            int[][] freqq = new int[m][26];
            for (int i = 0; i < n; i++) {
                for (char c : words[i].toCharArray()) {
                    freqw[i][c - 'a']++;
                }
            }
            for (int i = 0; i < m; i++) {
                for (char c : puzzles[i].toCharArray()) {
                    freqq[i][c - 'a']++;
                }
            }
            for (int i = 0; i < m; i++) {
                res.add(helper(freqq[i], puzzles[i].charAt(0), freqw, n));
            }
            return res;
        }
    
        private int helper(int[] freq, char c, int[][] freqw, int n) {
            int res = 0;
            for (int i = 0; i < n; i++) {
                if (freqw[i][c - 'a'] == 0) continue;
                if (isvalid(freq, freqw[i])) res++;
            }
            return res;
        }
        
        private boolean isvalid(int[] freq, int[] freqw) {
            for (int i = 0; i < 26; i++) {
                if (freqw[i] != 0 && freq[i] == 0) return false;
            }
            return true;
        }  

    解法二:

    本题的考点是位运算,可以使用位运算进行状态的压缩,另外单纯知道位运算进行状态压缩还是会TLE。

    需要考虑到puzzles的长度仅仅只有7,也就是说状态压缩之后其subset只有2 ^ 7 = 128种状态,如果直接遍历words的状压的map,会TLE,但是如果遍历puzzle的subset时间复杂度就会降低很多。

    二进制求subset也是本题的核心考点。

        public List<Integer> findNumOfValidWords(String[] words, String[] puzzles) {
            List<Integer> res = new ArrayList<>();
            Map<Integer, Integer> map = new HashMap<>();
            for (String word : words) {
                int mask = 0;
                for (char c : word.toCharArray()) {
                    mask |= 1 << c - 'a';
                }
                map.put(mask, map.getOrDefault(mask, 0) + 1);
            }
            for (String puzzle : puzzles) {
                int sum = 0;
                int mask = 0;
                int start = 1 << puzzle.charAt(0) - 'a';
                for (char c : puzzle.toCharArray()) {
                    mask |= 1 << c - 'a';
                }
                for (int s = mask; s > 0; s = (s - 1) & mask) {
                    if (map.containsKey(s) && (s & start) == start) sum += map.get(s);
                }
                res.add(sum);
            }
            return res;
        }
    

      

  • 相关阅读:
    springboot之热部署
    在动态sql的使用where时,if标签判断中,如果实体类中的某一个属性是String类型,那么就可以这样来判断连接语句:
    对集合进行判空的操作
    配置logback日志管理的时候
    SpringBoot序列化时间类型的问题
    Cannot determine embedded database driver class for database type NONE
    idea的基础设置
    使用navicat创建数据库
    LESS
    数据库链接池--简单的理解
  • 原文地址:https://www.cnblogs.com/hyserendipity/p/11444323.html
Copyright © 2011-2022 走看看