每日刷题记录 (二十六)

x33g5p2x  于2022-07-20 转载在 其他  
字(4.0k)|赞(0)|评价(0)|浏览(251)

第一题: 290. 单词规律

LeetCode: 290. 单词规律

描述:
给定一种规律 pattern 和一个字符串 s ,判断 s 是否遵循相同的规律。

这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接的对应规律。

解题思路:

  1. 这里使用哈希表解题.
  2. 首先将 s 字符串转成字符串数组.
  3. 如果 此时字符串数组的长度和 pattern 长度不一样, 直接返回false
  4. 如果当前哈希表中不存在 pattern.charAt(i) 的元素, 首先去判断, 对应的 value值是否重复出现. 如果重复出现了, 就返回false. 没有重复出现就 直接添加到 哈希表中.
  5. 如果当前哈希表中存在 pattern.charAt(i) 的元素, 就去查看对应的 value 值是否和当前的 str[i] 是否相等, 相等就表示对应有规律. 否则返回 false

代码实现:

class Solution {
    public boolean wordPattern(String pattern, String s) {
        String[] str = s.split(" ");
        if(pattern.length() != str.length) return false;
        Map<Character,String> map = new HashMap<>();
        for(int i = 0;i < str.length ;i++){
            if(!map.containsKey(pattern.charAt(i))) {
                if(map.containsValue(str[i])){
                    return false;
                }else{
                    map.put(pattern.charAt(i),str[i]);
                }
            }
        }
        for(int i = 0; i < str.length; i++) {
            if(!map.get(pattern.charAt(i)).equals(str[i])){
                return false;
            }
        }
        return true;
    }
}

第二题: 402. 移掉 K 位数字

LeetCode: 402. 移掉 K 位数字

描述:
给你一个以字符串表示的非负整数 num 和一个整数 k ,移除这个数中的 k 位数字,使得剩下的数字最小。请你以字符串形式返回这个最小的数字。

解题思路:

  1. 这里首先对当前 num 字符串进行判断, 如果k和字符串长度相等 返回"0"
  2. 使用一个辅助栈来解题.
  3. 如果当前对应的数字, 要大于栈顶元素, 就直接出栈.
  4. 否则, 查看当前的数字是否为0, 如果为0, 且 栈不为空就入栈,
  5. 当前数组不为0 就直接入栈.
  6. 遍历一次之后 查看k是否为空, 也就是出栈的次数是否为k次.
  7. 此时k不为空 再次出栈.
  8. 如果此时栈为空了, 就返回 “0”
  9. 栈不为空就进行字符串的拼接.

代码实现:

class Solution {
    public String removeKdigits(String num, int k) {
        if(k == num.length()) return "0";
        Stack<Integer> stack = new Stack<>();
        for(int i = 0; i < num.length(); i++) {
            int tmp = num.charAt(i) -'0';
            while(k != 0 && !stack.isEmpty() && stack.peek() > tmp) {
                stack.pop();
                k--;
            }
            if(tmp != 0 || !stack.isEmpty()) {
                stack.push(tmp);
            }
        }
        while(k != 0 && !stack.isEmpty()) {
            stack.pop();
            k--;
        }
        if(stack.isEmpty()) return "0";
        StringBuilder res = new StringBuilder();
        while(!stack.isEmpty()) {
            res.append(stack.pop());
        } 
        return res.reverse().toString();
    }
}

第三题: 409. 最长回文串

LeetCode: 409. 最长回文串

描述:
给定一个包含大写字母和小写字母的字符串 s ,返回 通过这些字母构造成的 最长的回文串

在构造过程中,请注意 区分大小写 。比如 “Aa” 不能当做一个回文字符串。

解题思路:

  1. 首先使用哈希表记录每个字符出现的次数.
  2. 如果一个字符出现了偶数次, 直接将这个字符出现的次数添加到结果集中.
  3. 如果一个字符出现了奇数次, 要添加这个次数-1次. 例如 aaa, 出现了3次, 但可以利用他的偶次, 3-1=2.
  4. 遍历结束, 如果有出现奇数的情况, 那么就要+1, 例如你记录了aaa, 只记录了偶次的情况, 结束之后, 还能再添加一次a

