zoukankan      html  css  js  c++  java
  • LeetCode 第 152 场周赛

    一、质数排列(LeetCode-1175)

    1.1 题目描述

    1.2 解题思路

    先统计出1-n中有多少个质数,得到质数个数(x),剩下的数(y = n - x)

    使用排列组合公式得出结果

    (A_x^x A_y^y)

    1.3 解题代码

    
    
    private static final long INF = 1000000007;
    
        public int numPrimeArrangements(int n) {
    
            int count = countPrime(n);
            //剩余位数
            int other = n - count;
            long res = 1;
            for (int i = 1; i <= count; i++) {
                res *= i;
                if(res > INF) res%=INF;
            }
            for (int i = 1; i <= other; i++) {
                res *= i;
                if(res > INF) res%=INF;
            }
    
            return (int) res;
        }
    
    
        /**
         * 判断n个数中有多少个质数
         *
         * @param n
         * @return
         */
        private int countPrime(int n) {
            int count = 0;
            for (int i = 2; i <= n; i++) {
                if (isPrime(i)) {
                    ++count;
                }
            }
            return count;
        }
    
        /**
         * 判断是否是质数
         *
         * @param n
         * @return
         */
        private boolean isPrime(int n) {
            if(n == 1){
                return false;
            }
            for (int i = 2; i <= Math.sqrt(n); i++) {
                if (n % i == 0) {
                    return false;
                }
            }
            return true;
        }
    
    
    

    二、健身计划评估(LeetCode-5174)

    2.1 题目描述

    2.2 解题思路

    非常简单的一道题,理解清楚题意就好。只要是连续的k天,都可以。

    2.3 解题代码

    
    public class Solution {
    
        public int dietPlanPerformance(int[] calories, int k, int lower, int upper) {
    
            int res = 0;
            int len = calories.length;
            OK:
            for (int i = 0; i < len; i++) {
                int sum = 0;
                if (i + k > len) {
                    continue OK;
                }
                for (int j = 0; j < k; j++) {
                    sum += calories[i + j];
                }
                if (sum > upper) {
                    res++;
                }
                if (sum < lower) {
                    res--;
                }
    
            }
            return res;
        }
    
    }
    

    三、构建回文串检测(LeetCode-5175)

    3.1 题目描述

    3.2 解题思路

    注意审题,可以对子串进行重新排序。

    思路1:所有可以统计子串中字符出现的次数。(超时)

    思路2:使用动态规划的思想,定义dict[n][t],dict[3][4]表示从第0个字符,到第3个字符的子串,第5个字符e的个数。(超时)

    思路3:使用位运算的思想,只关心每个字符是奇数或偶数,定义dict[n],表示0-n的子字符串的异或运算结果。

    例如:
    abc的位异或运算结果为1+2+4 = 7。
    abca = 1+2+4 -1 = 2+4 = 6

    公式为

    bitArray[i] = 1 << (strDict[i] - 'a');
    if (i > 0) {
        bitArray[i] ^= bitArray[i - 1];
    }
    

    最后统计子字符串异或结果中1的个数。

    公式为

    while (sum != 0) {
        sum &= (sum - 1);
        count++;
    }
    

    3.3 解题代码

    思路1:下面的提交,会提示超时。

    
    
    public class Solution {
    
        public List<Boolean> canMakePaliQueries(String s, int[][] queries) {
    
            List<Boolean> res = new ArrayList<>(queries.length);
    
            for (int i = 0; i < queries.length; i++) {
                int left = queries[i][0];
                int right = queries[i][1] + 1;
                String subStr = s.substring(left, right);
                res.add(isAlindrome(subStr, right - left, queries[i][2]));
            }
    
            return res;
        }
        
    
        private boolean isAlindrome(String str, int len, int k) {
            if (k >= 13) {
                return true;
            }
            if (len == 1 || len / 2 <= k) {
                return true;
            }
            int[] z = new int[26];
            for (int i = 0; i < len; i++) {
                z[str.charAt(i) - 'a']++;
            }
            int diff = 0;
            for (int i = 0; i < 26; i++) {
                if (z[i] > 0 && z[i] % 2 != 0) {
                    diff++;
                }
            }
            if (diff / 2 <= k) {
                return true;
            }
            return false;
        }
    
    }
    
    
    

    思路2:提交仍然会超时

    
    public class Solution2 {
    
        public List<Boolean> canMakePaliQueries(String s, int[][] queries) {
            int len = s.length();
            List<Boolean> res = new ArrayList<>(len);
    
            int[][] dict = new int[len][26];
            char[] strDict = s.toCharArray();
            for (int i = 0; i < len; i++) {
                if (i > 0) {
                    dict[i] = dict[i - 1].clone();
                }
                dict[i][strDict[i] - 'a']++;
            }
    
    
            for (int i = 0; i < queries.length; i++) {
                int left = queries[i][0];
                int right = queries[i][1];
                int k = queries[i][2];
                int diff = 0;
    
                for (int j = 0; j < 26; j++) {
                    if (left == 0) {
                        if ((dict[right][j] & 1) != 0) {
                            diff++;
                        }
                    } else {
                        if (((dict[right][j] - dict[left - 1][j]) & 1) != 0) {
                            diff++;
                        }
                    }
                }
                res.add(diff / 2 <= k);
            }
            return res;
    
        }
    
    }
    
    
    

    思路3:可以AC

    
    public class Solution3 {
    
        public List<Boolean> canMakePaliQueries(String s, int[][] queries) {
    
            int len = s.length();
            List<Boolean> res = new ArrayList<>(len);
    
            int[] bitArray = new int[len];
            char[] strDict = s.toCharArray();
            for (int i = 0; i < len; i++) {
                bitArray[i] = 1 << (strDict[i] - 'a');
                if (i > 0) {
                    bitArray[i] ^= bitArray[i - 1];
                }
            }
    
            for (int i = 0; i < queries.length; i++) {
                int left = queries[i][0];
                int right = queries[i][1];
                int k = queries[i][2];
                //子串各个位之和
                int sum = 0;
                if (left == 0) {
                    sum = bitArray[right];
                } else {
                    sum = bitArray[right] ^ bitArray[left - 1];
                }
                //计算子串的位中有多少个1
                int count = 0;
                //k <= count/2  等价于 2*k + 1 <= count
                k = 2 * k + 1;
                boolean ok = true;
                while (sum != 0) {
                    sum &= (sum - 1);
                    count++;
                    if (count > k) {
                        ok = false;
                        break;
                    }
                }
                res.add(ok);
            }
    
            return res;
        }
    
    }
    
    
  • 相关阅读:
    javaweb中带标签体的自定义标签
    javaweb带父标签的自定义标签
    Filter的常见应用
    Filter内容
    JFace TableViewer性能改善 -- 使用VirtualTable
    SWT table性能改善 -- 使用VirtualTable
    java自动探测文件的字符编码
    [小技巧]Filezilla无法确定拖放操作目标,由于shell未正确安装__解决办法
    批量导出VBA工程中的Source
    开源许可证知多少
  • 原文地址:https://www.cnblogs.com/fonxian/p/11444302.html
Copyright © 2011-2022 走看看