leetcode 字符串

目录

1.验证回文串

2.分割回文串

3.单词拆分

4.单词拆分II

5.实现Trie(前缀树)

6.单词搜索II

7.有效的字母异位词

8.字符串中的第一个唯一字符

9.反转字符串


1.验证回文串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

示例 1:

输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]
class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        head = 0
        rear = len(s) - 1
        while head < rear:
            s[head], s[rear] = s[rear], s[head]
            head += 1
            rear -= 1

2.分割回文串

给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。返回 s 所有可能的分割方案。

输入: "aab"
输出:
[
  ["aa","b"],
  ["a","a","b"]
]
class Solution:
    def partition(self, s):
        """
        :type s: str
        :rtype: List[List[str]]
        """
        if len(s) == 0:
            return []
        else:
            res = []
            self.partition_helper(s, [], res)
        return res

    def partition_helper(self, s, cur_res, result):
        if len(s) == 0:
            result.append(cur_res)
        for i in range(1, len(s)+1):
            if self.check(s[:i]):
                self.partition_helper(s[i:], cur_res + [s[:i]], result)


    def check(self, s):
        if len(s) == 0:
            return False
        else:
            start = 0
            end = len(s) - 1
            while start <= end:
                if s[start] != s[end]:
                    return False
                else:
                    start += 1
                    end -= 1
            return True


3.单词拆分

给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

说明:

拆分时可以重复使用字典中的单词。

你可以假设字典中没有重复的单词。

示例 1:

输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。

示例 2:

输入: s = "applepenapple", wordDict = ["apple", "pen"]
输出: true
解释: 返回 true 因为 "applepenapple" 可以被拆分成 "apple pen apple"
  注意你可以重复使用字典中的单词。

示例 3:

输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
输出: false
class Solution(object):
    def wordBreak(self, s, wordDict):
        """
        :type s: str
        :type wordDict: List[str]
        :rtype: bool
        """
        
        #将list变为set
        wordset = set(wordDict)
        dp = [0 for _ in range(len(s))]
        
        for i in range(len(s)):
            for j in range(0,i+1):
                if s[0:i+1] in wordset or s[j+1:i+1] in wordset and dp[j] ==1:
                    dp[i] = 1
                    break
        return dp[len(s)-1] == 1
    
        

4.单词拆分II

给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。

说明:

分隔时可以重复使用字典中的单词。你可以假设字典中没有重复的单词。

输入:
s = "catsanddog"
wordDict = ["cat", "cats", "and", "sand", "dog"]
输出:
[
  "cats and dog",
  "cat sand dog"
]

示例 2:

输入:
s = "pineapplepenapple"
wordDict = ["apple", "pen", "applepen", "pine", "pineapple"]
输出:
[
  "pine apple pen apple",
  "pineapple pen apple",
  "pine applepen apple"
]
解释: 注意你可以重复使用字典中的单词。

示例 3:

输入:
s = "catsandog"
wordDict = ["cats", "dog", "sand", "and", "cat"]
输出:
[]
class Solution(object):
    def wordBreak(self, s, wordDict):
        """
        :type s: str
        :type wordDict: List[str]
        :rtype: List[str]
        """
        res = []
        if len(s) == 0 or not wordDict:
            return []
        strides = [len(x) for x in wordDict]
        max_stride = max(strides)
        stride_set = set(strides)
        if self.canBreak(s, wordDict):
            self.sub_wordBreak(s, wordDict, max_stride, stride_set, [], res)
        return res
    
    def sub_wordBreak(self, sub_s, wordDict, max_stride, stride, cur_result, result):
        if len(sub_s) == 0:
            result.append(" ".join(cur_result))
        else:
            for stride_length in stride:
                if stride_length <= len(sub_s):
                    if sub_s[:stride_length] in wordDict:
                        self.sub_wordBreak(sub_s[stride_length:], wordDict, max_stride,stride, cur_result + [sub_s[:stride_length]], result)
            
    def canBreak(self, s, wordDict):
        can_make = [False] * (len(s)+1)         
        can_make[0] = True
        for i in range(1, len(s)+1):            
            for j in range(i-1, -1, -1):        
                if can_make[j] and s[j:i] in wordDict:
                    can_make[i] = True
                    break
        return can_make[-1]       

        

5.实现Trie(前缀树)

实现一个 Trie (前缀树),包含 insertsearch, 和 startsWith 这三个操作。

Trie trie = new Trie();

trie.insert("apple");
trie.search("apple");   // 返回 true
trie.search("app");     // 返回 false
trie.startsWith("app"); // 返回 true
trie.insert("app");   
trie.search("app");     // 返回 true

说明:

  • 你可以假设所有的输入都是由小写字母 a-z 构成的。
  • 保证所有输入均为非空字符串。