代码实现:

class Solution {
    public int longestPalindrome(String s) {
        Map<Character,Integer> map = new HashMap<>();
        for(char ch : s.toCharArray()) {
            map.put(ch,map.getOrDefault(ch,0)+1);
        }
        int count = 0;
        int ret = 0;
        for(Map.Entry<Character,Integer> entry : map.entrySet()) {
            if(entry.getValue() % 2 == 0) {
                count += entry.getValue();
            }else{
                count += entry.getValue()-1;
                ret = 1;
            }
        }
        return count + ret;
    }
}

第四题: 459. 重复的子字符串

LeetCode: 459. 重复的子字符串

描述:
给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

解题思路:

  1. 这里是否可以重构可以理解为, 把左边字符往右边移动, 是否可以变为原字符.
  2. 例如 abab, 第一次移动为 baba, 第二次移动为 abab, 第三次移动为 baba.
  3. 这里可以让字符串 s 拼接两次, 然后去掉首尾, 再去查找 是否存在 s

代码实现:

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        String str = s + s;
        return str.substring(1,str.length()-1).contains(s);
    }
}

第五题: 516. 最长回文子序列

LeetCode: 516. 最长回文子序列

描述:
给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。

子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

解题思路:

  1. 这里使用动态规划解题.
  2. 状态 F(i,j) : 表示 i ~ j 最长回文子序列的长度.
  • 状态转移方程:

  • F(i,j) = F(i+1)(j-1) + 2 (s[i] = s[j])

  • F(i,j) = Math.max(F(i+1)(j),F(i)(j-1)) (s[i] != s[j])

  • 初始状态: F(i,i) = 1

  • 返回结果: F(0,len-1)
     
    由于可以删除某些字符, 所有如果s[i] != s[j] 的时候, 就可以多算一个字符了.

代码实现:

class Solution {
    public int longestPalindromeSubseq(String s) {
        int[][] dp = new int[s.length()][s.length()];
        for(int i = 0; i < s.length(); i++){
            dp[i][i] = 1;
        }
        for(int i = s.length()-2; i >= 0; i--) {
            for(int j = i+1; j < s.length(); j++){
                if(s.charAt(i) == s.charAt(j)) {
                    dp[i][j] = dp[i+1][j-1] + 2;
                }else{
                    dp[i][j] = Math.max(dp[i+1][j],dp[i][j-1]);
                }
            }
        }
        return dp[0][s.length()-1];
    }
}

第六题: 520. 检测大写字母

LeetCode: 520. 检测大写字母

描述:
我们定义,在以下情况时,单词的大写用法是正确的:

  • 全部字母都是大写,比如 “USA” 。
  • 单词中所有字母都不是大写,比如 “leetcode” 。
  • 如果单词不只含有一个字母,只有首字母大写, 比如 “Google” 。

给你一个字符串 word 。如果大写用法正确,返回 true ;否则,返回 false 。

解题思路:

  1. 使用 upCount 记录大写字母出现的次数.
  2. 使用 lowCount 记录小写字母出现的次数.
  3. 遍历字符串,
  4. 如果 upCount == word,length() , 那么就满足条件1.
  5. 如果 lowCount == word.length(), 那么就满足条件2.
  6. 如果upCount == 1 && word.charAt(0)为大写, 那么就满足条件3.
  7. 不满足这3个 就返回false

代码实现:

class Solution {
    public boolean detectCapitalUse(String word) {
        int upCount = 0;
        int lowCount = 0;
        for(char ch : word.toCharArray()){
            if(ch>='a' && ch<='z') {
                lowCount++;
            }else{
                upCount++;
            }
        }
        if(lowCount == word.length()) {
            return true;
        }
        if(upCount == word.length()) {
            return true;
        }
        if(upCount == 1 && word.charAt(0) >= 'A' && word.charAt(0) <= 'Z'){
            return true;
        }
        return false;
    }
}

相关文章