diff --git a/DataStructureAndAlgorithm/11 Leetcode同步练习(四).md b/DataStructureAndAlgorithm/11 Leetcode同步练习(四).md new file mode 100644 index 0000000..ea8c0c7 --- /dev/null +++ b/DataStructureAndAlgorithm/11 Leetcode同步练习(四).md @@ -0,0 +1,1176 @@ +# Leetcodeͬϰģ + +## Ŀ01Сջ + +> - ţ155 +> - Ѷȣ +> - https://leetcode-cn.com/problems/min-stack/ + +һ֧ pushpoptop ڳʱڼСԪصջ + +- push(x) -- Ԫ x ջС +- pop() -- ɾջԪء +- top() -- ȡջԪء +- getMin() -- ջеСԪء + +ʾ: + +```c +MinStack minStack = new MinStack(); +minStack.push(-2); +minStack.push(0); +minStack.push(-3); +minStack.getMin(); --> -3. +minStack.pop(); +minStack.top(); --> 0. +minStack.getMin(); --> -2. +``` + +**˼·**øջķʽ + +**ο** + +- ״̬ͨ +- ִʱ: 192 ms, C# ύл 96.43% û +- ڴ: 33.5 MB, C# ύл 13.63% û + +```c +public class MinStack +{ + /** initialize your data structure here. */ + private readonly Stack _stack; + private readonly Stack _stackMin; + + public MinStack() + { + _stack = new Stack(); + _stackMin = new Stack(); + } + + public void Push(int x) + { + _stack.Push(x); + if (_stackMin.Count == 0 || _stackMin.Peek() >= x) + { + _stackMin.Push(x); + } + } + + public void Pop() + { + int x = _stack.Pop(); + if (_stackMin.Peek() == x) + { + _stackMin.Pop(); + } + } + + public int Top() + { + return _stack.Peek(); + } + + public int GetMin() + { + return _stackMin.Peek(); + } +} + +/** + * Your MinStack object will be instantiated and called as such: + * MinStack obj = new MinStack(); + * obj.Push(x); + * obj.Pop(); + * int param_3 = obj.Top(); + * int param_4 = obj.GetMin(); + */ +``` + + + + +--- +## Ŀ02Ч + +> - ţ20 +> - Ѷȣ +> - https://leetcode-cn.com/problems/valid-parentheses/ + +һֻ '('')''{''}''['']' ַжַǷЧ + +Чַ㣺 + +- űͬ͵űպϡ +- űȷ˳պϡ + +עַɱΪЧַ + +ʾ 1: +```c +: "()" +: true +``` + +ʾ 2: +```c +: "()[]{}" +: true +``` + +ʾ 3: +```c +: "(]" +: false +``` + +ʾ 4: +```c +: "([)]" +: false +``` + +ʾ 5: +```c +: "{[]}" +: true +``` + +ʾ 6: +```c +: "" +: true +``` + + + +ʾ 7: +```c +: "((" +: false +``` + +**˼·**ջ + +жϸַȵżԣ򷵻falseջȽص㣬{[(ջ}])ջԪؽбȽϣǶӦջ򷵻false + +**ο** + +- ִнͨ +- ִʱ88 ms, C# ύл 70.31% û +- ڴģ22 MB, C# ύл 17.91% û + + +```c +public class Solution { + public bool IsValid(string s) + { + if (string.IsNullOrEmpty(s)) + return true; + + int count = s.Length; + if(count%2 == 1) + return false; + + Stack stack = new Stack(); + for (int i = 0; i < count; i++) + { + char c = s[i]; + if (stack.Count == 0) + { + stack.Push(c); + } + else if(c == '[' || c == '{' || c == '(') + { + stack.Push(c); + } + else if (stack.Peek() == GetPair(c)) + { + stack.Pop(); + } + else + { + return false; + } + } + return stack.Count == 0; + } + + public static char GetPair(char c) + { + if (c == ')') + return '('; + if (c == '}') + return '{'; + if (c == ']') + return '['; + return '\0'; + } +} +``` + +--- +## Ŀ03öʵջ + +> - ţ225 +> - Ѷȣ +> - https://leetcode-cn.com/problems/implement-stack-using-queues/ + +ʹöʵջв + +- `push(x)` -- Ԫ x ջ +- `pop()` -- ƳջԪ +- `top()` -- ȡջԪء +- `empty()` -- ջǷΪ + +**ע:** + +- ֻʹöеĻ-- Ҳ push to back, peek/pop from front, size, is empty ЩǺϷġ +- ʹõҲֶ֧Сʹ `list` `deque`˫˶Уģһ, ֻҪDZ׼Ķвɡ +- ԼвЧģ, һյջ `pop` `top` + + +**˼·**νʵջӻʱѭǰn-1ڵ㣬Ӷ׳Ӻټڶβʵֶӷ + +**ο룺** + +- ִнͨ +- ִʱ124 ms, C# ύл 56.21% û +- ڴģ23.4 MB, C# ύл 63.73% û + +```c +public class MyStack +{ + Queue queue = new Queue(); + + /** Initialize your data structure here. */ + public MyStack() + { + } + + /** Push element x onto stack. */ + public void Push(int x) + { + queue.Enqueue(x); + for (int i = 0; i < queue.Count - 1; i++) + { + queue.Enqueue(queue.Dequeue()); + } + } + + /** Removes the element on top of the stack and returns that element. */ + public int Pop() + { + return queue.Count > 0 ? queue.Dequeue() : -1; + } + + /** Get the top element. */ + public int Top() + { + return queue.Count > 0 ? queue.Peek() : -1; + } + + /** Returns whether the stack is empty. */ + public bool Empty() + { + return queue.Count == 0; + } +} + +/** + * Your MyStack object will be instantiated and called as such: + * MyStack obj = new MyStack(); + * obj.Push(x); + * int param_2 = obj.Pop(); + * int param_3 = obj.Top(); + * bool param_4 = obj.Empty(); + */ +``` + + +--- +## Ŀ04ת + +> - ţ7 +> - Ѷȣ +> - https://leetcode-cn.com/problems/reverse-integer/ + + +һ 32 λзҪÿλϵֽзת + +ʾ 1: +```python +: 123 +: 321 +``` + +ʾ 2: +```python +: -123 +: -321 +``` + +ʾ 3: +```python +: 120 +: 21 +``` +ʾ 4: +```python +: 21474836472^31 ? 1 = int.MaxValue +: 0 +``` +ʾ 5: +```python +: -2147483648?2^31 = int.MinValue +: 0 +``` + + +ע + +ǵĻֻܴ洢 32 λзֵΧΪ`[?2^31, 2^31 ? 1]`裬תôͷ 0 + + +**˼·**ͨеķʽѸתΪͨСͳһ + +**ο** + +- ״̬ͨ +- ִʱ: 56 ms, C# ύл 93.28% û +- ڴ: 13.9 MB, C# ύл 13.98% û + +```c +public class Solution { + public int Reverse(int x) { + if (x == int.MinValue) + return 0; + + long result = 0; + int negative = x < 0 ? -1 : 1; + x = negative * x; + + Queue q = new Queue(); + while (x != 0) + { + q.Enqueue(x % 10); + x = x/10; + } + + while (q.Count != 0) + { + result += q.Dequeue()*(long) Math.Pow(10, q.Count); + if (negative == 1 && result > int.MaxValue) + { + result = 0; + break; + } + if (negative == -1 && result*-1 < int.MinValue) + { + result = 0; + break; + } + } + return (int)result*negative; + } +} +``` + +--- +## Ŀ05沨ʽֵ + +> - ţ150 +> - Ѷȣе +> - https://leetcode-cn.com/problems/evaluate-reverse-polish-notation/ + +沨ʾʽֵ + +Ч +, -, *, / ÿҲһ沨ʽ + +˵ + +- ֻ֡ +- 沨ʽЧġ仰˵ʽܻóЧֵҲڳΪ 0 + +ʾ 1 + +```c +: ["2", "1", "+", "3", "*"] +: 9 +: ((2 + 1) * 3) = 9 +``` + +ʾ 2 + +```c +: ["4", "13", "5", "/", "+"] +: 6 +: (4 + (13 / 5)) = 6 +``` + +ʾ 3 + +```c +: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"] +: 22 +: + ((10 * (6 / ((9 + 3) * -11))) + 17) + 5 += ((10 * (6 / (12 * -11))) + 17) + 5 += ((10 * (6 / -132)) + 17) + 5 += ((10 * 0) + 17) + 5 += (0 + 17) + 5 += 17 + 5 += 22 +``` + + + +**˼·**ջȳԽ㷨ʵ֡ + +**ο** + +- ִнͨ +- ִʱ100 ms, C# ύл 100.00% û +- ڴģ25 MB, C# ύл 69.81% û + +```c +public class Solution { + public int EvalRPN(string[] tokens) + { + Stack stack = new Stack(); + for (int i = 0; i < tokens.Length; i++) + { + string str = tokens[i]; + if (str == "+" || str == "-" || str == "*" || str == "/") + { + int b = stack.Pop(); + int a = stack.Pop(); + int c = Compute(a, b, str); + stack.Push(c); + } + else + { + stack.Push(int.Parse(str)); + } + } + return stack.Pop(); + } + + public static int Compute(int a, int b, string oper) + { + int result = 0; + switch (oper) + { + case "+": + result = a + b; + break; + case "-": + result = a - b; + break; + case "*": + result = a * b; + break; + case "/": + result = a / b; + break; + } + return result; + } +} +``` + + +--- +## Ŀ06ȫ + +> - ţ46 +> - Ѷȣе +> - https://leetcode-cn.com/problems/permutations/ + +һûظֵУпܵȫС + +ʾ: +```c +: [1,2,3] +: +[ + [1,2,3], + [1,3,2], + [2,1,3], + [2,3,1], + [3,1,2], + [3,2,1] +] +``` + + + +˼·ݷback tracking һѡֳΪ̽ѡǰԴﵽĿꡣ̽ijһʱԭѡ񲢲ŻﲻĿ꣬˻һѡ߲ͨ˻ߵļΪݷij״̬ĵΪݵ㡱 + +> ׻ݷΪͨѡͬIJ·ѰĿĵأһ·һ·ڵȥҵĿĵءߴ·ҵ·ڵһ·ֱҵĿĵء + +ϰĻݹʾ + + +![ݹ](https://img-blog.csdnimg.cn/20201009214444744.png) + +**ο룺** + +- ״̬ͨ +- ִʱ: 364 ms, C# ύл 80.00% û +- ڴ: 30.6 MB, C# ύл 7.14% û + +```c +public class Solution +{ + private IList> _result; + private bool[] _used; + + public IList> Permute(int[] nums) + { + _result = new List>(); + if (nums == null || nums.Length == 0) + return _result; + _used = new bool[nums.Length]; + + FindPath(nums, 0, new List()); + return _result; + } + + public void FindPath(int[] nums, int count, List path) + { + if (count == nums.Length) + { + //ݹֹ + List item = new List(); + item.AddRange(path); + //뿽 + _result.Add(item); + return; + } + for (int i = 0; i < nums.Length; i++) + { + if (_used[i] == false) + { + path.Add(nums[i]); + _used[i] = true; + FindPath(nums, count + 1, path); + path.RemoveAt(path.Count - 1); + _used[i] = false; + } + } + } +} +``` + + + + +--- +## Ŀ07ַת (atoi) + +> - ţ8 +> - Ѷȣе +> - https://leetcode-cn.com/problems/string-to-integer-atoi/ + +ʵһ `atoi` ʹַܽת + +ȣúҪõĿͷոֱַѰҵһǿոַΪֹ + +ѰҵĵһǿַΪ߸ʱ򽫸÷֮澡ܶΪţһǿֱַ֣ӽַ֮γ + +ַЧ֮ҲܻڶַЩַԱԣǶںӦӰ졣 + +ע⣺ַеĵһǿոַһЧַַΪջַհַʱĺҪת + +κ£ܽЧתʱ뷵 0 + +˵ + +ǵĻֻܴ洢 32 λСзôֵΧΪ `[?2^31, 2^31? 1]`ֵΧ뷵 `INT_MAX (2^31? 1)` `INT_MIN (?2^31)` + +ʾ 1: +```c +: "42" +: 42 +``` + +ʾ 2: +```c +: " -42" +: -42 +: һǿհַΪ '-', һš +Ǿֵܽõ -42 +``` +ʾ 3: +```c +: "4193 with words" +: 4193 +: תֹ '3' ΪһַΪ֡ +``` + +ʾ 4: +```c +: "words and 987" +: 0 +: һǿַ 'w', ֻš +޷ִЧת +``` + +ʾ 5: +```c +: "-91283472332" +: -2147483648 +: "-91283472332" 32 λзΧ +˷ INT_MIN (?231) +``` + + +ʾ 6: +```c +: " 0000000000012345678" +: 12345678 +``` + +ʾ 7: +```c +: "20000000000000000000" +: 2147483647 +``` + +**˼·**ͨеķʽ + +**ο** + +- ״̬ͨ +- ִʱ: 104 ms, C# ύл 98.32% û +- ڴ: 24.3 MB, C# ύл 24.45% û + +```c +public class Solution { + public int MyAtoi(string str) { + str = str.Trim(); + if (string.IsNullOrEmpty(str)) + return 0; + + if (str[0] != '-' && str[0] != '+') + { + if (str[0] < '0' || str[0] > '9') + return 0; + } + int negative = 1; + long result = 0; + Queue q = new Queue(); + for (int i = 0; i < str.Length; i++) + { + if (str[i] == '-' && i == 0) + { + negative = -1; + continue; + } + if (str[i] == '+' && i == 0) + { + continue; + } + if (str[i] < '0' || str[i] > '9') + { + break; + } + q.Enqueue(str[i] - '0'); + } + + while (q.Count != 0) + { + int i = q.Dequeue(); + + //ȥǰ˵ + if (i == 0 && result == 0) + continue; + + // سλ + if (negative == 1 && q.Count > 10) + { + return int.MaxValue; + } + if (negative == -1 && q.Count > 10) + { + return int.MinValue; + } + + result += i * (long)Math.Pow(10, q.Count); + if (negative == 1 && result > int.MaxValue) + { + return int.MaxValue; + } + if (negative == -1 && result * -1 < int.MinValue) + { + return int.MinValue; + } + } + return (int)result * negative; + } +} +``` + +--- +## Ŀ08ѭ˫˶ + +> - ţ641 +> - Ѷȣе +> - https://leetcode-cn.com/problems/design-circular-deque/ + +ʵ˫˶С + +ʵҪ֧² + +- `MyCircularDeque(k)`캯,˫˶еĴСΪk +- `insertFront()`һԪӵ˫˶ͷ ɹ true +- `insertLast()`һԪӵ˫˶βɹ true +- `deleteFront()`˫˶ͷɾһԪء ɹ true +- `deleteLast()`˫˶βɾһԪءɹ true +- `getFront()`˫˶ͷһԪء˫˶Ϊգ -1 +- `getRear()`˫˶еһԪء˫˶Ϊգ -1 +- `isEmpty()`˫˶ǷΪա +- `isFull()`˫˶Ƿˡ + +ʾ + +```c +MyCircularDeque circularDeque = new MycircularDeque(3); // СΪ3 +circularDeque.insertLast(1); // true +circularDeque.insertLast(2); // true +circularDeque.insertFront(3); // true +circularDeque.insertFront(4); // Ѿˣ false +circularDeque.getRear(); // 2 +circularDeque.isFull(); // true +circularDeque.deleteLast(); // true +circularDeque.insertFront(4); // true +circularDeque.getFront(); // 4 +``` + +ʾ + +- ֵķΧΪ [1, 1000] +- ķΧΪ [1, 1000] +- 벻Ҫʹõ˫˶п⡣ + + +**ο** + +- ִнͨ +- ִʱ160 ms, C# ύл 90.48% û +- ڴģ34.7 MB, C# ύл 7.14% û + + +```c +public class MyCircularDeque +{ + private int _pFront; + private int _pRear; + private readonly int[] _dataset; + private int _length; + private int _maxSize; + + /** Initialize your data structure here. Set the size of the deque to be k. */ + public MyCircularDeque(int k) + { + _dataset = new int[k]; + _length = 0; + _maxSize = k; + _pFront = 0; + _pRear = 0; + } + + /** Adds an item at the front of Deque. Return true if the operation is successful. */ + public bool InsertFront(int value) + { + if (_length == _maxSize) + return false; + + _pFront = (_pFront - 1 + _maxSize)%_maxSize; + _dataset[_pFront] = value; + _length++; + return true; + } + + /** Adds an item at the rear of Deque. Return true if the operation is successful. */ + public bool InsertLast(int value) + { + if (_length == _maxSize) + return false; + + _dataset[_pRear] = value; + _pRear = (_pRear + 1)%_maxSize; + _length++; + return true; + } + + /** Deletes an item from the front of Deque. Return true if the operation is successful. */ + public bool DeleteFront() + { + if (_length == 0) + return false; + _pFront = (_pFront + 1)%_maxSize; + _length--; + return true; + } + + /** Deletes an item from the rear of Deque. Return true if the operation is successful. */ + public bool DeleteLast() + { + if (_length == 0) + return false; + _pRear = (_pRear - 1 + _maxSize)%_maxSize; + _length--; + return true; + } + + /** Get the front item from the deque. */ + public int GetFront() + { + if (_length == 0) + return -1; + + return _dataset[_pFront]; + } + + /** Get the last item from the deque. */ + public int GetRear() + { + if (_length == 0) + return -1; + int index = (_pRear - 1 + _maxSize)%_maxSize; + return _dataset[index]; + } + + /** Checks whether the circular deque is empty or not. */ + public bool IsEmpty() + { + return _length == 0; + } + + /** Checks whether the circular deque is full or not. */ + public bool IsFull() + { + return _length == _maxSize; + } +} + +/** + * Your MyCircularDeque object will be instantiated and called as such: + * MyCircularDeque obj = new MyCircularDeque(k); + * bool param_1 = obj.InsertFront(value); + * bool param_2 = obj.InsertLast(value); + * bool param_3 = obj.DeleteFront(); + * bool param_4 = obj.DeleteLast(); + * int param_5 = obj.GetFront(); + * int param_6 = obj.GetRear(); + * bool param_7 = obj.IsEmpty(); + * bool param_8 = obj.IsFull(); + */ +``` + + + + + +--- +## Ŀ09Ч + +> - ţ32 +> - Ѷȣ +> - https://leetcode-cn.com/problems/longest-valid-parentheses/ + +һֻ '(' ')' ַҳİЧŵӴijȡ + +ʾ 1: + +```c +: "(()" +: 2 +: ЧӴΪ "()" +``` + +ʾ 2: +```c +: ")()())" +: 4 +: ЧӴΪ "()()" +``` + +ʾ 3: +```c +: "" +: 0 +: +``` +ʾ 4: +```c +: "()(())" +: 6 +: ЧӴΪ "()(())" +``` + +**˼·**ջ + +ǿջڱַĹȥжϵĿǰΪֹɨַЧԣͬʱЧַijȡȽ ?1 ջ + +- ÿ(ǽ±ջС +- ÿ)ǵջԪأжЧԣЧȡ + +**ο** + +- ״̬ͨ +- ִʱ92 ms, C# ύл 53.78% û +- ڴģ23.5 MB, C# ύл 7.14% û + +```c +public class Solution { + public int LongestValidParentheses(string s) { + Stack stack = new Stack(); + stack.Push(-1); + int result = 0; + for (int i = 0; i < s.Length; i++) + { + if (s[i] == '(') + { + stack.Push(i); + } + else + { + stack.Pop(); + if (stack.Count == 0) + { + stack.Push(i); + } + else + { + result = Math.Max(result, i - stack.First()); + } + } + } + return result; + } +} +``` + +--- +## Ŀ10ֵ + +> - ţ239 +> - Ѷȣ +> - https://leetcode-cn.com/problems/sliding-window-maximum/ + +һ numsһСΪ k ĻڴƶҲࡣֻԿڻڵ k ֡ÿֻƶһλ + +ػеֵ + +ʾ: + +```c +: nums = [1,3,-1,-3,5,3,6,7], k = 3 +: [3,3,5,5,6,7] +: + + ڵλ ֵ +--------------- ----- +[1 3 -1] -3 5 3 6 7 3 + 1 [3 -1 -3] 5 3 6 7 3 + 1 3 [-1 -3 5] 3 6 7 5 + 1 3 -1 [-3 5 3] 6 7 5 + 1 3 -1 -3 [5 3 6] 7 6 + 1 3 -1 -3 5 [3 6 7] 7 +``` + +ʾ + +Լ k Чģ鲻Ϊյ£1 k ĴС + + + + + +ʱ临Ӷڽ + +**ο룺** + +ʵһѰÿڵֵ + + +- ״̬ͨ +- ִʱ: 472 ms, C# ύл 53.33% û +- ڴ: 34.3 MB, C# ύл 50.00% û + +```c +public class Solution { + public int[] MaxSlidingWindow(int[] nums, int k) { + int len = nums.Length; + if (len == 0) + return nums; + + int[] result = new int[len - k + 1]; + for (int i = 0; i < result.Length; i++) + { + result[i] = GetMax(nums, i, i + k); + } + return result; + } + + public int GetMax(int[] arr,int start,int end) + { + int max = int.MinValue; + for (int i = start; i < end; i++) + { + if (arr[i] > max) + max = arr[i]; + } + return max; + } +} +``` + +ʵֶʱЧʾҪʹýṹˡ + +- ״̬ͨ +- ִʱ: 364 ms, C# ύл 75.33% û +- ڴ: 40.5 MB, C# ύл 100.00% û + + +**˼·**ѭ˫˶¼ǰڵϢдֵλü¼ڶԪС˫˶Ҫ֤λõֵɴС +- ҪɾԪء +- ڶβԪأҪɾβԪأѸԪصλò뵽β + + +```c +public class MyCircularDeque +{ + private int _pFront; + private int _pRear; + private readonly int[] _dataset; + private int _length; + private int _maxSize; + + /** Initialize your data structure here. Set the size of the deque to be k. */ + public MyCircularDeque(int k) + { + _dataset = new int[k]; + _length = 0; + _maxSize = k; + _pFront = 0; + _pRear = 0; + } + + /** Adds an item at the front of Deque. Return true if the operation is successful. */ + public bool InsertFront(int value) + { + if (_length == _maxSize) + return false; + + _pFront = (_pFront - 1 + _maxSize) % _maxSize; + _dataset[_pFront] = value; + _length++; + return true; + } + + /** Adds an item at the rear of Deque. Return true if the operation is successful. */ + public bool InsertLast(int value) + { + if (_length == _maxSize) + return false; + + _dataset[_pRear] = value; + _pRear = (_pRear + 1) % _maxSize; + _length++; + return true; + } + + /** Deletes an item from the front of Deque. Return true if the operation is successful. */ + public bool DeleteFront() + { + if (_length == 0) + return false; + _pFront = (_pFront + 1) % _maxSize; + _length--; + return true; + } + + /** Deletes an item from the rear of Deque. Return true if the operation is successful. */ + public bool DeleteLast() + { + if (_length == 0) + return false; + _pRear = (_pRear - 1 + _maxSize) % _maxSize; + _length--; + return true; + } + + /** Get the front item from the deque. */ + public int GetFront() + { + if (_length == 0) + return -1; + + return _dataset[_pFront]; + } + + /** Get the last item from the deque. */ + public int GetRear() + { + if (_length == 0) + return -1; + int index = (_pRear - 1 + _maxSize) % _maxSize; + return _dataset[index]; + + } + + /** Checks whether the circular deque is empty or not. */ + public bool IsEmpty() + { + return _length == 0; + } + + /** Checks whether the circular deque is full or not. */ + public bool IsFull() + { + return _length == _maxSize; + } +} + +public class Solution { + public int[] MaxSlidingWindow(int[] nums, int k) { + int len = nums.Length; + if (len == 0) + return nums; + int[] result = new int[len - k + 1]; + MyCircularDeque deque = new MyCircularDeque(k); + + for (int i = 0; i < len; i++) + { + // жϵǰж׵ֵǷЧ + if (deque.IsEmpty() == false && deque.GetFront() <= i - k) + { + deque.DeleteFront(); + } + + // ֤ӴС ǰСҪεֱҪ + while (deque.IsEmpty() == false && nums[deque.GetRear()] <= nums[i]) + { + deque.DeleteLast(); + } + //ӵǰֵӦ± + deque.InsertLast(i); + + // ڳΪkʱ 浱ǰֵ + if (i + 1 >= k) + { + result[i + 1 - k] = nums[deque.GetFront()]; + } + } + return result; + } +} +``` + +--- +

+ +

\ No newline at end of file diff --git a/DataStructureAndAlgorithm/11 字符串.md b/DataStructureAndAlgorithm/12 字符串.md similarity index 100% rename from DataStructureAndAlgorithm/11 字符串.md rename to DataStructureAndAlgorithm/12 字符串.md