class Trie(object):
 
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.dic = {}
        self.prefix = set()
 
    def insert(self, word):
        """
        Inserts a word into the trie.
        :type word: str
        :rtype: void
        """
        self.dic[word] = word
        i = 1
        while i < len(word)+1:
            self.prefix.add(word[:i])
            i += 1
 
 
 
    def search(self, word):
        """
        Returns if the word is in the trie.
        :type word: str
        :rtype: bool
        """
        return True if word in self.dic else False
 
    def startsWith(self, prefix):
        """
        Returns if there is any word in the trie that starts with the given prefix.
        :type prefix: str
        :rtype: bool
        """
        return True if prefix in self.prefix else False

6.单词搜索II

给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。

输入: 
words = ["oath","pea","eat","rain"] and board =
[
  ['o','a','a','n'],
  ['e','t','a','e'],
  ['i','h','k','r'],
  ['i','f','l','v']
]

输出: ["eat","oath"]

说明:
你可以假设所有输入都由小写字母 a-z 组成。

提示:

  • 你需要优化回溯算法以通过更大数据量的测试。你能否早点停止回溯?
  • 如果当前单词不存在于所有单词的前缀中,则可以立即停止回溯。什么样的数据结构可以有效地执行这样的操作?散列表是否可行?为什么? 前缀树如何?如果你想学习如何实现一个基本的前缀树,请先查看这个问题: 实现Trie(前缀树)
class Solution {
    private TrieNode root = new TrieNode();
    private int[] row = new int[]{-1,1,0,0};
    private int[] col = new int[]{0,0,-1,1};

    public List<String> findWords(char[][] board, String[] words) {

        //直接用 list 存,会出现 重复记录word 的情况。。。汗颜!
        //List<String> results = new ArrayList<String>();

        //改用 HashSet 暂存结果,确保不会出现重复word
        HashSet<String> temp = new HashSet<>();

        //前缀树
        for(int i=0;i<words.length;i++){
            TrieNode node = root;
            for(int j=0;j<words[i].length();j++)
                node = node.add(words[i].charAt(j));
            node.word = words[i];
        }
        //DFS
        boolean[][] visited = new boolean[board.length][board[0].length];
        for(int i=0;i<board.length;i++){
            for(int j=0;j<board[0].length;j++){
                if(root.ifExists(board[i][j])){
                    find(board,visited,i,j,root,temp);
                }
            }
        }

        List<String> results = new ArrayList<String>();
        results.addAll(temp);
        return results;
    }

    private void find(char[][] board,boolean[][] visited,int x,int y,TrieNode node,HashSet<String> temp){
        visited[x][y]=true;
        TrieNode cur = node.next[board[x][y]-'a'];
        //到达可匹配子串,记录当前 word
        if(cur.word!=null)
            temp.add(cur.word);
        for(int i=0;i<4;i++){
            int x2 = x + row[i];
            int y2 = y + col[i];
            if(x2>=0 && x2<board.length && y2 >=0 && y2 < board[0].length && !visited[x2][y2] ){
                if(cur.ifExists(board[x2][y2])){
                    find(board,visited,x2,y2,cur,temp);
                }
            }
        }
        visited[x][y] = false;
    }
    //前缀树
    class TrieNode{
        String word;
        TrieNode[] next = new TrieNode[26];
        TrieNode add(char chr){
            if(next[chr-'a'] != null) 
                return next[chr-'a'];
            next[chr-'a'] = new TrieNode();
            return next[chr-'a'];
        }

        boolean ifExists(char chr){
            return (next[chr - 'a']==null)?false:true;
        }
    }
}

7.有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词。

示例 1:

输入: s = "anagram", t = "nagaram"
输出: true

说明:
你可以假设字符串只包含小写字母。

进阶:
如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?

class Solution(object):
    def isAnagram(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        return sorted(s)==sorted(t)

8.字符串中的第一个唯一字符

给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。

案例:

s = "leetcode"
返回 0.

s = "loveleetcode",
返回 2.

注意事项:您可以假定该字符串只包含小写字母。

class Solution(object):
    def firstUniqChar(self, s):
        """
        :type s: str
        :rtype: int
        """
        dic=collections.Counter(s)#使用字典
        for i in range(len(s)):
            if dic[s[i]]==1:#如果字典中value为1
                return i
        return -1       

9.反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符

示例 1:输入:["h","e","l","l","o"] 输出:["o","l","l","e","h"]

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        head = 0
        rear = len(s) - 1
        while head < rear:
            s[head], s[rear] = s[rear], s[head]
            head += 1
            rear -= 1

猜你喜欢

转载自blog.csdn.net/yanyiting666/article/details/88980830