【LeetCode】2020-04 每日一题

8. 字符串转换整数 (atoi)(中等)

【分类】:模拟、正则表达式

【题解】:

解法1:直接模拟,但是在判断INT_MAX和INT_MIN上需要注意,因为直接判断会超出范围,所以可以将式子转换一下,本来是num * 10 + str[i] - '0' > MAX,可以转换为(MAX - (stri[i] - '0')) / 10 < num。

解法2:不得不说正则表达式真的牛逼啊啊啊啊!!!

'^[+-]?d+', s.lstrip()

 让我们来分析一下这个关键部分!

^x:表示匹配以字符串x为开头的字符串

[+-]?:匹配+或-或者什么也没有(?表示将前面的字符匹配0或1次)

d:表示数字

+:表示前面的字符一次或无数次

s.lstrip(a):将字符串前面连续的a字符去除,默认为‘ ’

肯定有人要问最前面的*是什么意思了!!这个是解包,可以将findall返回的列表组成一个字符串。

【代码】:

C++(解法1):

 1 class Solution {
 2 public:
 3     int myAtoi(string str) {
 4         int i = 0, f = 0;
 5         for (i = 0; i < str.size() && str[i] == ' '; i++);
 6         if (str[i] == '-')f = -1, i++;
 7         else if (str[i] == '+') f = 1, i++;
 8         else if(isdigit(str[i]))f = 1;
 9         if (f == 0)return 0;
10         int num = 0, f2 = 0;
11         int MAX = 2147483647, MIN = -2147483648;
12         for (; i < str.size() && isdigit(str[i]); i++)
13         {
14             if (num > ((MAX - (str[i] - '0')) / 10 ))
15             {
16                 if (f == 1)return MAX;
17                 else return MIN;
18             }
19             num = num * 10 + (str[i] - '0');
20         }
21         if (f == 1)return num;
22         else return -num;
23     }
24 };
View Code

Python3(解法2):

1 class Solution:
2     def myAtoi(self, s: str) -> int:
3         return max(min(int(*re.findall('^[+-]?d+', s.lstrip())), 2**31 - 1), -2**31)
View Code

11. 盛最多水的容器(中等)

【分类】:双指针

【题解】:将指针l、r分别位于两端,比较两端元素大小,假如说左端大,那么易得以右端为端点已经取到了最大值(因为元素间距离不能再大了),我们接下来可以看看以左端为端点还能不能更大,所以要把右指针往左移,此时如果右端大,那么以左端为端点已经取得了最大值,依次类推。

【代码】:

C++:

 1 class Solution {
 2 public:
 3     int maxArea(vector<int>& height) {
 4         int ans = 0, l = 0, r = height.size() - 1;
 5         while(l <= r)
 6         {
 7             ans = max(ans, min(height[l], height[r]) * (r - l));
 8             if (height[l] > height[r])r--;
 9             else l++;
10         }
11         return ans;
12     }
13 };
View Code

Python3:

 1 class Solution:
 2     def maxArea(self, height: List[int]) -> int:
 3         ans = 0
 4         l = 0
 5         r = len(height) - 1
 6         while l <= r:
 7             ans = max(ans, min(height[l], height[r]) * (r - l))
 8             if (height[l] > height[r]): r -= 1
 9             else: l += 1
10         return ans
View Code

22. 括号生成(中等)

【分类】:dfs、动态规划

【题解】:

解法1:回溯法,l为剩余左括号数量,r为剩余右括号数量,先考虑递归出口,也就是l=0&r=0的时候return(没有剩余括号啦)。然后只要l还有剩余我们就可以一直递归下去,那么右括号什么情况可以递归呢,必须当r > l时才可以,比如n=2我现在是(),后面肯定不能再加)啦。

