LeetCode-20200824-20200830

9 篇文章 0 订阅

重复的子字符串

  • 题目。给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。
  • 思路。O(N*N) 的解法比较好想。O(N)的解法是将两个 s连在一起得到ss,并移除第一个和最后一个字符。如果 ss 是该字符串的子串,那么 ss 就满足题目要求。
  • 代码。
public boolean repeatedSubstringPattern(String s) {
        if (s == null || s.length() == 0) {
            return true;
        }

        return (s + s).indexOf(s, 1) != s.length();

        // char[] ch = s.toCharArray(); 
        // for (int i = 1; i * 2 <= ch.length; i++) {
        //     if (ch.length % i != 0) {
        //         continue;
        //     }

        //     boolean match = true;
        //     for (int j = i; j < ch.length; j++) {
        //         if (ch[j] != ch[j - i]) {
        //             match = false;
        //             break;
        //         }
        //     }

        //     if (match) {
        //         return true;
        //     }
        // }
    
        // return false;
    }

递增子序列

  • 题目。给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。示例:
    输入: [4, 6, 7, 7]
    输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]
    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/increasing-subsequences

  • 思路。枚举所有结果。对于当前的位置,我们可以选也可以不选。如果选择当前元素,则必须满足当前元素大于前一个元素;如果不选择当前元素,那么前提是当前元素不等于前一个元素。

  • 代码。

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> tmp = new ArrayList<>();

    public List<List<Integer>> findSubsequences(int[] nums) {
        if (nums == null || nums.length == 0 || nums.length == 1) {
            return new ArrayList<>();
        }

        dfs(0, Integer.MIN_VALUE, nums);
        return res;
    }

    private void dfs(int curIndex, int preValue, int[] nums) {
        if (curIndex == nums.length) {
            if (tmp.size() >= 2) {
                res.add(new ArrayList<>(tmp));
            }
            return;
        }

        if (nums[curIndex] >= preValue) {
            tmp.add(nums[curIndex]);
            dfs(curIndex + 1, nums[curIndex], nums);
            tmp.remove(tmp.size() - 1);
        }

        if (nums[curIndex] != preValue) {
            dfs(curIndex + 1, preValue, nums);
        }
    }
}

电话号码的字母组合

  • 题目。给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
    给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
    示例:
    输入:“23”
    输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].
    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number

  • 思路。基于深度优先遍历,使用i表示当前遍历到的位置,如果i等于digits.length则得到了一个结果。

  • 代码。

class Solution {
    public List<String> letterCombinations(String digits) {
        if (digits == null || digits.length() == 0) {
            return new ArrayList<>();
        }

        char[] ch = digits.toCharArray();
        List<String> res = new ArrayList<>();
        search(ch, 0, "", res);
        return res;
    }

    /**
     * 表示从i位置开始,已有的字符串是s,能够得到的结果
     */
    private void search(char[] ch, int i, String s, List<String> res) {
        if (i == ch.length) {
            res.add(s);
            return;
        }

        char[] letters = letters(ch[i]);
        for (char c : letters) {
            search(ch, i + 1, s + c, res);
        }
    }

    private char[] letters(char ch) {
        List<Character> res = new ArrayList<>();
        if (ch == '2') {
            return new char[] {'a', 'b', 'c'};
        }

        if (ch == '3') {
            return new char[] {'d', 'e', 'f'};
        }

        if (ch == '4') {
            return new char[] {'g', 'h', 'i'};
        }

        if (ch == '5') {
            return new char[] {'j', 'k', 'l'};
        }

        if (ch == '6') {
            return new char[] {'m', 'n', 'o'};
        }

        if (ch == '7') {
            return new char[] {'p', 'q', 'r', 's'};
        }

        if (ch == '8') {
            return new char[] {'t', 'u', 'v'};
        }

        return new char[] {'w', 'x', 'y', 'z'};
    }
}

重新安排行程

  • 题目。给定一个机票的字符串二维数组 [from, to],子数组中的两个成员分别表示飞机出发和降落的机场地点,对该行程进行重新规划排序。所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 开始。
    提示:
    如果存在多种有效的行程,请你按字符自然排序返回最小的行程组合。例如,行程 [“JFK”, “LGA”] 与 [“JFK”, “LGB”] 相比就更小,排序更靠前
    所有的机场都用三个大写字母表示(机场代码)。
    假定所有机票至少存在一种合理的行程。
    所有的机票必须都用一次 且 只能用一次。
    示例 1:
    输入:[[“MUC”, “LHR”], [“JFK”, “MUC”], [“SFO”, “SJC”], [“LHR”, “SFO”]]
    输出:[“JFK”, “MUC”, “LHR”, “SFO”, “SJC”]
    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/reconstruct-itinerary
  • 思路。一道欧拉图相关的题。
  • 代码。
class Solution {
    public List<String> findItinerary(List<List<String>> tickets) {
        if (tickets == null || tickets.size() == 0) {
            return new ArrayList<>();
        }
        LinkedList<String> res = new LinkedList<>();

        // 构造图
        Map<String, PriorityQueue<String>> graph = new HashMap<>();
        for (List<String> ticket : tickets) {
            PriorityQueue<String> edges = graph.computeIfAbsent(ticket.get(0), k -> new PriorityQueue<>());
            edges.add(ticket.get(1));
        }

        visit(graph, "JFK", res);
        return res;
    }

