classSolution { public: intuniquePaths(int m, int n){ vector<vector<int>> dp(m, vector<int>(n)); for (int i = 0; i < m; ++i) dp[i][0] = 1; for (int i = 0; i < n; ++i) dp[0][i] = 1; for (int i = 1; i < m; ++i) for (int j = 1; j < n; ++j) dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; return dp[m - 1][n - 1]; } };
// 空间优化 classSolution { public: intuniquePaths(int m, int n){ vector<int> dp(n); dp[0] = 1; for (int i = 0; i < m; ++i) for (int j = 1; j < n; ++j) dp[j] = dp[j] + dp[j - 1]; return dp[n - 1]; } };
2. 组合数学
对于一个m∗n的二维数组,本质上有m−1次向下移动和n−1次向右移动,因此属于排列组合
1 2 3 4 5 6 7 8 9
classSolution { public: intuniquePaths(int m, int n){ longlong result = 1; for (int x = n, y = 1; y < m; ++x, ++y) result = result * x / y; returnstatic_cast<int>(result); } };
classSolution { public: string longestPalindrome(string s){ int len = s.size(); vector<vector<int>> dp(len, vector<int>(len)); if (len < 2) return s; for (int i = 0; i < len; ++i) dp[i][i] = true; int maxLen = 1; int begin = 0; for (int l = 2; l <= len; ++l) { for (int i = 0; i < len; ++i) { int right = l + i - 1; if (right >= len) break; if (s[i] != s[right]) dp[i][right] = false; else { if (right - i < 3) dp[i][right] = true; else { dp[i][right] = dp[i + 1][right - 1]; } } if (dp[i][right] && right - i + 1 > maxLen) { maxLen = right - i + 1; begin = i; } } } return s.substr(begin, maxLen); } };
classSolution { public: int len; string longestPalindrome(string s){ len = s.size(); int begin = 0; int end = 0; for (int i = 0; i < len; ++i) { auto [left1, right1] = Expand(s, i, i); auto [left2, right2] = Expand(s, i, i + 1); if (right1 - left1 > end - begin) { begin = left1; end = right1; } if (right2 - left2 > end - begin) { begin = left2; end = right2; } } return s.substr(begin, end - begin + 1); } pair<int, int> Expand(string& s, int left, int right) { while (left >= 0 && right < len && s[left] == s[right]) { --left; ++right; } return {left + 1, right - 1}; } };
classSolution { public: string longestPalindrome(string s){ int begin = 0; int end = -1; // 取-1为了下面正确的判断,从而使单个字符能够满足条件 string temp = "#"; for (auto& ch : s) { temp += ch; temp += '#'; } s = temp; int len = s.size(); vector<int> arm; int right = -1, cur = -1; for (int i = 0; i < len; ++i) { int curArm; if (right >= i) { int isysm = 2 * cur - i; int minArm = min(arm[isysm], right - i); curArm = Expand(s, i - minArm, i + minArm); } else { curArm = Expand(s, i, i); } arm.emplace_back(curArm); if (i + curArm > right) { cur = i; right = i + curArm; } if (curArm * 2 + 1 > end - begin) { begin = i - curArm; end = i + curArm; } } string result; for (int i = begin; i <= end; ++i) if (s[i] != '#') result += s[i]; return result; } intExpand(string& s, int left, int right) { while (left >= 0 && right < s.size() && s[left] == s[right]) { --left; ++right; } return (right - left - 2) >> 1; } };