解法2:考虑n个括号的情况可以由n-1个括号的情况得到,假设第n个括号的左括号在最左,那么n个括号的情况就是这样了()a,(a),a就是前n-1个括号的情况。所以也可以统一为(p)q,p = [0, n - 1],q = n - 1 - p即可涵盖上述情况。

【代码】:

C++(解法1):

 1 class Solution {
 2 public:
 3     vector<string>ans;
 4     vector<string> generateParenthesis(int n) {
 5         dfs("", n, n);
 6         return ans;
 7     }
 8     void dfs(string s, int l, int r)
 9     {
10         if (l == 0 && r == 0)
11         {
12             ans.push_back(s);
13             return;
14         }
15         if (l > 0)
16             dfs(s + "(", l - 1, r);
17         if (r > l)
18             dfs(s + ")", l, r - 1);
19         return;
20     }
21 };
View Code

Python3(解法2):

 1 class Solution:
 2     def generateParenthesis(self, n: int) -> List[str]:
 3         dp = []
 4         dp.append([""])
 5         for i in range(1, n + 1):
 6             cur = []
 7             for j in range(i):
 8                 l = dp[j]
 9                 r = dp[i - 1 -j]
10                 for ll in l:
11                     for rr in r:
12                         s = "(" + ll + ")" + rr
13                         cur.append(s)
14             dp.append(cur)
15         return dp[n]
View Code

55. 跳跃游戏(中等)

【分类】:贪心

【题解】:

解法1:因为每个位置除0外最小能跳的距离为1,实际上只要考虑每个0的位置能否跳过即可,所以每当遍历到0的时候,再往前遍历查找是否有一个位置能够跳过0,只要能跳过所有的0位置,就一定能跳到终点。

解法2:维护一个当前可以跳到的最大距离值。

【代码】:

C++(解法1):

 1 class Solution {
 2 public:
 3     bool canJump(vector<int>& nums) {
 4         for (int i = 0; i < nums.size() - 1; i++)
 5         {
 6             if (nums[i] == 0)
 7             {
 8                 int f = 0;
 9                 int t = i + 1, j = i - 1;
10                 while(j >= 0)
11                 {
12                     if (nums[j] >= t - j)
13                     {
14                         f = 1;
15                         break;
16                     }
17                     j--;
18                 }
19                 if (!f)return false;
20             }
21         }   
22         return true;
23     }
24 };
View Code

Python3(解法2):

1 class Solution:
2     def canJump(self, nums: List[int]) -> bool:
3         rightmost = 0
4         for i in range(len(nums)):
5             if rightmost >= i:
6                 rightmost = max(rightmost, i + nums[i])
7             else:
8                 return False
9         return True
View Code

56. 合并区间(中等)

【分类】:贪心

【题解】:每个区间按照左端点进行排序,然后遍历所有区间,当下一个区间的左端点大于当前区间的右端点说明这段区间不重合,反之说明重合,所以更新重合区间的右端点。

【代码】:

C++:

 1 struct Node{
 2     int x, y;
 3 };
 4 class Solution {
 5 public:
 6     static bool cmp(Node a, Node b)
 7     {
 8         return a.x != b.x ? a.x < b.x : a.y < b.y; 
 9     }
10     vector<vector<int>> merge(vector<vector<int>>& intervals) {
11         vector<Node>v;
12         vector<vector<int> > ans;
13         for (int i = 0; i < intervals.size(); i++)
14             v.push_back({intervals[i][0], intervals[i][1]});    
15         if (v.size() == 0)return ans;
16         sort(v.begin(), v.end(), cmp);
17         int l = v[0].x, r = v[0].y;
18         for (int i = 1; i < v.size(); i++)
19         {
20             if (v[i].x <= r) r = max(v[i].y, r);
21             else
22             {
23                 vector<int>t;
24                 t.push_back(l);
25                 t.push_back(r);
26                 ans.push_back(t);
27                 l = v[i].x;
28                 r = v[i].y;
29             }
30         }
31         vector<int>t;
32         t.push_back(l);
33         t.push_back(r);
34         ans.push_back(t);
35         return ans;
36     }
37 };
View Code

