@@ -30,79 +30,57 @@ static void Main(string[] args)
30
30
//int[] nums2 = new int[] { 10, 15, 20 };
31
31
//string input = "abc";
32
32
//string input2 = "ahbgdc";
33
- IList < IList < int > > triangle = new List < IList < int > > ( ) ;
34
- triangle . Add ( new List < int > ( ) { 2 } ) ;
35
- triangle . Add ( new List < int > ( ) { 3 , 4 } ) ;
36
- triangle . Add ( new List < int > ( ) { 6 , 5 , 7 } ) ;
37
- triangle . Add ( new List < int > ( ) { 4 , 1 , 8 , 3 } ) ;
38
- var res = solution . MinimumTotal ( triangle ) ;
33
+ //string s = "leetcode";
34
+ //IList<string> wordDict = new List<string>() { "leet", "code" };
35
+ //string s = "applepenapple";
36
+ //IList<string> wordDict = new List<string>() { "apple", "pen" };
37
+ string s = "catsandog" ;
38
+ IList < string > wordDict = new List < string > ( ) { "cats" , "dog" , "sand" , "and" , "cat" } ;
39
+
40
+ var res = solution . WordBreak ( s , wordDict ) ;
39
41
ConsoleX . WriteLine ( res ) ;
40
42
}
41
43
}
42
44
43
- /// <summary>
44
- /// Experience:在解决问题时试试思考反向的逻辑,普通思维的从前往后,那就从后往前想想;普通思维的自上而下,那就从下而上想想;或许能获得更好的解法。
45
- /// </summary>
46
-
47
45
public class Solution
48
46
{
49
47
/// <summary>
50
- /// 动态规划,优化做法,自下而上。逻辑清晰,减少了边界判断,减小了使用空间。
51
- /// 时间复杂度:O(n² )
52
- /// 空间复杂度:O(n),确切地说就是 n
48
+ /// 第一反应解,递归,然而超时
49
+ /// 时间复杂度:O(真不知道怎么算 OTL )
50
+ /// 空间复杂度:O(真不知道怎么算 OTL )
53
51
/// </summary>
54
- /// <param name="triangle"></param>
52
+ /// <param name="s"></param>
53
+ /// <param name="wordDict"></param>
55
54
/// <returns></returns>
56
- public int MinimumTotal ( IList < IList < int > > triangle )
55
+ public bool WordBreak ( string s , IList < string > wordDict )
57
56
{
58
- if ( triangle == null || triangle . Count == 0 )
59
- return 0 ;
60
-
61
- int [ ] dp = triangle [ triangle . Count - 1 ] . ToArray ( ) ;
62
- for ( int i = triangle . Count - 2 ; i >= 0 ; i -- )
63
- {
64
- for ( int j = 0 ; j <= i ; j ++ )
65
- {
66
- dp [ j ] = Math . Min ( dp [ j ] , dp [ j + 1 ] ) + triangle [ i ] [ j ] ;
67
- }
68
- }
69
- return dp [ 0 ] ;
57
+ _dic = new HashSet < string > ( wordDict ) ;
58
+ _maxWordLength = wordDict . Count != 0 ? wordDict . Max ( t => t . Length ) : 0 ;
59
+ Recurse ( s ) ;
60
+ return _res ;
70
61
}
71
62
72
- /// <summary>
73
- /// 动态规划,使用 2n 空间来存 dp 结果,计算完成再放到preDp中
74
- /// 时间复杂度:O(n²)
75
- /// 空间复杂度:O(n),确切的说是 2n
76
- /// 这里逻辑惯性使用了自顶向下的解决办法,这种方法需要对两边的边界做特判。而自下而上的办法就可以不特判,而且还可以只是用 n 的空间
77
- /// </summary>
78
- /// <param name="triangle"></param>
79
- /// <returns></returns>
80
- //public int MinimumTotal(IList<IList<int>> triangle)
81
- //{
82
- // if (triangle == null || triangle.Count == 0)
83
- // return 0;
63
+ private HashSet < string > _dic ;
64
+ private bool _res ;
65
+ private int _maxWordLength ;
84
66
85
- // int[] preDp = new int[triangle.Count];
86
- // int[] dp = new int[triangle.Count];
87
- // for (int i = 0; i < triangle.Count; i++)
88
- // {
89
- // var row = triangle[i];
90
- // for (int j = 0; j <= i; j++)
91
- // {
92
- // //自顶而下的边界特判
93
- // int leftParent = j > 0 ? preDp[j - 1] : int.MaxValue;
94
- // int rightParent = j == i ? int.MaxValue : preDp[j];
95
- // if (leftParent == int.MaxValue && rightParent == int.MaxValue)
96
- // dp[j] = row[j];
97
- // else
98
- // dp[j] = Math.Min(leftParent, rightParent) + row[j];
99
- // }
100
- // //不能单纯的赋值,引用类型
101
- // preDp = dp.ToArray();
102
- // }
67
+ private void Recurse ( string str )
68
+ {
69
+ if ( _res )
70
+ return ;
71
+
72
+ if ( _dic . Contains ( str ) )
73
+ {
74
+ _res = true ;
75
+ return ;
76
+ }
103
77
104
- // return dp.Min();
105
- //}
78
+ for ( int i = 0 ; i < str . Length && i < _maxWordLength ; i ++ )
79
+ {
80
+ if ( _dic . Contains ( str . Substring ( 0 , i + 1 ) ) )
81
+ Recurse ( str . Substring ( i + 1 ) ) ;
82
+ }
83
+ }
106
84
}
107
85
}
108
86
}
0 commit comments