121. 买卖股票的最佳时机(简单)
【分类】:模拟、思维
【题解】:可以用O(n)的复杂度完成,只需要在遍历的时候记录到当前位置为止买入股票的最小价格minn,再维护一个当前卖出股票价(a-minn)的最大值即可。
【代码】:
C++:
class Solution { public: int maxProfit(vector<int>& prices) { int minn = 0x3f3f3f3f; int ans = 0; for(int i = 0; i < prices.size(); i++) { minn = min(prices[i], minn); ans = max(ans, prices[i] - minn); } return ans; } };
Python3:
class Solution: def maxProfit(self, prices: List[int]) -> int: ans = 0 minn = float(inf) for a in prices: minn = min(minn, a) ans = max(ans, a - minn) return ans
169. 多数元素(简单)
【分类】:模拟、思维
【题解】:
解法1:找到一个出现次数大于n/2向下取整,其实稍微想一下就知道只要排序一下取中位数即可。
解法2:当然也可以直接做,用map存键值对,键为每个数字,值为每个数字出现的次数,然后遍历map找到出现次数大于n/2的键即可。
【代码】:
C++(解法1):
class Solution { public: int majorityElement(vector<int>& nums) { sort(nums.begin(), nums.end()); int n = nums.size(); return nums[n / 2]; } };
Python3(解法2):
class Solution: def majorityElement(self, nums: List[int]) -> int: dict1 = {} for a in nums: if a in dict1: dict1[a] = dict1[a] + 1 else: dict1[a] = 1 for k, v in dict1.items(): if v > (len(nums) / 2): return k
206. 反转链表(简单)
【分类】:链表、递归
【题解】:
解法1:遍历的思想。其实就是把1->2->3->4变为1<-2<-3<-4。然后就很好理解了,假如说当前head在3,那么需要将head后面的链表保存下来,由于newList已经是1<-2,所以只需要把head指向这个newList就变成1<-2<-3了。当然这种解法也可以携程递归形式。
解法2:递归地思想,还蛮难理解的。假设原理表为1->2->3->4,3和4已经反转那么链表变为1->2->3<-4,此时需要将2->3进行反转,head指向2,那么只需head-->next->nextt = head即可变成2<-3,但是此时head->next也指向3,为了不形成环需要将head->next = NULL,可以看看这个博主的图解,看了就懂的那种。
【代码】
C++(解法1递归形式):
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* pre = NULL; ListNode* tmp = NULL; ListNode* reverseList(ListNode* head) { if(head == NULL)return pre; tmp = head->next; head->next = pre; pre = head; head = tmp; return reverseList(head); } };
C++(解法2):
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* reverseList(ListNode* head) { if(head == NULL || head->next == NULL)return head; ListNode* now = reverseList(head->next); head->next->next = head; head->next = NULL; return now; } };
Python3(解法1遍历形式):
class Solution: def reverseList(self, head: ListNode) -> ListNode: newList = None while(head != None): tmp = head.next head.next = newList newList = head head = tmp return newList
225. 用队列实现栈(简单)
【分类】:队列、模拟
【题解】:
解法1:直接用deque做即可,因为是双端队列,栈该有的操作它都有。
解法2:由于栈是先进后出,队列是先进先出,所以每次有元素进入队列的时候只需要把底下的元素抽上来放到上面,让本次进的元素压在最下面,那么每次取队首元素即是栈顶元素。
【代码】:
C++(解法1):
1 class MyStack { 2 public: 3 /** Initialize your data structure here. */ 4 deque<int>dq; 5 MyStack() { 6 7 } 8 9 /** Push element x onto stack. */ 10 void push(int x) { 11 dq.push_back(x); 12 } 13 14 /** Removes the element on top of the stack and returns that element. */ 15 int pop() { 16 int x = dq.back(); 17 dq.pop_back(); 18 return x; 19 } 20 21 /** Get the top element. */ 22 int top() { 23 return dq.back(); 24 } 25 26 /** Returns whether the stack is empty. */ 27 bool empty() { 28 return dq.empty(); 29 } 30 }; 31 32 /** 33 * Your MyStack object will be instantiated and called as such: 34 * MyStack* obj = new MyStack(); 35 * obj->push(x); 36 * int param_2 = obj->pop(); 37 * int param_3 = obj->top(); 38 * bool param_4 = obj->empty(); 39 */
Python3(解法2):
1 class MyStack: 2 3 def __init__(self): 4 """ 5 Initialize your data structure here. 6 """ 7 self.ls = [] 8 9 def push(self, x: int) -> None: 10 """ 11 Push element x onto stack. 12 """ 13 self.ls.append(x) 14 l = len(self.ls) 15 while l > 1: 16 self.ls.append(self.ls[0]) 17 self.ls.pop(0) 18 l = l - 1 19 20 21 def pop(self) -> int: 22 """ 23 Removes the element on top of the stack and returns that element. 24 """ 25 return self.ls.pop(0) 26 27 28 29 def top(self) -> int: 30 """ 31 Get the top element. 32 """ 33 return self.ls[0] 34 35 36 def empty(self) -> bool: 37 """ 38 Returns whether the stack is empty. 39 """ 40 if len(self.ls) > 0: 41 return False 42 else: 43 return True 44 45 46 47 48 # Your MyStack object will be instantiated and called as such: 49 # obj = MyStack() 50 # obj.push(x) 51 # param_2 = obj.pop() 52 # param_3 = obj.top() 53 # param_4 = obj.empty()
300. 最长上升子序列(中等)
【分类】:动态规划、二分、贪心
【题解】:
解法1:动态规划经典题。dp[i]表示[0, i]区间内以nums[i]结尾的最长上升子序列长度。那么易得,对于j < i,只要nums[j] < nums[i],那么dp[i] = max(dp[i], dp[j] + 1)
解法2:我们可以维护一个数组v用来存放这个最长上升子序列,那么怎么维护呢?我通过样例说明一下:如果nums为[10,9,2,5,3,7,101,18]。
当i = 0时,nums[0] = 10,直接将10插入v中,v = [10]
当i = 1时,nums[1] = 9,因为要保持这个序列递增所以显然不能将9插入10后面,因为位置不能变所以也不能插到10前面,这时候就应该考虑了,如果把10换成9后面是不是更容易找到一个比9大的数字而不是10呢?这句话有点绕口,就是说后面如果出现一个10,那么答案就是1因为10 = 10不能插入,如果现在是9在v中呢,那么9 < 10答案就是2了,所以显然放一个更小的数字进去更容易找到比他大的数,所以v = [9]
当i = 2时,nums[2] = 2,同上,v = [ 2]
当i = 3时,nums[3] = 5,5 > 2所以v = [2, 5]
以此类推
v = [2, 4, 7, 18]
那么问题来了,如何在v中找到比当前nums[i]更大的数呢,由于v保证有序,所以可以通过二分查找,如果能找到那么把那个位置的数字换成nums[i],如果找不到,那么直接在v中插入即可。
至于二分可以自己手写,也可以用lower_bound函数。
【代码】:
C++(解法2):
1 class Solution { 2 public: 3 int lengthOfLIS(vector<int>& nums) { 4 vector<int>v; 5 if (nums.size() == 0)return 0; 6 v.push_back(nums[0]); 7 for (int i = 1; i < nums.size(); i++) 8 { 9 int pos = lower_bound(v.begin(), v.end(), nums[i]) - v.begin(); 10 if (pos == v.size())v.push_back(nums[i]); 11 else if (pos < v.size())v[pos] = nums[i]; 12 } 13 return v.size(); 14 } 15 };
Python3(解法1):
1 class Solution: 2 def lengthOfLIS(self, nums: List[int]) -> int: 3 l = len(nums) 4 dp = [0] * l 5 ans = 0 6 for i in range(l): 7 for j in range(0, i): 8 if nums[i] > nums[j]: 9 dp[i] = max(dp[i], dp[j]) 10 dp[i] += 1 11 ans = max(ans, dp[i]) 12 return ans;
322. 零钱兑换(中等)
【分类】:贪心、dfs、动态规划
【题解】:
解法1:贪心+dfs。因为题目要求兑换的零钱数目最少,所以可以利用贪心的思想从数目大的零钱开始兑换起,它能够兑换的最大数目是amount / coins[i],然后剩下的再用次大的零钱兑换,但是这样会存在一个问题,就是可能这种方式适无法兑换成功的,所以在这样的情况下需要回溯,同时还要加上适当的剪枝,比如idx < 0就不用再递归下去了 ,如果当前得到的数目已经比之前的答案大了也不用递归下去了。
解法2:动态规划。dp[i]兑换i的最少硬币数,那么当当前硬币j被放入时dp[i - coins[j]] + 1,如果不放时那么dp[i] = dp[i],只要取两者最小值即可,易得dp[i] = min( dp[i - coins[j]] + 1, dp[i])。
【代码】:
C++(解法1):
1 class Solution { 2 public: 3 int ans = 0x3f3f3f3f; 4 void dfs(vector<int>& coins, int idx, int num, int r) 5 { 6 if (r == 0) 7 { 8 ans = min(ans, num); 9 return; 10 } 11 if (idx < 0)return; 12 for (int i = r / coins[idx]; i >= 0 && num + i < ans; i--) 13 dfs(coins, idx - 1, num + i, r - i * coins[idx]); 14 } 15 int coinChange(vector<int>& coins, int amount) { 16 sort(coins.begin(), coins.end()); 17 dfs(coins, coins.size() - 1, 0, amount); 18 if (ans == 0x3f3f3f3f)return -1; 19 else return ans; 20 } 21 };
Python3(解法2):
1 class Solution: 2 def coinChange(self, coins: List[int], amount: int) -> int: 3 dp = [amount + 1] * (amount + 2) 4 dp[0] = 0 5 for i in range(1, amount + 1): 6 for j in range(len(coins)): 7 if i - coins[j] >= 0: 8 dp[i] = min(dp[i], dp[i - coins[j]] + 1); 9 if dp[amount] == amount + 1: 10 return -1 11 return dp[amount]
365. 水壶问题(中等)
【分类】:bfs、数学
【题解】
解法1:经典的倒水问题,可以分为以下六种情况。
(1)将A水杯倒满
(2)将B水杯倒满
(3)将A水杯清空
(4)将B水杯清空
(5)将A水杯中的水倒入B。若A水杯中的水能将B倒满,那么A水杯为空或者还剩水,如果不能将B倒满,那么A水杯为空,B水杯为为两杯之和
(6)将B水杯中的水倒入A。若B水杯中的水能将A倒满,那么B水杯为空或者还剩水,如果不能将A倒满,那么B水杯为空,A水杯为为两杯之和
分布讨论这六种情况,用bfs写一下即可。
解法2:数学题....哎我不懂
首先想让两个杯子x,y倒出一定的水量z,肯定满足ax+by=z,且a和b均为整数。
然后根据贝祖定理:若x,y是整数,且gcd(x, y) = d,那么对于任意的整数a, b, ax+by都一定是d的倍数,特别地,一定存在整数a,b,使ax+by = d成立。
由贝祖定理可知,若存在整数a,b,使得ax+by=z成立,则z一定为x,y最大公因数的整数倍。
所以最终题目就化解成求z是否为x、y的最大公约数的整数倍。
【代码】:
C++(解法2):
1 class Solution { 2 public: 3 bool canMeasureWater(int x, int y, int z) { 4 if (x == 0 && y == 0) return z == 0; 5 if (x + y < z) return false; 6 if (z % __gcd(x, y) == 0) return true; 7 else return false; 8 } 9 };
Python3(解法1):
1 class Solution: 2 def canMeasureWater(self, x: int, y: int, z: int) -> bool: 3 q = [(0, 0)] 4 vis = set() 5 while q: 6 rx, ry = q.pop() 7 if rx == z or ry == z or rx + ry == z: 8 return True 9 if (rx, ry) in vis: continue 10 vis.add((rx, ry)) 11 # 将x倒满 12 q.append((x, ry)) 13 # 将y倒满 14 q.append((rx, y)) 15 # 将x清空 16 q.append((0, ry)) 17 # 将y清空 18 q.append((rx, 0)) 19 # 将y倒入x 20 if x - rx <= ry: 21 q.append((x, ry - (x - rx))) 22 else: 23 q.append((rx + ry, 0)) 24 # 将x倒入y 25 if y - ry <= rx: 26 q.append((rx - (y - ry), y)) 27 else: 28 q.append((0, rx + ry)) 29 return False
409. 最长回文串(简单)
【分类】:思维、模拟
【题解】:刚开始没看清题目,还以为是让我求该字符串中最大回文串的长度。其实是通过字符串提供的字母组合一个最大回文串,这样就简单多了,如果该字符有偶数个那么肯定能构成回文串,如果是奇数个只能就只能是某个字符有奇数个,其他都必须是偶数个。
【代码】:
C++:
1 class Solution { 2 public: 3 map<char, int>mp; 4 int longestPalindrome(string s) { 5 int len = s.size(), sum = 0, f = 0; 6 for (int i = 0; i < len; i++) 7 mp[s[i]]++; 8 map<char, int>::iterator it; 9 for (it = mp.begin(); it != mp.end(); it++) 10 { 11 if (it->second % 2 != 0) 12 { 13 if (!f) 14 { 15 f = 1; 16 sum += it->second; 17 } 18 else sum += it->second - 1; 19 } 20 else sum += it->second; 21 } 22 return sum; 23 } 24 };
Python3:
1 class Solution: 2 def longestPalindrome(self, s: str) -> int: 3 l = len(s) 4 mp = {} 5 ans = 0 6 f = 0 7 for a in s: 8 if a in mp: 9 mp[a] = mp[a] + 1 10 else: 11 mp[a] = 1 12 for k, v in mp.items(): 13 if v % 2 != 0: 14 if f == 0: 15 f = 1 16 ans += v 17 else: 18 ans += v - 1 19 else: ans += v 20 return ans
543. 二叉树的直径(简单)
【分类】:dfs
【题解】:以任意节点为父节点的直径是它的左右子树的最大深度之和,那么我们只要在搜索每个节点的时候维护这样的一个最大值即可。
【代码】:
C++:
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 = 0; 13 int diameterOfBinaryTree(TreeNode* root) { 14 int d = dfs(root); 15 return ans; 16 17 } 18 int dfs(TreeNode *root) 19 { 20 if (root == NULL)return 0; 21 int l = dfs(root->left); 22 int r = dfs(root->right); 23 ans = max (ans, l + r); 24 return max(l, r) + 1; 25 } 26 };
Python3:
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 __init__(self): 10 self.ans = 0 11 def dfs(self, root): 12 if not root: 13 return 0 14 l = self.dfs(root.left) 15 r = self.dfs(root.right) 16 self.ans = max(self.ans, l + r) 17 return max(l, r) + 1 18 def diameterOfBinaryTree(self, root: TreeNode) -> int: 19 d = self.dfs(root) 20 return self.ans
695. 岛屿的最大面积(中等)
【分类】:dfs
【题解】:比较经典的dfs题,直接搜就好啦,别忘了判断边界。
【代码】:
C++:
1 class Solution { 2 public: 3 int dirx[4] = {1, -1, 0, 0}; 4 int diry[4] = {0, 0, 1, -1}; 5 int dfs(vector<vector<int>>& grid, int x, int y, int n, int m) 6 { 7 if (x >= n || x < 0 || y >= m || y < 0 || !grid[x][y]) 8 return 0; 9 int num = 1; 10 grid[x][y] = 0; 11 for (int i = 0; i < 4; i++) 12 { 13 int xx = x + dirx[i]; 14 int yy = y + diry[i]; 15 num += dfs(grid, xx, yy, n, m); 16 } 17 return num; 18 } 19 int maxAreaOfIsland(vector<vector<int>>& grid) { 20 int ans = 0; 21 int n = grid.size(), m = grid[0].size(); 22 for (int i = 0; i < n; i++) 23 for (int j = 0; j < m; j++) 24 ans = max(ans, dfs(grid, i, j, n, m)); 25 return ans; 26 } 27 };
Python3:
1 class Solution: 2 def dfs(self, grid, x, y, n, m): 3 if x < 0 or x >= n or y < 0 or y >= m or grid[x][y] == 0: 4 return 0 5 s = 1 6 grid[x][y] = 0 7 for dx, dy in self.dire: 8 xx, yy = x + dx, y + dy 9 s += self.dfs(grid, xx, yy ,n , m) 10 return s 11 def maxAreaOfIsland(self, grid: List[List[int]]) -> int: 12 self.dire = [(0, 1), (0, -1), (1, 0), (-1, 0)] 13 n = len(grid) 14 m = len(grid[0]) 15 ans = 0 16 for i in range(n): 17 for j in range(m): 18 if grid[i][j] == 1: 19 ans = max(ans, self.dfs(grid, i, j, n, m)) 20 return ans
820. 单词的压缩编码(中等)
【分类】:思维、字典树
【题解】:
解法1:可以先将单词存入set中,遍历每个单词的后缀如果在set中存在就删去,最后输出剩余单词的长度。
解法2:可以将每个单词翻转后插入字典树中,由字典树的定义可得只有当前缀不同时才会有分支,但是这样做的前提是必须先插入长度较长的字符串,最终只要计算每个叶子节点到根节点的个数之和即可。
【代码】:
C++(解法2):
1 class TrieNode { 2 public: 3 TrieNode* child[26]; 4 }; 5 class Trie{ 6 public: 7 TrieNode *root; 8 Trie(){ 9 root = new TrieNode(); 10 } 11 int insert(string word) 12 { 13 TrieNode *cur = root; 14 bool isNew = false; 15 for (int i = word.size() - 1; i >= 0; i--) 16 { 17 char ch = word[i] - 'a'; 18 if (cur->child[ch] == NULL) 19 { 20 cur->child[ch] = new TrieNode(); 21 isNew = true; 22 } 23 cur = cur->child[ch]; 24 } 25 if (isNew)return word.size() + 1; 26 else return 0; 27 } 28 }; 29 class Solution { 30 public: 31 static bool cmp(string a, string b) 32 { 33 return a.size() > b.size(); 34 } 35 int minimumLengthEncoding(vector<string>& words) { 36 sort(words.begin(), words.end(), cmp); 37 int ans = 0; 38 Trie *trie = new Trie(); 39 for (int i = 0; i < words.size(); i++) 40 ans += trie->insert(words[i]); 41 return ans; 42 } 43 };
Python3(解法1):
1 class Solution: 2 def minimumLengthEncoding(self, words: List[str]) -> int: 3 st = set(words) 4 for w in words: 5 for i in range(1, len(w)): 6 st.discard(w[i:]) 7 return sum(len(w) + 1 for w in st)
836. 矩形重叠(简单)
【分类】:思维、分类
【题解】:需要用到逆向思维,因为两个矩形重叠的情况很多,所以我们可以反过来思考不重叠的情况,那么就只有两个矩形平行分开或竖直分开,除去这两种情况就都是重叠了。
【代码】:
C++:
1 class Solution { 2 public: 3 bool isRectangleOverlap(vector<int>& rec1, vector<int>& rec2) { 4 if (rec1[2] <= rec2[0] || rec2[2] <= rec1[0])return false; 5 else if (rec1[3] <= rec2[1] || rec2[3] <= rec1[1])return false; 6 else return true; 7 } 8 };
Python3:
1 class Solution: 2 def isRectangleOverlap(self, rec1: List[int], rec2: List[int]) -> bool: 3 if (rec1[2] <= rec2[0] or rec2[2] <= rec1[0]): 4 return False 5 elif (rec1[3] <= rec2[1] or rec2[3] <= rec1[1]): 6 return False 7 else: 8 return True
876. 链表的中间结点(简单)
【分类】:思维
【题解】:
解法1:按照常规思维只要先遍历一遍链表知道长度,然后再遍历一遍链表即可找到中间位置。
解法2:快慢指针。说实话没看题解真没想到,看到后恍然大悟,其实只要遍历一次即可,即快指针每次走两个单位,慢指针每次走一个单位,当快指针走完链表后慢指针就刚刚到中间位置。
【代码】:
C++(解法1):
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* middleNode(ListNode* head) { 12 int num = 0; 13 ListNode *node = head; 14 while(node != NULL) 15 { 16 num++; 17 node = node->next; 18 } 19 num /= 2; 20 while(num--) 21 { 22 head = head->next; 23 } 24 return head; 25 } 26 };
Python3(解法2):
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 middleNode(self, head: ListNode) -> ListNode: 9 slow = head 10 fast = head 11 while (fast and fast.next): 12 fast = fast.next.next 13 slow = slow.next 14 return slow
892. 三维形体的表面积(简单)
【分类】:数学
【题解】:所有立方体的表面积-重叠面积。关键是重叠面积怎么计算,重叠面积分为两部分,一部分是自身那一列重叠的面积,另一部分是和周围有接触的列的重叠面积。
【代码】:
C++:
1 class Solution { 2 public: 3 int surfaceArea(vector<vector<int>>& grid) { 4 int num = 0; 5 int r = 0; 6 int row = grid.size(), col = grid[0].size(); 7 for (int i = 0; i < row; i++) 8 { 9 for (int j = 0; j < col; j++) 10 { 11 num += grid[i][j]; 12 if (grid[i][j] > 0)r += (grid[i][j] - 1) * 2; 13 if (i - 1 >= 0)r += min(grid[i - 1][j], grid[i][j]); 14 if (i + 1 < row) r += min(grid[i + 1][j], grid[i][j]); 15 if (j - 1 >= 0)r += min(grid[i][j - 1], grid[i][j]); 16 if (j + 1 < col) r += min(grid[i][j + 1], grid[i][j]); 17 } 18 } 19 return (num * 6 - r); 20 } 21 };
Python3:
1 class Solution: 2 def surfaceArea(self, grid: List[List[int]]) -> int: 3 num = 0 4 r = 0 5 row = len(grid) 6 col = len(grid[0]) 7 for i in range(row): 8 for j in range(col): 9 num += grid[i][j]; 10 if (grid[i][j] > 0): 11 r += (grid[i][j] - 1) * 2; 12 if (i - 1 >= 0): 13 r += min(grid[i - 1][j], grid[i][j]); 14 if (i + 1 < row): 15 r += min(grid[i + 1][j], grid[i][j]); 16 if (j - 1 >= 0): 17 r += min(grid[i][j - 1], grid[i][j]); 18 if (j + 1 < col): 19 r += min(grid[i][j + 1], grid[i][j]); 20 return (num * 6 - r);
912. 排序数组(中等)
【分类】:排序
【题解】:当然可以直接sort做,但是出题者本意应该是想让我们复习一下八大排序。这里就用快排和归并做一下。
【代码】:
C++(归并):
1 class Solution { 2 public: 3 void merge(vector<int>&nums, int l, int r) 4 { 5 if (l >= r)return; 6 int tmp[100005] = {0}; 7 int mid = (l + r) / 2, i = l, j = mid + 1, k = 0; 8 while(i <= mid && j <= r) 9 { 10 if (nums[i] <= nums[j])tmp[k++] = nums[i++]; 11 else tmp[k++] = nums[j++]; 12 } 13 while(i <= mid)tmp[k++] = nums[i++]; 14 while(j <= r)tmp[k++] = nums[j++]; 15 for(int i = 0; i < k; i++) 16 nums[i + l] = tmp[i]; 17 } 18 void mergesort(vector<int>& nums, int l, int r) 19 { 20 if (l >= r)return; 21 int mid = (l + r)/ 2; 22 mergesort(nums, l, mid); 23 mergesort(nums, mid + 1, r); 24 merge(nums, l, r); 25 } 26 vector<int> sortArray(vector<int>& nums) { 27 mergesort(nums, 0, nums.size() - 1); 28 return nums; 29 } 30 };
Python3(快排):
1 class Solution: 2 def quicksort(self, nums, begin, end): 3 if begin >= end: return 4 l = begin 5 r = end 6 t = nums[l] 7 while(l != r): 8 while l < r and nums[r] >= t: r -= 1 9 nums[l] = nums[r] 10 while l < r and nums[l] <= t: l += 1 11 nums[r] = nums[l] 12 nums[l] = t 13 self.quicksort(nums, begin, l) 14 self.quicksort(nums, l + 1, end) 15 16 def sortArray(self, nums: List[int]) -> List[int]: 17 self.quicksort(nums, 0, len(nums) - 1) 18 return nums
914. 卡牌分组(简单)
【分类】:数学、gcd
【题解】:理解后即可转换题意为求取这组数据中每个不同的数字的个数的最大公约数,如果最大公约数>1则输出True,反之输出False。这里求取最大公约数记得用辗转相除法哦。
【代码】:
C++:
1 class Solution { 2 public: 3 int gcd(int a, int b) 4 { 5 int r; 6 while(b > 0) 7 { 8 r = a % b; 9 a = b; 10 b = r; 11 } 12 return a; 13 } 14 bool hasGroupsSizeX(vector<int>& deck) { 15 map<int, int>mp; 16 for (int i = 0; i < deck.size(); i++) 17 mp[deck[i]]++; 18 map<int, int>::iterator it = mp.begin(); 19 int gd = it->second; 20 for (;it != mp.end(); it++) 21 gd = gcd(gd, it->second); 22 if (gd == 1)return false; 23 else return true; 24 } 25 };
Python3:
1 class Solution: 2 def gcd(self, a, b): 3 while b > 0: 4 r = a % b 5 a = b 6 b = r 7 return a 8 def hasGroupsSizeX(self, deck: List[int]) -> bool: 9 mp = {} 10 for x in deck: 11 if x not in mp: 12 mp[x] = 1 13 else: 14 mp[x] += 1 15 ls = list(mp.values()) 16 gd = ls[0] 17 for x in ls: 18 gd = self.gcd(x, gd) 19 if gd == 1: 20 return False 21 else: 22 return True
945. 使数组唯一的最小增量(中等)
【分类】:贪心
【题解】:排完序利用贪心的思想,因为每个元素只能增加1所以只需要和前面的元素比较,如果和它相等就加1即可。
【代码】:
C++:
1 class Solution { 2 public: 3 int minIncrementForUnique(vector<int>& A) { 4 sort(A.begin(), A.end()); 5 if (A.size() == 0)return 0; 6 int ans = 0; 7 for (int i = 1; i < A.size(); i++) 8 { 9 if (A[i] <= A[i - 1]) 10 { 11 ans += A[i - 1] - A[i] + 1; 12 A[i] = A[i - 1] + 1; 13 } 14 } 15 return ans; 16 } 17 };
Python3:
1 class Solution: 2 def minIncrementForUnique(self, A: List[int]) -> int: 3 A.sort() 4 if len(A) == 0: return 0 5 ans = 0 6 for i in range(1, len(A)): 7 if A[i] <= A[i - 1]: 8 ans += A[i - 1] - A[i] + 1 9 A[i] = A[i - 1] + 1 10 return ans
994. 腐烂的橘子(简单)
【分类】:bfs
【题解】:很经典的广搜题。
【代码】:
C++:
1 class Solution { 2 public: 3 struct Node{ 4 int x, y, v; 5 }; 6 int vis[15][15] = {0}; 7 int dirx[4] = {0, 0, 1, -1}; 8 int diry[4] = {1, -1, 0, 0}; 9 int orangesRotting(vector<vector<int>>& grid) { 10 int m = grid.size(); 11 int n = grid[0].size(); 12 queue<Node>q; 13 int num = 0; 14 for (int i = 0; i < m; i++) 15 { 16 for (int j = 0; j < n; j++) 17 { 18 if (grid[i][j] == 2) 19 { 20 q.push({i, j, 0}); 21 vis[i][j] = 1; 22 } 23 else if (grid[i][j] == 1)num++; 24 } 25 } 26 int ans = 0; 27 while(!q.empty()) 28 { 29 Node t = q.front(); 30 q.pop(); 31 ans = max(ans, t.v); 32 for (int i = 0; i < 4; i++) 33 { 34 int xx = t.x + dirx[i]; 35 int yy = t.y + diry[i]; 36 if (xx >=0 && xx < m && yy >= 0 && yy < n && !vis[xx][yy] && grid[xx][yy] == 1) 37 { 38 vis[xx][yy] = 1; 39 q.push({xx, yy, t.v + 1}); 40 num--; 41 } 42 } 43 } 44 if (num != 0)return -1; 45 else return ans; 46 } 47 };
Python3:
1 class Solution: 2 def orangesRotting(self, grid: List[List[int]]) -> int: 3 dirx = [0, 0, 1, -1] 4 diry = [1, -1, 0, 0] 5 n = len(grid) 6 m = len(grid[0]) 7 ls = [] 8 ans = 0 9 num = 0 10 for i in range(n): 11 for j in range(m): 12 if (grid[i][j] == 2): 13 ls.append([i, j, 0]) 14 elif (grid[i][j] == 1): 15 num += 1 16 while(len(ls) > 0): 17 t = ls.pop(0) 18 ans = max(ans, t[2]) 19 for i in range(4): 20 xx = t[0] + dirx[i] 21 yy = t[1] + diry[i] 22 if (xx >=0 and xx < n and yy >=0 and yy < m and grid[xx][yy] == 1): 23 grid[xx][yy] = 2 24 ls.append([xx, yy, t[2] + 1]) 25 num -= 1 26 if num > 0: 27 return -1 28 else: 29 return ans
999. 可以被一步捕获的棋子数(简单)
【分类】:模拟
【题解】:理解题意即可,分别计算R的四个方向,如果碰到边界或B退出循环,如果碰到p那么num+1退出循环(因为抓到一个就会停下)。
【代码】:
C++:
1 class Solution { 2 public: 3 int numRookCaptures(vector<vector<char>>& board) { 4 int n = board.size(); 5 int m = board[0].size(); 6 int x, y, num = 0, xx, yy; 7 for (int i = 0; i < n; i++) 8 { 9 for (int j = 0; j < m; j++) 10 { 11 if (board[i][j] == 'R') 12 { 13 x = i; 14 y = j; 15 break; 16 } 17 } 18 } 19 xx = x; 20 while(xx > 0) 21 { 22 xx--; 23 if (board[xx][y] == 'p') 24 { 25 num++; 26 break; 27 } 28 else if (board[xx][y] == 'B')break; 29 } 30 xx = x; 31 while(xx + 1 < n) 32 { 33 xx++; 34 if (board[xx][y] == 'p') 35 { 36 num++; 37 break; 38 } 39 else if (board[xx][y] == 'B')break; 40 } 41 yy = y; 42 while(yy > 0) 43 { 44 yy--; 45 if (board[x][yy] == 'p') 46 { 47 num++; 48 break; 49 } 50 else if (board[x][yy] == 'B')break; 51 } 52 yy = y; 53 while(yy + 1 < m) 54 { 55 yy++; 56 if (board[x][yy] == 'p') 57 { 58 num++; 59 break; 60 } 61 else if (board[x][yy] == 'B')break; 62 } 63 return num; 64 } 65 };
Python3:
1 class Solution: 2 def numRookCaptures(self, board: List[List[str]]) -> int: 3 n = len(board) 4 m = len(board) 5 x, y, num = 0, 0, 0 6 for i in range(n): 7 for j in range(m): 8 if board[i][j] == 'R': 9 x = i 10 y = j 11 break 12 xx = x 13 while xx > 0: 14 xx -= 1 15 if board[xx][y] == 'B':break 16 elif board[xx][y] == 'p': 17 num += 1 18 break; 19 xx = x 20 while xx + 1 < n: 21 xx += 1 22 if board[xx][y] == 'B':break 23 elif board[xx][y] == 'p': 24 num += 1 25 break; 26 yy = y 27 while yy > 0: 28 yy -= 1 29 if board[x][yy] == 'B':break 30 elif board[x][yy] == 'p': 31 num += 1 32 break; 33 yy = y 34 while yy + 1 < m: 35 yy += 1 36 if board[x][yy] == 'B':break 37 elif board[x][yy] == 'p': 38 num += 1 39 break; 40 return num
1013. 将数组分成和相等的三个部分(简单)
【分类】:思维、模拟
【题解】:直接暴力做就可以啦,首先排除不能分的情况,即所有所有数之和不能被3整除。然后直接找前两组等于和/3的数,如果还有数字被剩下那么久可以分成三个部分。
【代码】:
C++:
1 class Solution { 2 public: 3 bool canThreePartsEqualSum(vector<int>& A) { 4 int len = A.size(), i, sum = 0; 5 for (i = 0; i < len; i++) 6 { 7 sum += A[i]; 8 } 9 if (sum % 3 != 0)return false; 10 else 11 { 12 sum /= 3; 13 int t = 0; 14 for (i = 0; i < len; i++) 15 { 16 t += A[i]; 17 if (t == sum)break; 18 } 19 if (t != sum)return false; 20 t = 0; 21 for (i = i + 1; i < len; i++) 22 { 23 t += A[i]; 24 if (t == sum)break; 25 } 26 if (i >= len - 1)return false; 27 else return true; 28 } 29 } 30 };
Python3:
1 class Solution: 2 def canThreePartsEqualSum(self, A: List[int]) -> bool: 3 s = 0 4 for x in A: 5 s += x 6 if (s % 3 != 0): 7 return False 8 else: 9 s /= 3 10 t = 0 11 l = len(A) 12 for i in range(l): 13 t += A[i]; 14 if (t == s):break 15 if t != s: 16 return False; 17 t = 0 18 for x in range(i + 1, l): 19 t += A[x]; 20 if (t == s):break 21 if (x >= l - 1): 22 return False 23 else: 24 return True
1071. 字符串的最大公因子(简单)
【分类】:思维、模拟
【题解】:只要判断两个字符串是否是两字符串最大公因数串的子串即可。
【代码】:
C++:
1 class Solution { 2 public: 3 string gcdOfStrings(string str1, string str2) { 4 int l1 = str1.size(), l2 = str2.size(); 5 int gd = __gcd(l1, l2), f = 0; 6 string s = str1.substr(0, gd), t; 7 for (int i = 0; i < l1; i += gd) 8 { 9 t = ""; 10 for (int j = i; j < i + gd; j++) 11 t += str1[j]; 12 if (t != s) 13 { 14 f = 1; 15 break; 16 } 17 } 18 if (t != s || f == 1)return ""; 19 for (int i = 0; i < l2; i += gd) 20 { 21 t = ""; 22 for (int j = i; j < i + gd; j++) 23 t += str2[j]; 24 if (t != s) 25 { 26 f = 1; 27 break; 28 } 29 } 30 if (t != s || f == 1)return ""; 31 else return s; 32 } 33 };
Python3:
1 class Solution: 2 def gcd(self, a, b): 3 while b > 0: 4 t = a % b 5 a = b 6 b = t 7 return a 8 def gcdOfStrings(self, str1: str, str2: str) -> str: 9 l1 = len(str1) 10 l2 = len(str2) 11 gd = self.gcd(l1, l2) 12 s = str1[0: gd] 13 p = "" 14 f = 0 15 for i in range(0, l1, gd): 16 p = "" 17 for j in range(i, i + gd): 18 p = p + str1[j] 19 if (p != s): 20 f = 1 21 break 22 if (p != s or f == 1):return "" 23 for i in range(0, l2, gd): 24 p = "" 25 for j in range(i, i + gd): 26 p = p + str2[j] 27 if (p != s): 28 f = 1 29 break 30 if (p != s or f == 1):return "" 31 else: return s 32
1103. 分糖果 II(简单)
【分类】:模拟
【题解】:直接根据题意模拟即可。由于编号上存在循环,用到(i + 1)% 人数。当然也可以通过推数学公式来求。
【代码】:
C++:
1 class Solution { 2 public: 3 vector<int> distributeCandies(int candies, int num_people) { 4 vector<int>v; 5 int i = 0, num = 1; 6 for (int i = 0; i < num_people; i++) 7 v.push_back(0); 8 while(candies > 0) 9 { 10 v[i] += num; 11 candies -= num; 12 if (candies > num + 1)num++; 13 else num = candies; 14 i = (i + 1) % num_people; 15 } 16 return v; 17 } 18 };
Python3:
1 class Solution: 2 def distributeCandies(self, candies: int, num_people: int) -> List[int]: 3 ans = [] 4 for i in range(num_people): 5 ans.append(0) 6 num = 1 7 i = 0 8 while(candies): 9 ans[i] += num 10 candies -= num 11 if (candies > num + 1): 12 num += 1 13 else: num = candies 14 i = (i + 1) % num_people 15 return ans
1160. 拼写单词(简单)
【分类】:模拟
【题解】:根据题意直接做即可,记录字母表中每个字母的个数,只要统计每个单词出现的字母的个数小于等于字母表就可以啦。不得不说python真是太方便了!!
【代码】:
C++:
1 class Solution { 2 public: 3 int countCharacters(vector<string>& words, string chars) { 4 map<char, int> mp; 5 for (int i = 0; i < chars.size(); i++) 6 mp[chars[i]]++; 7 int ans = 0; 8 for (int i = 0; i < words.size(); i++) 9 { 10 int f = 0; 11 map<char, int>mp2 = mp; 12 for (int j = 0; j < words[i].size(); j++) 13 { 14 if (mp2[words[i][j]] >= 1) 15 mp2[words[i][j]]--; 16 else 17 { 18 f = 1; 19 break; 20 } 21 } 22 if (!f) 23 ans += words[i].size(); 24 } 25 return ans; 26 } 27 };
Python3:
1 class Solution: 2 def countCharacters(self, words: List[str], chars: str) -> int: 3 c = collections.Counter(chars) 4 ans = 0 5 for s in words: 6 w = collections.Counter(s) 7 if all([c[i] >= w[i] for i in w]): 8 ans += len(s) 9 return ans
面试题 01.06. 字符串压缩(简单)
【分类】:模拟
【题解】:不难。根据题意直接做就好啦。
【代码】:
C++:
1 class Solution { 2 public: 3 string compressString(string S) { 4 string ans = ""; 5 if (S == "")return ""; 6 int num = 1; 7 for (int i = 1; i < S.size(); i++) 8 { 9 if (S[i] != S[i - 1]) 10 { 11 ans += S[i - 1]; 12 ans += to_string(num); 13 num = 1; 14 } 15 else num++; 16 } 17 ans += S[S.size() - 1]; 18 ans += to_string(num); 19 if (ans.size() >= S.size())return S; 20 else return ans; 21 } 22 };
Python3:
1 class Solution: 2 def compressString(self, S: str) -> str: 3 ans = "" 4 if S == "": return "" 5 num = 1 6 for i in range(1, len(S)): 7 if (S[i] != S[i - 1]): 8 ans += S[i - 1] 9 ans += str(num) 10 num = 1 11 else: num += 1 12 ans += S[len(S) - 1] 13 ans += str(num) 14 if len(ans) >= len(S): return S 15 else: return ans
面试题 10.01. 合并排序的数组(简单)
【分类】:排序、思维
【题解】:
解法1:直接将第二个数组放入第一个数组中然后排序。
解法2:从两个数组的最后一个元素开始比起,谁大就往后面移,当然不要忘记有种情况是第一个数组的所有数都比第二个大,所以退出循环后记得把第二个数组的元素放进去。
【代码】:
C++(解法1):
1 class Solution { 2 public: 3 void merge(vector<int>& A, int m, vector<int>& B, int n) { 4 int len = A.size() - B.size(); 5 for(int i = 0; i < B.size(); i++) 6 A[len + i] = B[i]; 7 sort(A.begin(), A.end()); 8 } 9 };
Python3(解法2):
1 class Solution: 2 def merge(self, A: List[int], m: int, B: List[int], n: int) -> None: 3 i = m - 1 4 j = n - 1 5 while(i >= 0 and j >= 0): 6 if A[i] >= B[j]: 7 A[i + j + 1] = A[i] 8 i -= 1 9 else: 10 A[i + j + 1] = B[j] 11 j -= 1 12 while(j >= 0): 13 A[i + j + 1] = B[j] 14 j -= 1
面试题 17.16. 按摩师(简单)
【分类】:动态规划
【题解】:我不明白这题为什么简单!!我觉得所有dp都是难的!!
设dp[i]为0-i这个区间内的最大值。那么可以分类讨论:
(1)如果取nums[i],那么nums[i-1]就不能取,也就是说状态得从dp[i-2]传过来,所以dp[i] = dp[i-2] + nums[i]
(2)如果不取nums[i],那么状态就可以从ddp[i-1]传过来,所以dp[i] = dp[i - 1]
最后取这两种情况的最大值即可。
【代码】:
C++(解法1):
1 class Solution { 2 public: 3 int dp[10005]; 4 int massage(vector<int>& nums) { 5 int len = nums.size(); 6 if (len == 0)return 0; 7 else if (len == 1)return nums[0]; 8 dp[0] = nums[0]; 9 dp[1] = max(nums[0], nums[1]); 10 for (int i = 2; i < len; i++) 11 dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]); 12 return dp[len - 1]; 13 } 14 };
Python3(解法2):
1 class Solution: 2 def massage(self, nums: List[int]) -> int: 3 n = len(nums) 4 if n == 0: return 0 5 elif n == 1: return nums[0] 6 dp = [0] * (n + 1) 7 dp[0] = nums[0] 8 dp[1] = max(nums[0], nums[1]) 9 for i in range(2, n): 10 dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]) 11 return dp[n - 1]
面试题40. 最小的k个数(简单)
【分类】:排序
【题解】:
解法1:直接用内置sort排序然后输出即可。
解法2:很经典的堆排序题,用大顶堆做。
【代码】:
C++(解法1):
1 class Solution { 2 public: 3 vector<int> getLeastNumbers(vector<int>& arr, int k) { 4 sort(arr.begin(), arr.end()); 5 vector<int>ans; 6 for (int i = 0; i < k; i++) 7 ans.push_back(arr[i]); 8 return ans; 9 } 10 };
Python3(解法2):
1 class Solution: 2 def getLeastNumbers(self, arr: List[int], k: int) -> List[int]: 3 if (k == 0): return list() 4 # 由于python里的heapq是小根堆,所以需要取相反数 5 hp = [-x for x in arr[:k]] 6 # 让列表具备堆特性 7 heapq.heapify(hp) 8 for i in range(k, len(arr)): 9 if -hp[0] > arr[i]: 10 heapq.heappop(hp) 11 heapq.heappush(hp, -arr[i]) 12 ans = [-x for x in hp] 13 return ans
面试题57 - II. 和为s的连续正数序列(简单)
【分类】:思维
【题解】:滑动窗口法,虽然n的范围在10^5但是实际上易得枚举数字只要到n/2 + 1即可,然后我们就可以设置一个左右边界l,r,将l到r-1所有的数加起来,如果超过target那么l 就向右移,也就是减去了l,同理如果小于target那r就向右移。
【代码】:
C++:
1 class Solution { 2 public: 3 vector<vector<int>> findContinuousSequence(int target) { 4 int h = (target / 2) + 1; 5 int l = 1, r = 1, sum = 0; 6 vector<vector<int> >ans; 7 while(l<=h) 8 { 9 if (sum > target) 10 { 11 sum -= l; 12 l++; 13 } 14 else if (sum < target) 15 { 16 sum += r; 17 r++; 18 } 19 else 20 { 21 vector<int>v; 22 for (int i = l; i < r; i++) 23 v.push_back(i); 24 ans.push_back(v); 25 sum -= l; 26 l++; 27 } 28 } 29 return ans; 30 } 31 };
Python3:
1 class Solution: 2 def findContinuousSequence(self, target: int) -> List[List[int]]: 3 h = (target / 2) + 1 4 ans = [] 5 l = 1 6 r = 1 7 s = 0 8 while l <= h: 9 if s < target: 10 s += r 11 r += 1 12 elif s > target: 13 s -= l 14 l += 1 15 else: 16 a = [] 17 for i in range(l, r): 18 a.append(i) 19 ans.append(a) 20 s -= l 21 l += 1 22 return ans
面试题62. 圆圈中最后剩下的数字(简单)
【分类】:数学
【题解】:约瑟夫环问题。可以看这篇题解,感觉我以前也是一知半解,看完这个豁然开朗。
f(n,m) = 0, n = 1
f(n,m) = [ f(n-1, m) +m ] %n, n > 1
【代码】:
C++:
1 class Solution { 2 public: 3 int lastRemaining(int n, int m) { 4 int pos = 0; 5 for (int i = 2; i <= n; i++) 6 pos = (pos + m) % i; 7 return pos; 8 } 9 };
Python3:
1 class Solution: 2 def lastRemaining(self, n: int, m: int) -> int: 3 pos = 0 4 for i in range(2, n + 1): 5 pos = (pos + m) % i 6 return pos
------------恢复内容开始------------
121. 买卖股票的最佳时机(简单)
【分类】:模拟、思维
【题解】:可以用O(n)的复杂度完成,只需要在遍历的时候记录到当前位置为止买入股票的最小价格minn,再维护一个当前卖出股票价(a-minn)的最大值即可。
【代码】:
C++:
class Solution { public: int maxProfit(vector<int>& prices) { int minn = 0x3f3f3f3f; int ans = 0; for(int i = 0; i < prices.size(); i++) { minn = min(prices[i], minn); ans = max(ans, prices[i] - minn); } return ans; } };
Python3:
class Solution: def maxProfit(self, prices: List[int]) -> int: ans = 0 minn = float(inf) for a in prices: minn = min(minn, a) ans = max(ans, a - minn) return ans
169. 多数元素(简单)
【分类】:模拟、思维
【题解】:
解法1:找到一个出现次数大于n/2向下取整,其实稍微想一下就知道只要排序一下取中位数即可。
解法2:当然也可以直接做,用map存键值对,键为每个数字,值为每个数字出现的次数,然后遍历map找到出现次数大于n/2的键即可。
【代码】:
C++(解法1):
class Solution { public: int majorityElement(vector<int>& nums) { sort(nums.begin(), nums.end()); int n = nums.size(); return nums[n / 2]; } };
Python3(解法2):
class Solution: def majorityElement(self, nums: List[int]) -> int: dict1 = {} for a in nums: if a in dict1: dict1[a] = dict1[a] + 1 else: dict1[a] = 1 for k, v in dict1.items(): if v > (len(nums) / 2): return k
206. 反转链表(简单)
【分类】:链表、递归
【题解】:
解法1:遍历的思想。其实就是把1->2->3->4变为1<-2<-3<-4。然后就很好理解了,假如说当前head在3,那么需要将head后面的链表保存下来,由于newList已经是1<-2,所以只需要把head指向这个newList就变成1<-2<-3了。当然这种解法也可以携程递归形式。
解法2:递归地思想,还蛮难理解的。假设原理表为1->2->3->4,3和4已经反转那么链表变为1->2->3<-4,此时需要将2->3进行反转,head指向2,那么只需head-->next->nextt = head即可变成2<-3,但是此时head->next也指向3,为了不形成环需要将head->next = NULL,可以看看这个博主的图解,看了就懂的那种。
【代码】
C++(解法1递归形式):
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* pre = NULL; ListNode* tmp = NULL; ListNode* reverseList(ListNode* head) { if(head == NULL)return pre; tmp = head->next; head->next = pre; pre = head; head = tmp; return reverseList(head); } };
C++(解法2):
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* reverseList(ListNode* head) { if(head == NULL || head->next == NULL)return head; ListNode* now = reverseList(head->next); head->next->next = head; head->next = NULL; return now; } };
Python3(解法1遍历形式):
class Solution: def reverseList(self, head: ListNode) -> ListNode: newList = None while(head != None): tmp = head.next head.next = newList newList = head head = tmp return newList
225. 用队列实现栈(简单)
【分类】:队列、模拟
【题解】:
解法1:直接用deque做即可,因为是双端队列,栈该有的操作它都有。
解法2:由于栈是先进后出,队列是先进先出,所以每次有元素进入队列的时候只需要把底下的元素抽上来放到上面,让本次进的元素压在最下面,那么每次取队首元素即是栈顶元素。
【代码】:
C++(解法1):
1 class MyStack { 2 public: 3 /** Initialize your data structure here. */ 4 deque<int>dq; 5 MyStack() { 6 7 } 8 9 /** Push element x onto stack. */ 10 void push(int x) { 11 dq.push_back(x); 12 } 13 14 /** Removes the element on top of the stack and returns that element. */ 15 int pop() { 16 int x = dq.back(); 17 dq.pop_back(); 18 return x; 19 } 20 21 /** Get the top element. */ 22 int top() { 23 return dq.back(); 24 } 25 26 /** Returns whether the stack is empty. */ 27 bool empty() { 28 return dq.empty(); 29 } 30 }; 31 32 /** 33 * Your MyStack object will be instantiated and called as such: 34 * MyStack* obj = new MyStack(); 35 * obj->push(x); 36 * int param_2 = obj->pop(); 37 * int param_3 = obj->top(); 38 * bool param_4 = obj->empty(); 39 */
Python3(解法2):
1 class MyStack: 2 3 def __init__(self): 4 """ 5 Initialize your data structure here. 6 """ 7 self.ls = [] 8 9 def push(self, x: int) -> None: 10 """ 11 Push element x onto stack. 12 """ 13 self.ls.append(x) 14 l = len(self.ls) 15 while l > 1: 16 self.ls.append(self.ls[0]) 17 self.ls.pop(0) 18 l = l - 1 19 20 21 def pop(self) -> int: 22 """ 23 Removes the element on top of the stack and returns that element. 24 """ 25 return self.ls.pop(0) 26 27 28 29 def top(self) -> int: 30 """ 31 Get the top element. 32 """ 33 return self.ls[0] 34 35 36 def empty(self) -> bool: 37 """ 38 Returns whether the stack is empty. 39 """ 40 if len(self.ls) > 0: 41 return False 42 else: 43 return True 44 45 46 47 48 # Your MyStack object will be instantiated and called as such: 49 # obj = MyStack() 50 # obj.push(x) 51 # param_2 = obj.pop() 52 # param_3 = obj.top() 53 # param_4 = obj.empty()
300. 最长上升子序列(中等)
【分类】:动态规划、二分
【题解】:
解法1:设dp[i]为以nums[i]结尾的最长上升子序列长度。
解法2:维护一个数组v即最终的最优数列,v[i]代表当长度为i+1时最后一个元素的最小值。可能这么讲不太明白,我以样例为例。
原数组a:[10,9,2,5,3,7,101,18],每当我们遍历到一个元素时,我们找到能在v中插入的最佳位置,哪个是最佳位置呢?
当i = 0时,a[i] = 10,直接插入v数组中,v = [10]
当i = 1时,a[i] = 9,那么显然9不可能插在10的后面,但是又要维护这个序列的序号是递增的所以也不可能插在10的前面,很显然9比10小,也就是说后面遇到比9大的数字的可能性比10大,比如后面遇到一个10,那么如果v中是9的话还能再插入,如果是10的话就不能了,所以我们现在要把10替换成9,那么v = [9]
当i = 2时,a[i] = 2,同理v = [2]
当i = 3时,a[i] = 5,此时5比2大,所以可以插在后面v = [2, 5]
以此类推
v = [2, 5,7, 18]
那么问题来了怎样快速确定v中有没有比当前a[i]大的数呢,因为v是有序的,所以显然可以用二分,这个二分可以自己写当然也可以直接用函数lower_bound()。
【代码】:
C++(解法2):
1 class Solution { 2 public: 3 int lengthOfLIS(vector<int>& nums) { 4 vector<int>v; 5 if (nums.size() == 0)return 0; 6 v.push_back(nums[0]); 7 for (int i = 1; i < nums.size(); i++) 8 { 9 int pos = lower_bound(v.begin(), v.end(), nums[i]) - v.begin(); 10 if (pos == v.size())v.push_back(nums[i]); 11 else if (pos < v.size())v[pos] = nums[i]; 12 } 13 return v.size(); 14 } 15 };
Python3(解法1):
1 class Solution: 2 def lengthOfLIS(self, nums: List[int]) -> int: 3 l = len(nums) 4 dp = [0] * l 5 ans = 0 6 for i in range(l): 7 for j in range(0, i): 8 if nums[i] > nums[j]: 9 dp[i] = max(dp[i], dp[j]) 10 dp[i] += 1 11 ans = max(ans, dp[i]) 12 return ans;
409. 最长回文串(简单)
【分类】:思维、模拟
【题解】:刚开始没看清题目,还以为是让我求该字符串中最大回文串的长度。其实是通过字符串提供的字母组合一个最大回文串,这样就简单多了,如果该字符有偶数个那么肯定能构成回文串,如果是奇数个只能就只能是某个字符有奇数个,其他都必须是偶数个。
【代码】:
C++:
1 class Solution { 2 public: 3 map<char, int>mp; 4 int longestPalindrome(string s) { 5 int len = s.size(), sum = 0, f = 0; 6 for (int i = 0; i < len; i++) 7 mp[s[i]]++; 8 map<char, int>::iterator it; 9 for (it = mp.begin(); it != mp.end(); it++) 10 { 11 if (it->second % 2 != 0) 12 { 13 if (!f) 14 { 15 f = 1; 16 sum += it->second; 17 } 18 else sum += it->second - 1; 19 } 20 else sum += it->second; 21 } 22 return sum; 23 } 24 };
Python3:
1 class Solution: 2 def longestPalindrome(self, s: str) -> int: 3 l = len(s) 4 mp = {} 5 ans = 0 6 f = 0 7 for a in s: 8 if a in mp: 9 mp[a] = mp[a] + 1 10 else: 11 mp[a] = 1 12 for k, v in mp.items(): 13 if v % 2 != 0: 14 if f == 0: 15 f = 1 16 ans += v 17 else: 18 ans += v - 1 19 else: ans += v 20 return ans
543. 二叉树的直径(简单)
【分类】:dfs
【题解】:以任意节点为父节点的直径是它的左右子树的最大深度之和,那么我们只要在搜索每个节点的时候维护这样的一个最大值即可。
【代码】:
C++:
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 = 0; 13 int diameterOfBinaryTree(TreeNode* root) { 14 int d = dfs(root); 15 return ans; 16 17 } 18 int dfs(TreeNode *root) 19 { 20 if (root == NULL)return 0; 21 int l = dfs(root->left); 22 int r = dfs(root->right); 23 ans = max (ans, l + r); 24 return max(l, r) + 1; 25 } 26 };
Python3:
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 __init__(self): 10 self.ans = 0 11 def dfs(self, root): 12 if not root: 13 return 0 14 l = self.dfs(root.left) 15 r = self.dfs(root.right) 16 self.ans = max(self.ans, l + r) 17 return max(l, r) + 1 18 def diameterOfBinaryTree(self, root: TreeNode) -> int: 19 d = self.dfs(root) 20 return self.ans
836. 矩形重叠(简单)
【分类】:思维、分类
【题解】:需要用到逆向思维,因为两个矩形重叠的情况很多,所以我们可以反过来思考不重叠的情况,那么就只有两个矩形平行分开或竖直分开,除去这两种情况就都是重叠了。
【代码】:
C++:
1 class Solution { 2 public: 3 bool isRectangleOverlap(vector<int>& rec1, vector<int>& rec2) { 4 if (rec1[2] <= rec2[0] || rec2[2] <= rec1[0])return false; 5 else if (rec1[3] <= rec2[1] || rec2[3] <= rec1[1])return false; 6 else return true; 7 } 8 };
Python3:
1 class Solution: 2 def isRectangleOverlap(self, rec1: List[int], rec2: List[int]) -> bool: 3 if (rec1[2] <= rec2[0] or rec2[2] <= rec1[0]): 4 return False 5 elif (rec1[3] <= rec2[1] or rec2[3] <= rec1[1]): 6 return False 7 else: 8 return True
876. 链表的中间结点(简单)
【分类】:思维
【题解】:
解法1:按照常规思维只要先遍历一遍链表知道长度,然后再遍历一遍链表即可找到中间位置。
解法2:快慢指针。说实话没看题解真没想到,看到后恍然大悟,其实只要遍历一次即可,即快指针每次走两个单位,慢指针每次走一个单位,当快指针走完链表后慢指针就刚刚到中间位置。
【代码】:
C++(解法1):
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* middleNode(ListNode* head) { 12 int num = 0; 13 ListNode *node = head; 14 while(node != NULL) 15 { 16 num++; 17 node = node->next; 18 } 19 num /= 2; 20 while(num--) 21 { 22 head = head->next; 23 } 24 return head; 25 } 26 };
Python3(解法2):
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 middleNode(self, head: ListNode) -> ListNode: 9 slow = head 10 fast = head 11 while (fast and fast.next): 12 fast = fast.next.next 13 slow = slow.next 14 return slow
892. 三维形体的表面积(简单)
【分类】:数学
【题解】:所有立方体的表面积-重叠面积。关键是重叠面积怎么计算,重叠面积分为两部分,一部分是自身那一列重叠的面积,另一部分是和周围有接触的列的重叠面积。
【代码】:
C++:
1 class Solution { 2 public: 3 int surfaceArea(vector<vector<int>>& grid) { 4 int num = 0; 5 int r = 0; 6 int row = grid.size(), col = grid[0].size(); 7 for (int i = 0; i < row; i++) 8 { 9 for (int j = 0; j < col; j++) 10 { 11 num += grid[i][j]; 12 if (grid[i][j] > 0)r += (grid[i][j] - 1) * 2; 13 if (i - 1 >= 0)r += min(grid[i - 1][j], grid[i][j]); 14 if (i + 1 < row) r += min(grid[i + 1][j], grid[i][j]); 15 if (j - 1 >= 0)r += min(grid[i][j - 1], grid[i][j]); 16 if (j + 1 < col) r += min(grid[i][j + 1], grid[i][j]); 17 } 18 } 19 return (num * 6 - r); 20 } 21 };
Python3:
1 class Solution: 2 def surfaceArea(self, grid: List[List[int]]) -> int: 3 num = 0 4 r = 0 5 row = len(grid) 6 col = len(grid[0]) 7 for i in range(row): 8 for j in range(col): 9 num += grid[i][j]; 10 if (grid[i][j] > 0): 11 r += (grid[i][j] - 1) * 2; 12 if (i - 1 >= 0): 13 r += min(grid[i - 1][j], grid[i][j]); 14 if (i + 1 < row): 15 r += min(grid[i + 1][j], grid[i][j]); 16 if (j - 1 >= 0): 17 r += min(grid[i][j - 1], grid[i][j]); 18 if (j + 1 < col): 19 r += min(grid[i][j + 1], grid[i][j]); 20 return (num * 6 - r);
914. 卡牌分组(简单)
【分类】:数学、gcd
【题解】:理解后即可转换题意为求取这组数据中每个不同的数字的个数的最大公约数,如果最大公约数>1则输出True,反之输出False。这里求取最大公约数记得用辗转相除法哦。
【代码】:
C++:
1 class Solution { 2 public: 3 int gcd(int a, int b) 4 { 5 int r; 6 while(b > 0) 7 { 8 r = a % b; 9 a = b; 10 b = r; 11 } 12 return a; 13 } 14 bool hasGroupsSizeX(vector<int>& deck) { 15 map<int, int>mp; 16 for (int i = 0; i < deck.size(); i++) 17 mp[deck[i]]++; 18 map<int, int>::iterator it = mp.begin(); 19 int gd = it->second; 20 for (;it != mp.end(); it++) 21 gd = gcd(gd, it->second); 22 if (gd == 1)return false; 23 else return true; 24 } 25 };
Python3:
1 class Solution: 2 def gcd(self, a, b): 3 while b > 0: 4 r = a % b 5 a = b 6 b = r 7 return a 8 def hasGroupsSizeX(self, deck: List[int]) -> bool: 9 mp = {} 10 for x in deck: 11 if x not in mp: 12 mp[x] = 1 13 else: 14 mp[x] += 1 15 ls = list(mp.values()) 16 gd = ls[0] 17 for x in ls: 18 gd = self.gcd(x, gd) 19 if gd == 1: 20 return False 21 else: 22 return True
994. 腐烂的橘子(简单)
【分类】:bfs
【题解】:很经典的广搜题。
【代码】:
C++:
1 class Solution { 2 public: 3 struct Node{ 4 int x, y, v; 5 }; 6 int vis[15][15] = {0}; 7 int dirx[4] = {0, 0, 1, -1}; 8 int diry[4] = {1, -1, 0, 0}; 9 int orangesRotting(vector<vector<int>>& grid) { 10 int m = grid.size(); 11 int n = grid[0].size(); 12 queue<Node>q; 13 int num = 0; 14 for (int i = 0; i < m; i++) 15 { 16 for (int j = 0; j < n; j++) 17 { 18 if (grid[i][j] == 2) 19 { 20 q.push({i, j, 0}); 21 vis[i][j] = 1; 22 } 23 else if (grid[i][j] == 1)num++; 24 } 25 } 26 int ans = 0; 27 while(!q.empty()) 28 { 29 Node t = q.front(); 30 q.pop(); 31 ans = max(ans, t.v); 32 for (int i = 0; i < 4; i++) 33 { 34 int xx = t.x + dirx[i]; 35 int yy = t.y + diry[i]; 36 if (xx >=0 && xx < m && yy >= 0 && yy < n && !vis[xx][yy] && grid[xx][yy] == 1) 37 { 38 vis[xx][yy] = 1; 39 q.push({xx, yy, t.v + 1}); 40 num--; 41 } 42 } 43 } 44 if (num != 0)return -1; 45 else return ans; 46 } 47 };
Python3:
1 class Solution: 2 def orangesRotting(self, grid: List[List[int]]) -> int: 3 dirx = [0, 0, 1, -1] 4 diry = [1, -1, 0, 0] 5 n = len(grid) 6 m = len(grid[0]) 7 ls = [] 8 ans = 0 9 num = 0 10 for i in range(n): 11 for j in range(m): 12 if (grid[i][j] == 2): 13 ls.append([i, j, 0]) 14 elif (grid[i][j] == 1): 15 num += 1 16 while(len(ls) > 0): 17 t = ls.pop(0) 18 ans = max(ans, t[2]) 19 for i in range(4): 20 xx = t[0] + dirx[i] 21 yy = t[1] + diry[i] 22 if (xx >=0 and xx < n and yy >=0 and yy < m and grid[xx][yy] == 1): 23 grid[xx][yy] = 2 24 ls.append([xx, yy, t[2] + 1]) 25 num -= 1 26 if num > 0: 27 return -1 28 else: 29 return ans
999. 可以被一步捕获的棋子数(简单)
【分类】:模拟
【题解】:理解题意即可,分别计算R的四个方向,如果碰到边界或B退出循环,如果碰到p那么num+1退出循环(因为抓到一个就会停下)。
【代码】:
C++:
1 class Solution { 2 public: 3 int numRookCaptures(vector<vector<char>>& board) { 4 int n = board.size(); 5 int m = board[0].size(); 6 int x, y, num = 0, xx, yy; 7 for (int i = 0; i < n; i++) 8 { 9 for (int j = 0; j < m; j++) 10 { 11 if (board[i][j] == 'R') 12 { 13 x = i; 14 y = j; 15 break; 16 } 17 } 18 } 19 xx = x; 20 while(xx > 0) 21 { 22 xx--; 23 if (board[xx][y] == 'p') 24 { 25 num++; 26 break; 27 } 28 else if (board[xx][y] == 'B')break; 29 } 30 xx = x; 31 while(xx + 1 < n) 32 { 33 xx++; 34 if (board[xx][y] == 'p') 35 { 36 num++; 37 break; 38 } 39 else if (board[xx][y] == 'B')break; 40 } 41 yy = y; 42 while(yy > 0) 43 { 44 yy--; 45 if (board[x][yy] == 'p') 46 { 47 num++; 48 break; 49 } 50 else if (board[x][yy] == 'B')break; 51 } 52 yy = y; 53 while(yy + 1 < m) 54 { 55 yy++; 56 if (board[x][yy] == 'p') 57 { 58 num++; 59 break; 60 } 61 else if (board[x][yy] == 'B')break; 62 } 63 return num; 64 } 65 };
Python3:
1 class Solution: 2 def numRookCaptures(self, board: List[List[str]]) -> int: 3 n = len(board) 4 m = len(board) 5 x, y, num = 0, 0, 0 6 for i in range(n): 7 for j in range(m): 8 if board[i][j] == 'R': 9 x = i 10 y = j 11 break 12 xx = x 13 while xx > 0: 14 xx -= 1 15 if board[xx][y] == 'B':break 16 elif board[xx][y] == 'p': 17 num += 1 18 break; 19 xx = x 20 while xx + 1 < n: 21 xx += 1 22 if board[xx][y] == 'B':break 23 elif board[xx][y] == 'p': 24 num += 1 25 break; 26 yy = y 27 while yy > 0: 28 yy -= 1 29 if board[x][yy] == 'B':break 30 elif board[x][yy] == 'p': 31 num += 1 32 break; 33 yy = y 34 while yy + 1 < m: 35 yy += 1 36 if board[x][yy] == 'B':break 37 elif board[x][yy] == 'p': 38 num += 1 39 break; 40 return num
1013. 将数组分成和相等的三个部分(简单)
【分类】:思维、模拟
【题解】:直接暴力做就可以啦,首先排除不能分的情况,即所有所有数之和不能被3整除。然后直接找前两组等于和/3的数,如果还有数字被剩下那么久可以分成三个部分。
【代码】:
C++:
1 class Solution { 2 public: 3 bool canThreePartsEqualSum(vector<int>& A) { 4 int len = A.size(), i, sum = 0; 5 for (i = 0; i < len; i++) 6 { 7 sum += A[i]; 8 } 9 if (sum % 3 != 0)return false; 10 else 11 { 12 sum /= 3; 13 int t = 0; 14 for (i = 0; i < len; i++) 15 { 16 t += A[i]; 17 if (t == sum)break; 18 } 19 if (t != sum)return false; 20 t = 0; 21 for (i = i + 1; i < len; i++) 22 { 23 t += A[i]; 24 if (t == sum)break; 25 } 26 if (i >= len - 1)return false; 27 else return true; 28 } 29 } 30 };
Python3:
1 class Solution: 2 def canThreePartsEqualSum(self, A: List[int]) -> bool: 3 s = 0 4 for x in A: 5 s += x 6 if (s % 3 != 0): 7 return False 8 else: 9 s /= 3 10 t = 0 11 l = len(A) 12 for i in range(l): 13 t += A[i]; 14 if (t == s):break 15 if t != s: 16 return False; 17 t = 0 18 for x in range(i + 1, l): 19 t += A[x]; 20 if (t == s):break 21 if (x >= l - 1): 22 return False 23 else: 24 return True
1071. 字符串的最大公因子(简单)
【分类】:思维、模拟
【题解】:只要判断两个字符串是否是两字符串最大公因数串的子串即可。
【代码】:
C++:
1 class Solution { 2 public: 3 string gcdOfStrings(string str1, string str2) { 4 int l1 = str1.size(), l2 = str2.size(); 5 int gd = __gcd(l1, l2), f = 0; 6 string s = str1.substr(0, gd), t; 7 for (int i = 0; i < l1; i += gd) 8 { 9 t = ""; 10 for (int j = i; j < i + gd; j++) 11 t += str1[j]; 12 if (t != s) 13 { 14 f = 1; 15 break; 16 } 17 } 18 if (t != s || f == 1)return ""; 19 for (int i = 0; i < l2; i += gd) 20 { 21 t = ""; 22 for (int j = i; j < i + gd; j++) 23 t += str2[j]; 24 if (t != s) 25 { 26 f = 1; 27 break; 28 } 29 } 30 if (t != s || f == 1)return ""; 31 else return s; 32 } 33 };
Python3:
1 class Solution: 2 def gcd(self, a, b): 3 while b > 0: 4 t = a % b 5 a = b 6 b = t 7 return a 8 def gcdOfStrings(self, str1: str, str2: str) -> str: 9 l1 = len(str1) 10 l2 = len(str2) 11 gd = self.gcd(l1, l2) 12 s = str1[0: gd] 13 p = "" 14 f = 0 15 for i in range(0, l1, gd): 16 p = "" 17 for j in range(i, i + gd): 18 p = p + str1[j] 19 if (p != s): 20 f = 1 21 break 22 if (p != s or f == 1):return "" 23 for i in range(0, l2, gd): 24 p = "" 25 for j in range(i, i + gd): 26 p = p + str2[j] 27 if (p != s): 28 f = 1 29 break 30 if (p != s or f == 1):return "" 31 else: return s 32
1103. 分糖果 II(简单)
【分类】:模拟
【题解】:直接根据题意模拟即可。由于编号上存在循环,用到(i + 1)% 人数。当然也可以通过推数学公式来求。
【代码】:
C++:
1 class Solution { 2 public: 3 vector<int> distributeCandies(int candies, int num_people) { 4 vector<int>v; 5 int i = 0, num = 1; 6 for (int i = 0; i < num_people; i++) 7 v.push_back(0); 8 while(candies > 0) 9 { 10 v[i] += num; 11 candies -= num; 12 if (candies > num + 1)num++; 13 else num = candies; 14 i = (i + 1) % num_people; 15 } 16 return v; 17 } 18 };
Python3:
1 class Solution: 2 def distributeCandies(self, candies: int, num_people: int) -> List[int]: 3 ans = [] 4 for i in range(num_people): 5 ans.append(0) 6 num = 1 7 i = 0 8 while(candies): 9 ans[i] += num 10 candies -= num 11 if (candies > num + 1): 12 num += 1 13 else: num = candies 14 i = (i + 1) % num_people 15 return ans
1160. 拼写单词(简单)
【分类】:模拟
【题解】:根据题意直接做即可,记录字母表中每个字母的个数,只要统计每个单词出现的字母的个数小于等于字母表就可以啦。不得不说python真是太方便了!!
【代码】:
C++:
1 class Solution { 2 public: 3 int countCharacters(vector<string>& words, string chars) { 4 map<char, int> mp; 5 for (int i = 0; i < chars.size(); i++) 6 mp[chars[i]]++; 7 int ans = 0; 8 for (int i = 0; i < words.size(); i++) 9 { 10 int f = 0; 11 map<char, int>mp2 = mp; 12 for (int j = 0; j < words[i].size(); j++) 13 { 14 if (mp2[words[i][j]] >= 1) 15 mp2[words[i][j]]--; 16 else 17 { 18 f = 1; 19 break; 20 } 21 } 22 if (!f) 23 ans += words[i].size(); 24 } 25 return ans; 26 } 27 };
Python3:
1 class Solution: 2 def countCharacters(self, words: List[str], chars: str) -> int: 3 c = collections.Counter(chars) 4 ans = 0 5 for s in words: 6 w = collections.Counter(s) 7 if all([c[i] >= w[i] for i in w]): 8 ans += len(s) 9 return ans
1162. 地图分析(中等)
【分类】:bfs
【题解】:
解法1:最普通的bfs,通过遍历地图每遍历到一个0时进入bfs,因为最近的1肯定是最先被搜索到的,所以一旦搜索到了1即可退出,并计算两个位置的距离。
解法2:不需要vis记录,我们可以先记录一个1的队列,通过这个队列去搜索0,因为我们最后要找的是最大距离,每遇到一个0就进队,当队列为空即遍历完整幅图时,返回答案。
【代码】:
C++(解法1):
1 class Solution { 2 public: 3 int vis[105][105]; 4 int dirx[4] = {0, 0, 1, -1}; 5 int diry[4] = {1, -1, 0, 0}; 6 int bfs(vector<vector<int>>& grid, int x, int y, int n, int m) 7 { 8 queue<pair<int, int>>q; 9 q.push(make_pair(x, y)); 10 while(!q.empty()) 11 { 12 pair<int, int> p = q.front(); 13 int xx = p.first, yy = p.second; 14 q.pop(); 15 if (grid[xx][yy] == 1) 16 return (abs(x - xx) + abs(y -yy)); 17 for(int i = 0; i < 4; i++) 18 { 19 int tx = xx + dirx[i]; 20 int ty = yy + diry[i]; 21 if (tx >= 0 && tx < n && ty >= 0 && ty < m && !vis[tx][ty] ) 22 { 23 vis[tx][ty] = 1; 24 q.push(make_pair(tx, ty)); 25 } 26 } 27 } 28 return -1; 29 } 30 int maxDistance(vector<vector<int>>& grid) { 31 int n = grid.size(), m = grid[0].size(); 32 int ans = -1; 33 for (int i = 0; i < n; i++) 34 { 35 for (int j = 0; j < m; j++) 36 { 37 if (!grid[i][j]) 38 { 39 memset(vis, 0, sizeof(vis)); 40 ans = max(ans, bfs(grid, i, j, n, m)); 41 } 42 } 43 } 44 return ans; 45 } 46 };
Python3(解法2):
1 class Solution: 2 from collections import deque 3 def maxDistance(self, grid: List[List[int]]) -> int: 4 n = len(grid) 5 dire = [(0, 1), (0, -1), (1, 0), (-1, 0)] 6 ans = -1 7 q = deque((i, j) for i in range(n) for j in range(n) if grid[i][j] == 1) 8 if len(q) == 0 or len(q) == n ** 2: return -1 9 while q: 10 for i in range(len(q)): 11 x, y = q.popleft() 12 for dx, dy in dire: 13 xx, yy = x + dx, y + dy 14 if xx >= 0 and xx < n and yy >= 0 and yy < n and grid[xx][yy] == 0: 15 grid[xx][yy] -= 1 16 q.append((xx, yy)) 17 ans += 1 18 return ans
面试题 01.06. 字符串压缩(简单)
【分类】:模拟
【题解】:不难。根据题意直接做就好啦。
【代码】:
C++:
1 class Solution { 2 public: 3 string compressString(string S) { 4 string ans = ""; 5 if (S == "")return ""; 6 int num = 1; 7 for (int i = 1; i < S.size(); i++) 8 { 9 if (S[i] != S[i - 1]) 10 { 11 ans += S[i - 1]; 12 ans += to_string(num); 13 num = 1; 14 } 15 else num++; 16 } 17 ans += S[S.size() - 1]; 18 ans += to_string(num); 19 if (ans.size() >= S.size())return S; 20 else return ans; 21 } 22 };
Python3:
1 class Solution: 2 def compressString(self, S: str) -> str: 3 ans = "" 4 if S == "": return "" 5 num = 1 6 for i in range(1, len(S)): 7 if (S[i] != S[i - 1]): 8 ans += S[i - 1] 9 ans += str(num) 10 num = 1 11 else: num += 1 12 ans += S[len(S) - 1] 13 ans += str(num) 14 if len(ans) >= len(S): return S 15 else: return ans
面试题 10.01. 合并排序的数组(简单)
【分类】:排序、思维
【题解】:
解法1:直接将第二个数组放入第一个数组中然后排序。
解法2:从两个数组的最后一个元素开始比起,谁大就往后面移,当然不要忘记有种情况是第一个数组的所有数都比第二个大,所以退出循环后记得把第二个数组的元素放进去。
【代码】:
C++(解法1):
1 class Solution { 2 public: 3 void merge(vector<int>& A, int m, vector<int>& B, int n) { 4 int len = A.size() - B.size(); 5 for(int i = 0; i < B.size(); i++) 6 A[len + i] = B[i]; 7 sort(A.begin(), A.end()); 8 } 9 };
Python3(解法2):
1 class Solution: 2 def merge(self, A: List[int], m: int, B: List[int], n: int) -> None: 3 i = m - 1 4 j = n - 1 5 while(i >= 0 and j >= 0): 6 if A[i] >= B[j]: 7 A[i + j + 1] = A[i] 8 i -= 1 9 else: 10 A[i + j + 1] = B[j] 11 j -= 1 12 while(j >= 0): 13 A[i + j + 1] = B[j] 14 j -= 1
面试题 17.16. 按摩师(简单)
【分类】:动态规划
【题解】:我不明白这题为什么简单!!我觉得所有dp都是难的!!
设dp[i]为0-i这个区间内的最大值。那么可以分类讨论:
(1)如果取nums[i],那么nums[i-1]就不能取,也就是说状态得从dp[i-2]传过来,所以dp[i] = dp[i-2] + nums[i]
(2)如果不取nums[i],那么状态就可以从ddp[i-1]传过来,所以dp[i] = dp[i - 1]
最后取这两种情况的最大值即可。
【代码】:
C++(解法1):
1 class Solution { 2 public: 3 int dp[10005]; 4 int massage(vector<int>& nums) { 5 int len = nums.size(); 6 if (len == 0)return 0; 7 else if (len == 1)return nums[0]; 8 dp[0] = nums[0]; 9 dp[1] = max(nums[0], nums[1]); 10 for (int i = 2; i < len; i++) 11 dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]); 12 return dp[len - 1]; 13 } 14 };
Python3(解法2):
1 class Solution: 2 def massage(self, nums: List[int]) -> int: 3 n = len(nums) 4 if n == 0: return 0 5 elif n == 1: return nums[0] 6 dp = [0] * (n + 1) 7 dp[0] = nums[0] 8 dp[1] = max(nums[0], nums[1]) 9 for i in range(2, n): 10 dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]) 11 return dp[n - 1]
面试题40. 最小的k个数(简单)
【分类】:排序
【题解】:
解法1:直接用内置sort排序然后输出即可。
解法2:很经典的堆排序题,用大顶堆做。
【代码】:
C++(解法1):
1 class Solution { 2 public: 3 vector<int> getLeastNumbers(vector<int>& arr, int k) { 4 sort(arr.begin(), arr.end()); 5 vector<int>ans; 6 for (int i = 0; i < k; i++) 7 ans.push_back(arr[i]); 8 return ans; 9 } 10 };
Python3(解法2):
1 class Solution: 2 def getLeastNumbers(self, arr: List[int], k: int) -> List[int]: 3 if (k == 0): return list() 4 # 由于python里的heapq是小根堆,所以需要取相反数 5 hp = [-x for x in arr[:k]] 6 # 让列表具备堆特性 7 heapq.heapify(hp) 8 for i in range(k, len(arr)): 9 if -hp[0] > arr[i]: 10 heapq.heappop(hp) 11 heapq.heappush(hp, -arr[i]) 12 ans = [-x for x in hp] 13 return ans
面试题57 - II. 和为s的连续正数序列(简单)
【分类】:思维
【题解】:滑动窗口法,虽然n的范围在10^5但是实际上易得枚举数字只要到n/2 + 1即可,然后我们就可以设置一个左右边界l,r,将l到r-1所有的数加起来,如果超过target那么l 就向右移,也就是减去了l,同理如果小于target那r就向右移。
【代码】:
C++:
1 class Solution { 2 public: 3 vector<vector<int>> findContinuousSequence(int target) { 4 int h = (target / 2) + 1; 5 int l = 1, r = 1, sum = 0; 6 vector<vector<int> >ans; 7 while(l<=h) 8 { 9 if (sum > target) 10 { 11 sum -= l; 12 l++; 13 } 14 else if (sum < target) 15 { 16 sum += r; 17 r++; 18 } 19 else 20 { 21 vector<int>v; 22 for (int i = l; i < r; i++) 23 v.push_back(i); 24 ans.push_back(v); 25 sum -= l; 26 l++; 27 } 28 } 29 return ans; 30 } 31 };
Python3:
1 class Solution: 2 def findContinuousSequence(self, target: int) -> List[List[int]]: 3 h = (target / 2) + 1 4 ans = [] 5 l = 1 6 r = 1 7 s = 0 8 while l <= h: 9 if s < target: 10 s += r 11 r += 1 12 elif s > target: 13 s -= l 14 l += 1 15 else: 16 a = [] 17 for i in range(l, r): 18 a.append(i) 19 ans.append(a) 20 s -= l 21 l += 1 22 return ans
面试题59 - II. 队列的最大值(中等)
【分类】:队列
【题解】:重新维护一个双端队列d用来维护队列的最大值,保证d的队首元素为当前队列的最大值,每当一个元素进入队列时要与d中的队尾元素比较,如果比它小,那么直接插入,如果比它大那么要弹出d中的元素直到找到比它小的位置。那么为什么要这么操作呢?
首先队列时先进先出的,比如我当前队列是1 2 3 5,只要5不出队列那么最大值就一直是5,此时如果再入队一个6,那么为了保证只要6不出队列最大值就是6就得把5从d中弹出,让d的队首元素时6。此时如果再来个3,我肯定不能把6弹出去,因为此时q为1 2 3 5 6 3最大值仍然是6,那么当前面的1 2 3 5 6都被弹出去了的话最大值就变成了3,所以为了保证能做到这样,3得进入队列d。
【代码】:
C++:
1 class MaxQueue { 2 public: 3 queue<int>q; 4 deque<int>d; 5 MaxQueue() { 6 7 } 8 9 int max_value() { 10 if(d.empty())return -1; 11 else return d.front(); 12 } 13 14 void push_back(int value) { 15 q.push(value); 16 while(!d.empty() && d.back() < value) 17 d.pop_back(); 18 d.push_back(value); 19 } 20 21 int pop_front() { 22 if(q.empty())return -1; 23 else 24 { 25 int t = q.front(); 26 if (t == d.front())d.pop_front(); 27 q.pop(); 28 return t; 29 } 30 } 31 }; 32 33 /** 34 * Your MaxQueue object will be instantiated and called as such: 35 * MaxQueue* obj = new MaxQueue(); 36 * int param_1 = obj->max_value(); 37 * obj->push_back(value); 38 * int param_3 = obj->pop_front(); 39 */
Python3:
1 import queue 2 class MaxQueue: 3 4 def __init__(self): 5 self.d = queue.deque() 6 self.q = queue.Queue() 7 8 def max_value(self) -> int: 9 if self.d: return self.d[0] 10 else: return -1 11 12 def push_back(self, value: int) -> None: 13 while(self.d and self.d[-1] < value): 14 self.d.pop() 15 self.q.put(value) 16 self.d.append(value) 17 18 def pop_front(self) -> int: 19 if not self.d: return -1 20 ans = self.q.get() 21 if ans == self.d[0]:self.d.popleft() 22 return ans 23 24 25 26 27 # Your MaxQueue object will be instantiated and called as such: 28 # obj = MaxQueue() 29 # param_1 = obj.max_value() 30 # obj.push_back(value) 31 # param_3 = obj.pop_front()
面试题62. 圆圈中最后剩下的数字(简单)
【分类】:数学
【题解】:约瑟夫环问题。可以看这篇题解,感觉我以前也是一知半解,看完这个豁然开朗。
f(n,m) = 0, n = 1
f(n,m) = [ f(n-1, m) +m ] %n, n > 1
【代码】:
C++:
1 class Solution { 2 public: 3 int lastRemaining(int n, int m) { 4 int pos = 0; 5 for (int i = 2; i <= n; i++) 6 pos = (pos + m) % i; 7 return pos; 8 } 9 };
Python3:
1 class Solution: 2 def lastRemaining(self, n: int, m: int) -> int: 3 pos = 0 4 for i in range(2, n + 1): 5 pos = (pos + m) % i 6 return pos
------------恢复内容结束------------
[10,9,2,5,3,7,101,18]