Python3:

 1 class Solution:
 2     def merge(self, intervals: List[List[int]]) -> List[List[int]]:
 3         if len(intervals) == 0:
 4             return []
 5         res = []
 6         intervals.sort(key=lambda x: x[0])  
 7         for inter in intervals:
 8             if len(res) == 0 or res[-1][1] < inter[0]:  
 9                 res.append(inter)
10             else:  
11                 res[-1][1] = max(res[-1][1], inter[1])
12         return res
View Code

151. 翻转字符串里的单词(中等)

【分类】:字符串

【题解】:这种字符串的题用Python简直不要方便太多!!C++的话根据题意老老实实模拟就好啦。

【代码】:

C++:

 1 class Solution {
 2 public:
 3     string reverseWords(string s) {
 4         vector<string>v;
 5         string ss = "";
 6         for (int i = 0; i < s.size(); i++)
 7         {
 8             if (s[i] != ' ')ss = ss + s[i];
 9             else
10             {
11                 if (ss != "")
12                 {
13                     v.push_back(ss);
14                     ss = "";
15                 }
16             }
17         }
18         if (ss != "")v.push_back(ss);
19         if (v.size() == 0)return "";
20         ss = "";
21         reverse(v.begin(), v.end());
22         for (int i = 0; i < v.size() - 1; i++)
23             ss = ss + v[i] + " ";
24         ss = ss + v[v.size() - 1];
25         return ss;
26     }
27 };
View Code

Python3:

1 class Solution:
2     def reverseWords(self, s: str) -> str:
3         ls = s.split(' ') # 按空格分隔单词
4         ls = list(filter(None, ls)) # 去除列表中的空字符串
5         ls.reverse() # 将列表倒序
6         ans = " ".join(ls)
7         return ans
View Code

199. 二叉树的右视图(中等)

【分类】:dfs、bfs、二叉树

【题解】:

解法1:bfs,维护一个数组d,d[i]表示深度为i的节点值,因为bfs是从左往右层序遍历,所以遍历过程中每个深度最后保存的值就是右视图看过去的值。

解法2:dfs,先遍历右子树,更新在每一层最先出现的元素即可。

【代码】:

C++(解法1):

 1 /**
 2  * Definition for a binary tree node.
 3  * struct TreeNode {
 4  *     int val;
 5  *     TreeNode *left;
 6  *     TreeNode *right;
 7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 8  * };
 9  */
10 class Solution {
11 public:
12     int ans[10005];
13     vector<int> rightSideView(TreeNode* root) {
14         queue<TreeNode*>q;
15         queue<int>d;
16         vector<int>v;
17         if (root == NULL)return v;
18         q.push(root);
19         d.push(0);
20         int maxdepth = 0;
21         while(!q.empty())
22         {
23             TreeNode* t = q.front();
24             q.pop();
25             int dd = d.front();
26             d.pop();
27             ans[dd] = t->val;
28             maxdepth = max(maxdepth, dd);
29             if (t->left != NULL)
30             {
31                 q.push(t->left);
32                 d.push(dd + 1);
33             }
34             if (t->right != NULL)
35             {
36                 q.push(t->right);
37                 d.push(dd + 1);
38             }
39         }
40         for(int i = 0; i <= maxdepth; i++)
41             v.push_back(ans[i]);
42         return v;
43     }
44 };
View Code

Python3(解法2):

 1 # Definition for a binary tree node.
 2 # class TreeNode:
 3 #     def __init__(self, x):
 4 #         self.val = x
 5 #         self.left = None
 6 #         self.right = None
 7 
 8 class Solution:
 9     def dfs(self, root, depth):
