LeetCode算法面试题汇总之分割回文串

8 篇文章 0 订阅
1 篇文章 0 订阅

LeetCode算法面试题汇总

分割回文串
给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。

返回 s 所有可能的分割方案。

示例:

输入: "aab"
输出:

[
  ["aa","b"],
  ["a","a","b"]
]

在这里插入图片描述
这题用到了回溯法,之前学算法又学到,但是o(╥﹏╥)o,全忘了。一开始想,只要我吧所有的可能都给找出来一一判断是不是回文,但是从来没想过回溯(完全忘了),哎。

class Solution {
    List<List<String>> stulist=new ArrayList<List<String>>();
    List<String> listtemp= new ArrayList<String>();
    public List<List<String>> partition(String s) {
        if(s=="") return stulist;
        int len=s.length();
        dfs(s, len,0);
        return stulist;
    }
    public void dfs(String str,int strlength,int beginIndex){
        if(strlength==beginIndex) {
            stulist.add(new ArrayList<>(listtemp));
            return;
        }
        for(int endIndex=beginIndex;endIndex<strlength;endIndex++){
 //我发现如果你把代码块放在if里面,它的运行时间就会很高,改了之后从10ms,到了2ms
if(!isPalindrome(str,beginIndex,endIndex)){
              continue;
            }
            listtemp.add(str.substring(beginIndex,endIndex+1));
            dfs(str,strlength,endIndex+1);
            listtemp.remove(listtemp.size()-1);
        }
    }
    public boolean isPalindrome(String str,int left,int right){
        while (right>=left){
            if(str.charAt(right--)!=str.charAt(left++)){
                return false;
            }
        }
        return true;
    }
}

找了一个大佬的,感觉好复杂看不懂

class Solution {
    public List<List<String>> partition(String s) {
        List<List<String>> res = new ArrayList<>();
        int len = s.length();
        boolean[][] dp = new boolean[len][len];
        for(int i = 0; i < len; i++){
            prePro(s, i, i, dp);
            prePro(s, i, i + 1, dp);
        }
        helper(res, new ArrayList<>(), s, 0, dp);
        return res;
    }
	
    //进行预处理,利用中心扩展 将所有回文子串的位置存储到 dp 中
    private void prePro(String s, int left , int right, boolean[][] dp){
        while(left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)){
            dp[left][right] = true;
            left--;
            right++;
        }
    }
	
    private void helper(List<List<String>> res, List<String> list, String s, int index, boolean[][] dp){
        if(index == s.length()){
            res.add(new ArrayList<>(list));
            return;
        }
        for(int i = index; i < s.length(); i++){
            //利用预处理结果就不用再去判断该字符串是否是回文串
            if(!dp[index][i]){
                continue;
            }
            list.add(s.substring(index, i + 1));
            helper(res, list, s, i + 1, dp);
            list.remove(list.size() - 1);
        }
    }
}

后来我从新学了了一遍动态规划,发现我们的那个回溯法重复判断了很多东西,所以我又增加了一个数组来存储已经判断过的子串,这样就会减少调用isPalindrome()的次数,减少运行时间。但是这样所占用的内存就会变大,

   List<List<String>> stulist=new ArrayList<List<String>>();
    List<String> listtemp= new ArrayList<String>();
    int[][] is;
    public List<List<String>> partition(String s) {
        is=new int[s.length()][s.length()];
        if(s=="") return stulist;
        int len=s.length();
        dfs(s,len,0);
        return stulist;
    }
    public void dfs(String str,int strlength,int beginIndex){
        if(strlength==beginIndex) {
            stulist.add(new ArrayList<>(listtemp));
            return;
        }
        for(int endIndex=beginIndex;endIndex<strlength;endIndex++){
            if(is[beginIndex][endIndex]==0){
                if(!isPalindrome(str,beginIndex,endIndex))
                continue;
            }
            else if(is[beginIndex][endIndex]==1){
                continue;
            }
            listtemp.add(str.substring(beginIndex,endIndex+1));
            dfs(str,strlength,endIndex+1);
            listtemp.remove(listtemp.size()-1);

        }
    }
    public boolean isPalindrome(String str,int left,int right){
        int lefttemp=left;
        int righttemp=right;
        while (right>=left){
            if(str.charAt(right--)!=str.charAt(left++)){
                is[lefttemp][righttemp]=1;
                return false;
            }
        }
        is[lefttemp][righttemp]=2;
        return true;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值