zoukankan      html  css  js  c++  java
  • 动态规划面试题

    一、简单DP

    礼物最大价值(矩阵贪心类题目)剑指 Offer 47

    class Solution {
    public:
        int maxValue(vector<vector<int>>& grid) {
            int m = grid.size(), n = grid[0].size();
            
            for(int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    if (i == 0 && j ==0) {
                        continue;
                    }
                    if (i == 0) {
                        grid[i][j] += grid[i][j - 1];
                    }
                    else if (j == 0) {
                        grid[i][j] += grid[i - 1][j];
                    }
                    else {
                        grid[i][j] += max(grid[i][j - 1], grid[i - 1][j]);
                    }
                }
            }
            return grid[m - 1][n - 1];
        }
    };
    

    时间复杂度 O(MN):M, N分别为矩阵行高、列宽;动态规划需遍历整个grid矩阵,使用 O(MN)时间。
    空间复杂度 O(1):原地修改使用常数大小的额外空间。

    爬楼梯 剑指 Offer 10- II.

    class Solution {
    public:
        int numWays(int n) {
            if (n == 0 || n == 1) 
            {
                return 1;    
            }
            if (n == 2)
            {
                return 2;
            }
            int a = 1, b = 2;
            int res = 0, MOD = 1000000007;
            for (int i = 3; i <= n; i++)
            {
                res = (a + b) % MOD;
                a = b;
                b = res;
            }
            return res ;
        }
    };
    

    时间复杂度O(n),空间复杂度O(1)

    二、字符串+DP

    编辑距离 leetcode 72

    class Solution {
    public:
        int minDistance(string word1, string word2) {
            int m = word1.length(), n = word2.length();
            if (m * n == 0) {
                return m + n;
            }
            int dp[m + 1][n + 1];
    
            for (int i = 0; i <= m; i++)
            {
                dp[i][0] = i;    // 当word2为空时, word1需要删掉i个字符
            }
            for (int j = 0; j <= n; j++)
            {
                dp[0][j] = j;
            }
            for (int i = 1; i <= m; ++i)
            {
                for (int j = 1; j <= n; ++j)
                {
                    int flag = (word1[i - 1] == word2[j - 1] ? 0 : 1);
                    dp[i][j] = min(dp[i - 1][j] + 1, min(dp[i][j - 1] + 1, dp[i - 1][j - 1] + flag));
                }
            }
            return dp[m][n];
        }
    };
    

    最长公共子序列 leetcode 1143

    class Solution {
    public:
        int longestCommonSubsequence(string text1, string text2) {
            int m = text1.length(), n = text2.length();
            if (m * n == 0) {
               return 0;
            }
            int dp[m + 1][n + 1];
            memset(dp, 0, sizeof(dp));
            // vector<vector<int> > dp(m + 1, vector<int>(n + 1, 0));
            
            for (int i = 1; i <= m; ++i)
            {
                for (int j = 1; j <= n; ++j)
                {
                    if(text1[i - 1] == text2[j - 1])
                    {
                        dp[i][j] = dp[i - 1][j - 1] + 1;
                    }
                    else
                    {
                        dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
                    }
                    
                }
            }
            return dp[m][n];
        }
    };
    

    最长回文字串 leetcode 5

    中心拓展算法

    class Solution {
    public:
        pair<int, int> expandAroundCenter(const string& s, int left, int right)
        {
            while (left >= 0 && right < s.size() && s[left] == s[right])
            {
                --left;
                ++right;
            }
            return {left + 1, right - 1};
        }
        string longestPalindrome(string s) {
            int slen = s.length();
            if (slen == 1) 
            {
                return s;
            }
            int start = 0, end = 0;
            for (int i = 0; i < s.size(); ++i)
            {
                auto [left1, right1] = expandAroundCenter(s, i, i);
                auto [left2, right2] = expandAroundCenter(s, i, i + 1);
                if (right1 - left1 > end - start)  // 相当于
                {
                    start = left1;
                    end = right1;
                }
                if (right2 - left2 > end - start)
                {
                    start = left2;
                    end = right2;
                }
            }
            return s.substr(start, end - start + 1);
        }
    };
    

    能看懂的写法

    class Solution {
    public:
        string longestPalindrome(string s) {
            int slen = s.length();
            if (slen == 1) 
            {
                return s;
            }
            
            int max_left = 0, max_right = -1;
            for (int i = 0; i < slen; ++i)
            {
                int left = i, right = i;
                while (left >= 0 && s[left] == s[i]) --left;
                while (right < slen && s[right] == s[i]) ++right;
                while (left >= 0 && right < slen && s[left] == s[right]) 
                {
                    --left; ++right;
                }
                if (max_right - max_left < right - left)
                {
                    max_left = left;
                    max_right = right;
                }
            }
            return s.substr(max_left + 1, max_right - max_left - 1);
        }
    };
    

    最长不重复子串 leetcode 3

    class Solution:
        def lengthOfLongestSubstring(self, s: str) -> int:
            occ = set()
            slen = len(s)
    
            # 右指针,初始值为-1,相当于我们在字符串的左边界的左侧,还没有开始移动
            rk, ans = -1, 0
            for i in range(slen):
                if i != 0:
                    # 左指针向右移动一格,移除一个字符
                    occ.remove(s[i - 1])
                while rk + 1 < slen and s[rk + 1] not in occ:
                    # 不断的移动右指针
                    occ.add(s[rk + 1])
                    rk += 1
                # 第 i 到 rk个字符是一个极长的无重复字符串子串
                ans = max(ans, rk - i + 1)
            return ans
    
  • 相关阅读:
    Celery最佳实践(转)
    我希望知道的关于Django的11件事(转)
    Celery和Rabbitmq自学
    我眼中的各种编程语言(转)
    linux 的nohup & 和daemon 总结(转)
    模糊测试之AVI文件分析
    微信Netting-QRLJacking分析利用-扫我二维码获取你的账号权限
    一个Unix内核级别漏洞(一)
    一次对SNMP服务的渗透测试
    定位日站大法之-社会工程学
  • 原文地址:https://www.cnblogs.com/douzujun/p/15207575.html
Copyright © 2011-2022 走看看