10         if root == None: return
11         if depth > len(self.ans):
12             self.ans.append(root.val)
13         self.dfs(root.right, depth + 1)
14         self.dfs(root.left, depth + 1)
15     def rightSideView(self, root: TreeNode) -> List[int]:
16         self.ans = [] 
17         self.dfs(root, 1)
18         return self.ans
View Code

200. 岛屿数量(中等)

【分类】:dfs、bfs

【题解】:算是比较基础的搜索题吧,只写了dfs。一定要看清楚题目是字符啊!!我一直以为是数字,被坑了好久。

【代码】:

C++:

 1 class Solution {
 2 public:
 3     int dirx[4] = {0, 0, 1, -1};
 4     int diry[4] = {1, -1, 0, 0};
 5     void dfs(vector<vector<char>>& grid, int x, int y, int n, int m)
 6     {
 7         if (x < 0 || x >= n || y < 0 || y >= m || grid[x][y] == '0')
 8             return;
 9         grid[x][y] = '0';
10         for(int i = 0; i < 4; i++)
11             dfs(grid, x + dirx[i], y + diry[i], n, m);
12         return;
13     }
14     int numIslands(vector<vector<char>>& grid) {
15         int n = grid.size();
16         if (n == 0)return 0;
17         int m = grid[0].size();
18         int ans = 0;
19         for (int i = 0; i < n; i++)
20         {
21             for (int j = 0; j < m; j++)
22             {
23                 if (grid[i][j] == '1')
24                 {
25                     ans++;
26                     dfs(grid, i, j, n, m);
27                 }
28             }
29         }
30         return ans;
31     }
32 };
View Code

Python3:

 1 class Solution:
 2     def __init__(self):
 3         self.dire = [(0, 1), (0, -1), (1, 0), (-1, 0)]
 4     def dfs(self, grid, x, y, n, m):
 5         if x < 0 or x >= n or y < 0 or y >= m or grid[x][y] == '0':
 6             return
 7         grid[x][y] = '0'
 8         for d in self.dire:
 9             self.dfs(grid, x + d[0], y + d[1], n, m)
10     def numIslands(self, grid: List[List[str]]) -> int:
11         n = len(grid)
12         if n == 0: return 0
13         m = len(grid[0])
14         ans = 0
15         for i in range(n):
16             for j in range(m):
17                 if grid[i][j] == '1':
18                     ans += 1
19                     self.dfs(grid, i, j, n, m)
20         return ans;
View Code

289. 生命游戏(中等)

【分类】:模拟、位运算

【题解】:

解法1:直接模拟,因为要求必须同时进行,所以只要将更新后的状态赋值给另一个数组,等更新完后再赋值回去就可以啦。

解法2:位运算。这个操作还是挺有意思的,反正我想不出来。现在我们用二进制表示每个格子细胞的状态(低位为之前的状态,高位为后来的状态):

(0)00:表示刚开始死的,后来还是死的

(1)01:表示刚开始活的,后来死了

(2)10:表示刚开始死的,后来活了

(3)11:表示刚开始活的,后来还是活的

然后分析一下条件可以发现:

1、当细胞是活的,周围有2或3个活细胞时可以活,对应上面的第(3)种情况

2、当细胞是死的,周围有3个活细胞时可以活,对应上面的第(2)种情况

所以每当满足以上两个条件的时候,如果是活细胞就记为3,死细胞就记为2。那么怎样计数呢?由于之前的状态在低位,所以只要每个状态&1就是本身的状态。

由于后来的状态在高位,那么最后的答案就是所有状态右移一位啦。

【代码】:

