恋上数据结构与算法第三季百度、阿里、腾讯等面试题02

1._121_买卖股票的最佳时机

标签:数组、动态规划

思路:1.一个变量记录前面扫描过的最小值,一个变量记录目前交易中最大的收益金额。

           从头至尾扫描一遍数组,如果当前的值 < 已扫描过的最小值,更新最小值;收益 = Math.max(maxProfit,prices[i] - minPrice);

代码:

    public int maxProfit(int[] prices) {
        int minPrice = prices[0];
        int maxProfit = 0;
        for(int i = 1;i < prices.length;i++){
            if(prices[i] < minPrice){
                minPrice = prices[i];
            }
            maxProfit = Math.max(maxProfit,prices[i] - minPrice);
        }
        return maxProfit;
    }

思路2:动态规划解法

             dp[i][j]表示第i天买入,第j天卖出的利润。

2._72_编辑距离

标签:动态规划

思路:设字符串s1长度为n1,字符串s2长度为n2,设置一个dp[n1+1][n2+1]数组。

           dp[i][j]是s1[0,i)转化成s2[0,j)的最少操作数

           初始状态:dp[0][0] = 0;

                             dp[0,i]表示s1空串转换成s2[0,i)的最少操作数,即s2的长度

                             dp[i,0]表示s1[0,i)转换成s2空串的最少操作数,即s2的长度

           将一个字符串转换成另一个字符串共有三种操作(删除、添加、替换),dp[i][j]可能有以下情况:

           1)dp[i][j] = dp[i - 1][j] +1;

           2)dp[i][j] = dp[i][j - 1] + 1;

           3)  若s1[i - 1] = s2[j - 1]: dp[i][j] = dp[i-1][j-1]

                 s1[i - 1] != s2[j - 1] :dp[i][j] = dp[i-1][j-1] + 1;

 代码:

  public int minDistance(String word1, String word2) {
        char[] s1 = word1.toCharArray();
        char[] s2 = word2.toCharArray();
        int[][] dp = new int[s1.length + 1][s2.length + 1];
        dp[0][0] = 0;
        for(int i = 1;i <= s1.length;i++){
            dp[i][0] = i;
        }
        for(int j = 1;j <= s2.length;j++){
            dp[0][j] = j;
        }
        for(int i = 1;i <= s1.length;i++){
            for(int j = 1;j <= s2.length;j++){
                int top = dp[i - 1][j] + 1;
                int left = dp[i][j - 1] + 1;
                int leftTop;
                if(s1[i - 1] == s2[j - 1]){
                    leftTop = dp[i - 1][j - 1] ;
                }else{
                    leftTop = dp[i - 1][j - 1] + 1;
                }

                dp[i][j] = Math.min(Math.min(top,left),leftTop);
            }
        }
        return dp[s1.length][s2.length];

    }

3._5_最长回文子串

标签:字符串、动态规划

思路1:采用动态规划的思想,设置dp数组,dp[i][j]表示s[i][j]是否为回文串,dp数组存储true或false;

分两种情况讨论:

1)s[i,j]的长度 <=2,即s[i,i]或是s[i,i+1]这种情况,如果s[i]==s[j],那么s[i,j]是回文串,dp[i][j] = true;

2)  s[i][j]的长度 > 2,如果s[i+1,j-1]是回文串,且s[i] == s[j] ,dp[i][j]才为true.

     在存储true时,需要记录回文子串长度的最大值,且需要记录最大值的起始索引。

代码:

    public String longestPalindrome(String s) {
       char[] cs = s.toCharArray();
        boolean[][] dp = new boolean[cs.length][cs.length];
        int maxLength = 1;
        int begin = 0;
        for(int i = cs.length - 1;i >= 0 ;i--){
            for(int j = i;j < cs.length;j++){
                int len = j - i + 1;
                dp[i][j] = (cs[i] == cs[j] && (len <= 2 || dp[i +1][j - 1]));
                if(dp[i][j] && len > maxLength){
                    maxLength = len;
                    begin = i;
                }
            }
        }

        return s.substring(begin,begin + maxLength);

    }

时间复杂度:O(n²)       空间复杂度 :O(n²)

思路2:扩展中心法

             以每个字符每个间隙为中心,向左右扩展

代码:

    public String longestPalindromeEX(String s) {
        char[] cs = s.toCharArray();
        if(cs.length <= 1) return s;
        int maxLength = 1;
//        最长回文子串的开始索引
        int begin = 0;

        for(int i = cs.length - 2;i >= 1;i--){
//            以字符为中心向左右扩展
            int len1 = palindromeLength(cs,i -1,i + 1);
//            以字符右边的间隙为中心向左右扩展
            int len2 = palindromeLength(cs,i,i + 1);
            len1 = Math.max(len1,len2);
            if(len1 > maxLength){
                maxLength = len1;
                begin = i - ((maxLength -1) >> 1);
            }
        }
//        以0号字符右边的间隙为中心的最长回文子长度是2
        if(cs[0] == cs[1] && maxLength < 2){
            maxLength = 2;
            begin = 0;
        }
        return s.substring(begin,begin + maxLength);

    }

    /**
     * 只需传入左开始索引和右开始索引,向左向右延申。
     */
    private int palindromeLength(char[] cs,int l,int r){
        while(l >= 0 && r < cs.length && cs[l] == cs[r]){
            l--;
            r++;
        }
        return r - l - 1;

    }

时间复杂度:O(n²)       空间复杂度 :O(1 )

扩展中心法的优化:

思路:

 

代码:

    public String longestPalindromeEX_B(String s) {
        char[] cs = s.toCharArray();
        if(cs.length <= 1) return s;
        int maxLength = 1;
//        最长回文子串的开始索引
        int begin = 0;
        int i = 0;

        while(i < cs.length ){
            int l = i - 1;
            int r = i;
            //找到右边第一个不等于cs[i]的位置
            while(++r < cs.length && cs[r] == cs[i]);
            //r作为下一次的i
            i = r;
            //从l向左,从r向右扩展
            while(l >= 0 && r < cs.length && cs[l]==cs[r]){
                l--;
                r++;
            }
            //扩展结束后,cs[l + 1,r)就是找到的最大回文子串
            //++l后是找到的最大回文子串的开始索引
            int len = r - ++l;
            if(len > maxLength){
                maxLength = len;
                begin = l;
            }

        }

        return s.substring(begin,begin + maxLength);

    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值