leetcode刷题总结

leetcode算法总结

最长回文子串

44. 通配符匹配

给定一个字符串 (s) 和一个字符模式 § ,实现一个支持 ‘?’ 和 ‘*’ 的通配符匹配。

‘?’ 可以匹配任何单个字符。
‘*’ 可以匹配任意字符串(包括空字符串)。

解题思路;
1、想到用双指针,但是不好判断*到底匹配多少个字符串,放弃
2、跟前面第十题一样用递归????(搞不清楚什么情况下该用递归)
3、动态规划

  • 状态 dp[i][j] : 表示 s 的前 i 个字符和 p 的前 j 个字符是否匹配 (true 的话表示匹配)
  • 状态转移方程:
    • 当 s[I-1] == p[j-1],或者 p[j] == ? 那么 dp[i][j] = dp[i - 1][j - 1];
    • 当 p[j-1] == * 那么 dp[i][j] = dp[i][j - 1] || dp[i - 1][j] 其中:
      dp[i][j - 1] 表示 * 代表的是空字符,例如 ab, ab*
      dp[i - 1][j] 表示 * 代表的是非空字符,例如 abcd, ab*
  • 初始化:
    • dp[0][0] 表示什么都没有,其值为 true
    • 第一行 dp[0][j],换句话说,s 为空,与 p 匹配,所以只要 p 开始为 * 才为 true
    • 第一列 dp[i][0],当然全部为 false
for(int i=1;i<=n;i++)
        {
            if(c2[i-1]=='*'&&dp[0][i-1])
            {
                dp[0][i]=true;
            }

        }

相似题目:

10. 正则表达式匹配

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。

‘.’ 匹配任意单个字符
‘*’ 匹配零个或多个前面的那一个元素

思路:可以用递归,时间复杂度太高。
用动态规划,跟上题一样

  • 状态: dp[i][j] : 表示 s 的前 i 个字符和 p 的前 j 个字符是否匹配 (true 的话表示匹配)
  • 状态转移方程:
    • 当 s[I-1] == p[j-1],或者 p[j] =. 那么 dp[i][j] = dp[i - 1][j - 1];
    • p[j-1] == *,还要看s[I-1]和p[j-2],相不相等
      • 如果不等,dp[i][j] = dp[i ][j - 2];
      • 如果相等或者p[j-2]=.
        1、匹配0个 dp[i ][j - 2]
        2、匹配一个 dp[i ][j -1]
        3、匹配多个 dp[i -1][j]
    • 初始化:跟上面那题还不一样,偶数位上为“”,都能匹配上s为空,p为abc的时候,dp[i][j]为ftftft
for (int i = 2; i <= n; i+= 2) {
            if (p.charAt(i - 1) == '*') {
                dp[0][i] = dp[0][i - 2];
            }
        }

完整代码:

class Solution {
    public boolean isMatch(String s, String p) {
        int m=s.length(),n=p.length();
        char[] c1=s.toCharArray();
        char[] c2=p.toCharArray();
        boolean dp[][]=new boolean[m+1][n+1];
        //初始化 .*.* .**** 
        dp[0][0]=true;
        for (int i = 2; i <= n; i+= 2) {
            if (c2[i - 1] == '*') {
                dp[0][i] = dp[0][i - 2];
            }
        }

        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(c1[i-1]==c2[j-1]||c2[j-1]=='.')
                {
                    dp[i][j]=dp[i-1][j-1];
                }
                else if(c2[j-1]=='*')
                {
                    if(c1[i-1]!=c2[j-2]&&c2[j-2]!='.')
                    {
                        dp[i][j]=dp[i][j-2];
                    }
                    else if(c1[i-1]==c2[j-2]||c2[j-2]=='.')
                    {
                    dp[i][j]=dp[i][j-2]||dp[i][j-1]||dp[i-1][j];
                    }
                }
            }
        }
        return dp[m][n];

    }
}


48.旋转图像

给定一个 n × n 的二维矩阵表示一个图像。将图像顺时针旋转 90 度。

**思路:**先按照主对角线对称,然后再按中轴列互换就可以实现顺时针旋转90度。

49.字母异位词分组

给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

思路

1、把字符串的字母一致的分成一组,用 hashmap来存,key是同一个字符串,value是字母异位词。
怎么看是否是同一个字符串呢,先排序,排序相同的就是同一个字符串。
时间复杂度:O(nKlog(K)),klogk是排序的时间复杂度。

2、这个时间复杂度可以降为k,用一个长度为26数组来存放字符串中字符出现的次数,然后再转换为key,异位词的key是相同的。 
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        if (strs.length == 0) return new ArrayList();
        Map<String, List> ans = new HashMap<String, List>();
        for (String s : strs) {
            char[] ca = s.toCharArray();
            Arrays.sort(ca);
            String key = String.valueOf(ca);
            //如果没有key,创建一个key, new ArrayList()
            if (!ans.containsKey(key)) ans.put(key, new ArrayList());
            //然后再往里面add进s
            ans.get(key).add(s);
        }
        //可以不写<>,直接获取到map.values()
        return new ArrayList(ans.values());
    }
}

50. Pow(x, n)

实现 pow(x, n) ,即计算 x 的 n 次幂函数。

**思路:**直接用for循环的话,会超时,那么就想到用递归,一半一半的成。
2的10次方,每次都分半,n/2,10-5-2-1,时间复杂度从O(n)到O(log(n)),n为奇数的时候,还要再乘上一个x。

注意:int的范围是-2147483648到2147483647。
Math.abs(-2147483648)等于-2147483648!!!!!!
int型的-2147483648乘以-1还是等于-2147483648!!!!!
所以要先转成long型。

55. 跳跃游戏

给定一个非负整数数组,你最初位于数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个位置。

**思路:**这道题不能用递归,会超时。

维护了一个最大跳跃值,每次判断当前位置是否大于最大跳跃值,如果大于,就表示不能跳过去。最大跳跃值:k=Math.max(k,i+nums[i])

54. 螺旋矩阵

给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
思路:控制左l右r,上u下d边界:
1、向左:for(int i=l;i<=r;++i),上边界u+1,再判断上下边界是否越界
2、向下:for(int i=u;i<=d;++i),右边界-1,再判断左右边界。

61. 旋转链表
给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。
思路:找到倒数第k个节点,然后把前面的第k个节点链接到后面。
终于没看题解就做出来了。。。。。

你可能感兴趣的:(算法题)