C++:

 1 class Solution {
 2 public:
 3     int t[505][505];
 4     int dirx[8] = {0, 0, 1, 1, 1, -1, -1, -1};
 5     int diry[8] = {1, -1, 0, 1, -1, 0, 1, -1};
 6     void gameOfLife(vector<vector<int>>& board) {
 7         int n = board.size();
 8         if (n == 0)return;
 9         int m = board[0].size();
10         for (int i = 0; i < n; i++)
11         {
12             for (int j = 0; j < m; j++)
13             {
14                 int num1 = 0;
15                 for(int ii = 0; ii < 8; ii++)
16                 {
17                     int x = i + dirx[ii];
18                     int y = j + diry[ii];
19                     if (x >= 0 &&  x < n && y >=0 && y < m && board[x][y])
20                         num1++;
21                 }
22                 if (board[i][j] == 0)
23                 {
24                     if(num1 == 3)t[i][j] = 1;
25                     else t[i][j] = 0;
26                 }
27                 else
28                 {
29                     if(num1 == 2 || num1 == 3)t[i][j] = 1;
30                     else t[i][j] = 0;
31                 }
32             }
33         }
34         for (int i = 0; i < n; i++)
35             for (int j = 0; j < m; j++)
36                 board[i][j] = t[i][j];
37     }
38 };
View Code

Python3:

 1 class Solution:
 2     def __init__(self):
 3         self.dire = [(0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (1, -1), (-1, 1), (-1, -1)]
 4     def gameOfLife(self, board: List[List[int]]) -> None:
 5         n = len(board)
 6         if n == 0: return
 7         m = len(board[0])
 8         for i in range(n):
 9             for j in range(m):
10                 num1 = 0
11                 for d in self.dire:
12                     x = i + d[0]
13                     y = j + d[1]
14                     if x >= 0 and x < n and y >= 0 and y < m:
15                         num1 += board[x][y] & 1
16                 if board[i][j] == 0 and num1 == 3:
17                     board[i][j] = 2
18                 elif board[i][j] == 1 and num1 in [2, 3]:
19                     board[i][j] = 3
20         for i in range(n):
21             for j in range(m):
22                 board[i][j] >>= 1
23         
View Code

445. 两数相加 II(中等)

【分类】:栈、链表

【题解】:倒序首先就要想到栈啦,把两个链表的数据分别存入两个栈中,再依次取出相加即可,比忘了进位哦。

【代码】:

C++:

 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode(int x) : val(x), next(NULL) {}
 7  * };
 8  */
 9 class Solution {
10 public:
11     ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
12         stack<int> s1, s2;
13         while(l1 != NULL)
14         {
15             s1.push(l1->val);
16             l1 = l1->next;
17         }
18         while(l2 != NULL)
19         {
20             s2.push(l2->val);
21             l2 = l2->next;
22         }
23         int c = 0;
24         ListNode* ans = NULL;
25         while(!s1.empty() || !s2.empty() || c != 0)
26         {
27             int t1 = s1.empty() ? 0: s1.top();
28             int t2 = s2.empty() ? 0: s2.top();
29             if(!s1.empty())s1.pop();
30             if(!s2.empty())s2.pop();  
31             int t = t1 + t2 + c;
32             int now = t % 10;
33             c = t / 10;
34             ListNode* cur = new ListNode();
35             cur->val = now;
36             cur->next = ans;
37             ans = cur;
38         }
39         return ans;
40     }
41 };
View Code

Python3:

 1 # Definition for singly-linked list.
 2 # class ListNode:
 3 #     def __init__(self, x):
 4 #         self.val = x
 5 #         self.next = None
 6 
 7 class Solution:
 8     def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
 9         s1 = []
10         s2 = []
11         while(l1):
12             s1.append(l1.val)
13             l1 = l1.next
14         while(l2):
15             s2.append(l2.val)
16             l2 = l2.next
17         c = 0
18         ans = None
19         while(s1 or s2 or c != 0):
20             t1 = 0 if not s1 else s1.pop()
21             t2 = 0 if not s2 else s2.pop()
22             t = t1 + t2 + c
23             now = t % 10
24             c = t // 10
25             cur = ListNode(now)
26             cur.next = ans
27             ans = cur
28         return ans
View Code
原文地址:https://www.cnblogs.com/z1014601153/p/12731777.html