    private void visit(Map<String, PriorityQueue<String>> graph, String cur, LinkedList<String> res) {
        PriorityQueue<String> edges = graph.get(cur);
        while (edges != null && edges.size() > 0) {
            String neighbor = edges.poll();
            visit(graph, neighbor, res);
        }
        res.addFirst(cur);
    }
}

机器人能否返回原点

  • 题目。在二维平面上,有一个机器人从原点 (0, 0) 开始。给出它的移动顺序,判断这个机器人在完成移动后是否在 (0, 0) 处结束。
    移动顺序由字符串表示。字符 move[i] 表示其第 i 次移动。机器人的有效动作有 R(右),L(左),U(上)和 D(下)。如果机器人在完成所有动作后返回原点,则返回 true。否则,返回 false。
    注意:机器人“面朝”的方向无关紧要。 “R” 将始终使机器人向右移动一次,“L” 将始终向左移动等。此外,假设每次移动机器人的移动幅度相同。
    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/robot-return-to-origin

  • 思路。简单的题。

  • 代码。

class Solution {
    public boolean judgeCircle(String moves) {
        int l = 0;
        int r = 0;
        int u = 0;
        int d = 0;
        char[] ch = moves.toCharArray();
        for (char c : ch) {
            if (c == 'L') {
                l++;
            } else if (c == 'R') {
                r++;
            } else if (c == 'U') {
                u++;
            } else {
                d++;
            }
        }
        
        return l == r && u == d;
    }
}

最短回文串

  • 题目。给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。
    示例 1:
    输入: “aacecaaa”
    输出: “aaacecaaa”
    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/shortest-palindrome
  • 思路。Manacher的变种。找到必须包含第一个字符的最长回文子串,将后面的部分反转填到原始字符串前面即可。
  • 代码。
class Solution {
    public String shortestPalindrome(String s) {
        if (s == null || s.length() == 0) {
            return s;
        }

        // 找到必须包含第一个字符的最长回文子串,将后面的部分反转填到原始字符串前面即可
        char[] ch = convert(s);

        // pArr[i]表示以i位置的字符为中心,向左右两边可以扩出去的最大回文半径
        int[] pArr = new int[ch.length];

        // 最右即将到达的位置
        int pR = -1;

        // 最近一次pR更新时,回文中心的位置
        int index = -1;
        // 包含第一个字符的最长回文半径长度
        int maxContainsStart = -1;
        for (int i = 0; i < ch.length; i++) {
            pArr[i] = i < pR ? Math.min(pArr[2 * index - i], pR - i) : 1;
            // 向两边扩
            while (i + pArr[i] < ch.length && i - pArr[i] > -1) {
                if (ch[i + pArr[i]] == ch[i - pArr[i]]) {
                    pArr[i]++;
                } else {
                    break;
                }
            }

            if (i + pArr[i] > pR) {
                pR = i + pArr[i];
                index = i;
            }

            if (i + 1 == pArr[i]) {
                maxContainsStart = Math.max(maxContainsStart, pArr[i]);
            }
        }


        int resIndex = (maxContainsStart - 1) * 2;
        if (ch.length - 1 == resIndex) {
            return s;
        }

        char[] prefix = new char[ch.length - 1 - resIndex];
        int j = 0;
        for (int i = ch.length - 1; i > resIndex; i--) {
            prefix[j++] = ch[i];
        }
        String s1 = String.valueOf(prefix) + String.valueOf(ch);
        StringBuilder res = new StringBuilder();
        for (int i = 0; i < s1.length(); i++) {
            if ((i & 1) == 1) {
                res.append(s1.charAt(i));
            }
        }

        return res.toString();
    }

    private char[] convert(String s) {
        char[] ch = s.toCharArray();
        char[] res = new char[2 * ch.length + 1];
        int index = 0;
        for (int i = 0; i < res.length; i++) {
            res[i] = (i & 1) == 0 ? '#' : ch[index++];
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeetCode-Editor是一种在线编码工具,它提供了一个用户友好的界面编写和运行代码。在使用LeetCode-Editor时,有时候会出现乱码的问题。 乱码的原因可能是由于编码格式不兼容或者编码错误导致的。在这种情况下,我们可以尝试以下几种解决方法: 1. 检查文件编码格式:首先,我们可以检查所编辑的文件的编码格式。通常来说,常用的编码格式有UTF-8和ASCII等。我们可以将编码格式更改为正确的格式。在LeetCode-Editor中,可以通过界面设置或编辑器设置来更改编码格式。 2. 使用正确的字符集:如果乱码是由于使用了不同的字符集导致的,我们可以尝试更改使用正确的字符集。常见的字符集如Unicode或者UTF-8等。在LeetCode-Editor中,可以在编辑器中选择正确的字符集。 3. 使用合适的编辑器:有时候,乱码问题可能与LeetCode-Editor自身相关。我们可以尝试使用其他编码工具,如Text Editor、Sublime Text或者IDE,看是否能够解决乱码问题。 4. 查找特殊字符:如果乱码问题只出现在某些特殊字符上,我们可以尝试找到并替换这些字符。通过仔细检查代码,我们可以找到导致乱码的特定字符,并进行修正或替换。 总之,解决LeetCode-Editor乱码问题的方法有很多。根据具体情况,我们可以尝试更改文件编码格式、使用正确的字符集、更换编辑器或者查找并替换特殊字符等方法来解决这个问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值