1、單詞拆分
給定一個非空字符串 s 和一個包含非空單詞列表的字典 wordDict,判定 s 是否可以被空格拆分爲一個或多個在字典中出現的單詞。
說明:
拆分時可以重複使用字典中的單詞,
你可以假設字典中沒有重複的單詞
示例1
輸入: s = “leetcode”, wordDict = [“leet”, “code”]
輸出: true
解釋: 返回 true 因爲 “leetcode” 可以被拆分成 “leet code”。
示例2
輸入: s = “applepenapple”, wordDict = [“apple”, “pen”]
輸出: true
解釋: 返回 true 因爲 “applepenapple” 可以被拆分成 “apple pen apple”。
注意你可以重複使用字典中的單詞。
示例3
輸入: s = “catsandog”, wordDict = [“cats”, “dog”, “sand”, “and”, “cat”]
輸出: false
方法一:通過兩個下標對字符串進行控制,如果當前字符串s[j:i]存在於 wordDict 中,把右下標加到 temp 中,那麼下次就可以從 i 下標爲起點(左下標)來判斷字符串…這樣,temp 最後一個值一定就是字符串長度,否則就無法分割
def wordBreak(s, wordDict):
n = len(s)
temp = [0]
for i in range(n+1):
for j in temp:
if s[j:i] in wordDict:
temp.append(i)
break
return temp[-1] == n
方法二:利用 C++ 容器中 unordered_set 對字符串進行分割和查找
bool wordBreak(string s, vector<string>& wordDict) {
vector<bool>dp(s.size()+1,false);
unordered_set<string>m(wordDict.begin(),wordDict.end());
dp[0] = true;
for(int i = 0;i < s.size()+1;++i){
for(int j = 0;j<i;++j){
if(dp[j] && m.find(s.substr(j,i-j))!=m.end()){
dp[i] = true;
break;
}
}
}
return dp[s.size()];
}
進階:給定一個非空字符串 s 和一個包含非空單詞列表的字典 wordDict,在字符串中增加空格來構建一個句子,使得句子中所有的單詞都在詞典中。返回所有這些可能的句子
說明:
分隔時可以重複使用字典中的單詞。
你可以假設字典中沒有重複的單詞。
示例1
輸入:
s = “catsanddog”
wordDict = [“cat”, “cats”, “and”, “sand”, “dog”]
輸出:
[
“cats and dog”,
“cat sand dog”
]
示例2
輸入:
s = “pineapplepenapple”
wordDict = [“apple”, “pen”, “applepen”, “pine”, “pineapple”]
輸出:
[
“pine apple pen apple”,
“pineapple pen apple”,
“pine applepen apple”
]
解釋: 注意你可以重複使用字典中的單詞。
示例3
輸入:
s = “catsandog”
wordDict = [“cats”, “dog”, “sand”, “and”, “cat”]
輸出:
[]
先判斷是否可以分割,然後進行回溯,有一定的難度
class Solution {
public:
// 判斷是否可以分割
bool wordBreak2(string s, vector<string>& wordDict) {
vector<bool>dp(s.size()+1,false);
unordered_set<string>m(wordDict.begin(),wordDict.end());
dp[0] = true;
for(int i = 0;i < s.size()+1;++i){
for(int j = 0;j<i;++j){
if(dp[j] && m.find(s.substr(j,i-j))!=m.end()){
dp[i] = true;
break;
}
}
}
return dp[s.size()];
}
// 進行回溯
void helper(string s, int l, int r){
if(l>r){
string str;
for(int i=0; i<path.size()-1; i++)
str = str + path[i] + " ";
str += path.back();
ans.push_back(str);
return ;
}
// i是截取字符串的長度
for(int i=1; i<=r-l+1; i++){
string tmp = s.substr(l, i);
if(sstr.find(tmp) != sstr.end()){
path.push_back(tmp);
helper(s, l+i, r);
path.pop_back();
}
}
}
vector<string> wordBreak(string s, vector<string>& wordDict) {
if(!wordBreak2(s, wordDict)){
return ans;
}
sstr = unordered_set<string>(wordDict.begin(), wordDict.end());
helper(s, 0, s.size()-1);
return ans;
}
private:
unordered_set<string>sstr;
vector<string>ans;
vector<string>path;
};
2、最大子序列之和
給定一個整數數組 nums ,找到一個具有最大和的連續子數組(子數組最少包含一個元素),返回其最大和
示例
輸入: [-2,1,-3,4,-1,2,1,-5,4],
輸出: 6
解釋: 連續子數組 [4,-1,2,1] 的和最大,爲 6
動態規劃解題:temp [i]表示到第i爲時由第i個數爲序列最後一個數時的最大和,若temp [i-1]>0,果斷連起來,加 temp[i];反之,以當前數位序列的第一個數;每一位時都記錄到目前爲止最大的子序列和。
C++ 參考代碼
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.empty()) return 0;
int n = nums.size();
vector<int>dp(n,0);
dp[0] = nums[0];
int ans = dp[0];
for(int i = 1;i<n;++i){
// 如果前 i 和數字之和大於0,則加當前元素
if(dp[i-1]>0){
dp[i] = dp[i-1]+nums[i];
}else{
// 如果小於0則把當前元素賦值給dp
dp[i] = nums[i];
}
ans = max(ans,dp[i]);
}
return ans;
}
};
方法二:可以不保存前 i 個元素之和,直接進行當前元素與最大值的判斷,並且時刻更新最大值,最後返回,空間複雜度爲O(1)
C++ 參考代碼
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.empty()) return 0;
int n = nums.size();
int temp = nums[0];
int ans = temp;
for(int i = 1;i<n;++i){
if(temp > 0){
temp += nums[i];
}else{
temp = nums[i];
}
ans = max(ans,temp);
}
return ans;
}
};
3、最長有效括號
給定一個只包含 ‘(’ 和 ‘)’ 的字符串,找出最長的包含有效括號的子串的長度。
示例1
輸入: “(()”
輸出: 2
解釋: 最長有效括號子串爲 “()”
示例2
輸入: “)()())”
輸出: 4
解釋: 最長有效括號子串爲 “()()”
思路:dp[i]表示以第i個字符結尾的有效括號的最長長度
對於( )(( ))
i=4: dp = [0,2,0,0,2,0]
i=5: dp = [0,2,0,0,2,6]
dp[5] = 2 + dp[5-dp[5-1]-2]
解釋:dp[i] 和dp[i-1]有關,還和dp[i-dp[i-1]-2]有關,沒有第5位的‘)’時, 第2位的‘(’把0-4的字串分成了兩端有效括號,但有了第5位的‘)’時,激活了這兩段之間的連接,使之形成一整段有效括號
當s[i] == ‘(’:dp[i] = 0
當s[i] == ‘)’,並能找到前半個‘(’:
狀態轉移方程:dp[i] = dp[i-dp[i-1]-2] + 2+ dp[i-1]
def longestValidParentheses(self, s):
max_len = 0
len_s = len(s)
dp = [0]*len_s
for i in range(1,len_s):
if s[i] ==')':
if i-dp[i-1]-1>=0 and s[i-dp[i-1]-1]=='(':
dp[i] = dp[i-dp[i-1]-2] + 2+ dp[i-1]
max_len = max(max_len, dp[i])
return max_len