LeetCode第160场周赛题解

题目链接

5238. 找出给定方程的正整数解

这个题主要考阅读理解,除去阅读之外,很容易就可解决。有两种解法:

  1. 暴力O(n^2)

    public List<List<Integer>> findSolution(CustomFunction customfunction, int z) {
            List<List<Integer>> listListInt = new ArrayList<>();
            for (int x = 1; x <= 1000; x ++) {
                for (int y = 1; y <= 1000; y ++) {
                    if (z == customfunction.f(x,y)) {
                        List<Integer> listInt = new ArrayList<>();
                        listInt.add(x);
                        listInt.add(y);
                        listListInt.add(listInt);
                    }
                }
            }
            return listListInt;
        }
    
  2. 第二种方法,根据题目中说到的单调性,我们可以尝试构造出O(n)时间复杂度的解决方案

    这里参考了这位同学的解法

    • 通时,LeetCode第74题也是这种解法或者用二分法
        public List<List<Integer>> findSolution(CustomFunction customfunction, int z) {
            List<List<Integer>> listListInt = new ArrayList<>();
            int x = 1, y = 1000;
            while (x <= 1000 && y >= 1) {
                if (z > customfunction.f(x,y)) x ++; 
                else if (z < customfunction.f(x,y)) y --; 
                else {
                    List<Integer> listInt = new ArrayList<>();
                    listInt.add(x);
                    listInt.add(y);
                    listListInt.add(listInt);
                    y --; // 此处换为x ++也可
                }
            }
            return listListInt;
        }
    

5239. 循环码排列

这个题是格雷码的变种题,如果不了解格雷码,可以参考这个题:格雷码

格雷码构成一般方法(非公式):

LeetCode第160场周赛题解_第1张图片

    // 法一:用参考题的方法也可解决,不过要修改add的位数
    // 法二:异或:值相同为0,不同为1
    public List<Integer> circularPermutation(int n, int start) {
        List<Integer> grayCode = new ArrayList<>();
        grayCode.add(start);
        int offset = 0;
        for (int i = 0; i < n; i ++) {
            for (int j = grayCode.size() - 1; j >= 0; j --) {
                grayCode.add(grayCode.get(j) ^ (1 << offset));
            }
            offset ++;
        }
        return grayCode;
    }

5240. 串联字符串的最大长度

对于这个题来说,可以用DFS来解决。DFS即Depth first search,深度优先遍历,这是在树中所必学的一个算法。

对于本题来说,我们也可以把这个List当做一个树,因为每一个元素都有两种遍历方式,即比较或者不比较,用题目中的例子来说:["cha", "r", "act", "ers"],它所派生出的二叉树如下:

LeetCode第160场周赛题解_第2张图片

按照上面的例子,一共有16中情况,DFS流程为:

  • 从第一个字符串开始遍历
    • 两种情况,第一种是加入第一个字符串
    • 第二种是不要第一个字符串
  • 遇到第二个字符串,比较第一个字符串和第二个字符串是否有相同的字符
  • 如果相同,跳过第二个字符,如果不同,把第二个字符加入
  • 如果字符串到达List的最后一个,结束。否则,跳转到第一步
    int maxLen = 0;
    public int maxLength(List<String> arr) {
        dfs(arr, 0, 0, 0);
        return maxLen;
    }
    private void dfs(List<String> arr, int index, int ck, int tempMax) {
        if (index == arr.size()) {
            maxLen = Math.max(maxLen, tempMax);
            return;
        }
        String str = arr.get(index);
        int tempCk = getCk(ck, str);
        if (tempCk != -1) dfs(arr, index + 1, tempCk, tempMax + str.length());
        dfs(arr, index + 1, ck, tempMax);
    }
    // 比较str和之前ck代表的字符串是否有相同字符,如果没有,则把str代表的ck加去,如果有,则返回-1
    private int getCk(int ck, String str) {
        char[] chars = str.toCharArray();
        for(char c: chars) {
            int tempInt = c - 'a';
            if ((ck & (1 << tempInt)) != 0) {
                return -1;
            }
            ck = ck | (1 << tempInt);
        }
        return ck;
    }

说句题外话,查看两个字符串(只含有小写字符)是否有相同字符的方法:

  1. 使用一个一维数组,遍历两边字符串。空间复杂度O(1),时间复杂度O(n)

        private boolean notEqual(String a, String b) {
            int[] charArray = new int[30];
            for (int i = 0; i < a.length(); i ++) {
                charArray[a.charAt(i) - 'a'] = 1;
            }
            for (int i = 0; i < b.length(); i ++) {
                if (charArray[b.charAt(i) - 'a'] == 1) {
                    return false;
                }
            }
            return true;
        }
    
  2. 使用位运算:``ck & (1 << i) == 0`

    其中,ck是一个最少26byte的字符,从左至右,每一位分别代表a,b,x,y,x

    i代表字符串中的字符

        // 比较str和之前ck代表的字符串是否有相同字符,如果没有,则把str代表的ck加去,如果有,则返回-1
        private int notEqual(int ck, String str)) {
            char[] chars = str.toCharArray();
            for(char c: chars) {
                if (ck & 1 << (a - 'a')) != 0) {
                    return -1;
                }
                ck = ck | 1 << (a - 'a');
            }
            return ck;
        }
    

4.

这个题水平不够,,,没有题解。。。。

你可能感兴趣的:(算法和数据结构)