Posted onEdited onInLeetCodeDisqus: Symbols count in article: 879Reading time ≈1 mins.
O(1) time O(1) space
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
from copy import deepcopy classSolution: defisValidSudoku(self, board: List[List[str]]) -> bool: v = [[False] * 10for _ inrange(9)] h = [[False] * 10for _ inrange(9)] b = [[False] * 10for _ inrange(9)] # v = [[False] * 10 for _ in range(9)] # h, b = deepcopy(v), deepcopy(v) for r inrange(9): for c inrange(9): x = board[r][c] if x != '.': x = int(x) # 巧妙! if v[c][x] or h[r][x] or b[r // 3 * 3 + c // 3][x]: returnFalse v[c][x] = h[r][x] = b[r // 3 * 3 + c // 3][x] = True returnTrue
用bitset替代hashtable遍历找重复即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution { public: boolisValidSudoku(vector<vector<char>>& board){ vector<bitset<9>> h(9), v(9), s(9); for (int r(0); r < 9; ++r) { for (int c(0); c < 9; ++c) { if (board[r][c] == '.') continue; int x = board[r][c] - '1'; if (h[r][x] || v[c][x] || s[r / 3 * 3 + c / 3][x]) returnfalse; h[r][x] = v[c][x] = s[r / 3 * 3 + c / 3][x] = true; } } returntrue; } };
Posted onEdited onInLeetCodeDisqus: Symbols count in article: 768Reading time ≈1 mins.
O(logn) time 找lower_bound
1 2 3 4 5 6 7 8 9 10
classSolution: defsearchInsert(self, nums: List[int], target: int) -> int: l, r = 0, len(nums) # 注意直接用左闭右开!! while l < r: m = l + (r - l) // 2 if nums[m] < target: l = m + 1 else: r = m return l
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution { public: intsearchInsert(vector<int>& nums, int target){ int n = nums.size(); int l = 0, r = n; // 直接用左闭右开 while (l < r) { int m = l + (r - l) / 2; if (target > nums[m]) { l = m + 1; } else { r = m; } } return l; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution { public: intsearchInsert(vector<int>& nums, int target){ int n = nums.size(); int l = 0, r = n - 1; while (l <= r) { int m = l + (r - l) / 2; if (nums[m] == target) { return m; } elseif (target > nums[m]) { l = m + 1; } else { r = m - 1; } } return l; } };
Posted onEdited onInLeetCodeDisqus: Symbols count in article: 1.1kReading time ≈1 mins.
O(logn) time
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution: defsearchRange(self, nums: List[int], target: int) -> List[int]: deffind(b, e, t): while b < e: m = b + (e - b) // 2 if nums[m] < t: b = m + 1 else: e = m return b n = len(nums) l = find(0, n, target) if l == n or nums[l] != target: return [-1, -1] return [l, find(l + 1, n, target + 1) - 1]
classSolution { public: vector<int> searchRange(vector<int>& nums, int target){ int n = nums.size(); int i = lb(nums, 0, n, target); if (i == n || nums[i] != target) return {-1, -1}; return {i, lb(nums, i, n, target + 1) - 1}; // 找大一号的数即可,且可以从下界找起 }
intlb(constvector<int> &nums, int l, int r, int target){ while (l < r) { int m = l + (r - l) / 2; if (nums[m] < target) { l = m + 1; } else { r = m; } } return l; } };
Posted onEdited onInLeetCodeDisqus: Symbols count in article: 873Reading time ≈1 mins.
binary search O(logn) 先判断左半边数多还是右半边数多,再对每一种情况分类讨论
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution: defsearch(self, nums: List[int], target: int) -> int: l, r = 0, len(nums) - 1 while (l <= r): m = l + (r - l) // 2 if nums[m] == target: return m elif nums[m] > nums[r]: if nums[l] <= target < nums[m]: r = m - 1 else: l = m + 1 else: if nums[m] < target <= nums[r]: l = m + 1 else: r = m - 1 return -1
classSolution { public: intlongestValidParentheses(string s){ int n = s.length(); vector<int> v{-1}; // 开始加入-1方便后面计算,比如"()()())" for (int i = 0; i < n; ++i) { if (s[i] == '(') { // 如果是"(",直接把下标入栈 v.push_back(i); } else { if (v.back() != -1 && s[v.back()] == '(') { // 如果是")",并且栈不为『空』或者栈顶是"(",证明有正确的匹配,将栈顶的"("的下标出栈 v.pop_back(); } else { // 否则证明是一个孤立无法匹配的")",将下标入栈 v.push_back(i); } } } v.push_back(n); // 最后入栈一个结尾长度下标,方便计算,比如")()()" int res = 0; for (int i = 1; i < v.size(); ++i) { res = max(res, v[i] - v[i - 1] - 1); // 只需要检查前后两个不匹配的括号之前的距离便可以找到最长的合法匹配的括号的长度 } return res; } };
进一步优化,不需要最后再扫一遍,每次找到一个合法匹配就可以直接更新res
1 2 3 4 5 6 7 8 9 10 11 12
classSolution: deflongestValidParentheses(self, s: str) -> int: stk, res = [-1], 0 for i, c inenumerate(s): if c == '(': stk.append(i) elif stk[-1] >= 0and s[stk[-1]] == '(': stk.pop() res = max(res, i - stk[-1]) else: stk.append(i) return res
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution { public: intlongestValidParentheses(string s){ int n = s.length(), res = 0; stack<int> stk{{-1}}; // 开始加入-1方便后面计算,比如"()()())" for (int i = 0; i < n; ++i) { if (s[i] == '(') { // 如果是"(",直接把下标入栈 stk.push(i); } elseif (stk.top() != -1 && s[stk.top()] == '(') { // 如果是")",并且栈不为『空』或者栈顶是"(",证明有正确的匹配,将栈顶的"("的下标出栈 stk.pop(); // 一定要先出栈再更新res res = max(res, i - stk.top()); // 当前是一个合法的匹配,更新res } else { // 否则证明是一个孤立无法匹配的")",将下标入栈 stk.push(i); } } return res; } };
classSolution: defnextPermutation(self, nums: List[int]) -> None: """ Do not return anything, modify nums in-place instead. """ n = len(nums) for i inrange(n - 2, -1, -1): if nums[i] < nums[i + 1]: break else: nums.reverse() return for j inrange(n - 1, i, -1): if nums[j] > nums[i]: nums[i], nums[j] = nums[j], nums[i] break l, r = i + 1, n - 1 while l < r: nums[l], nums[r] = nums[r], nums[l] l += 1 r -= 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution { public: voidnextPermutation(vector<int>& nums){ int n = nums.size(); int i = n - 1; while (i > 0 && nums[i - 1] >= nums[i]) --i; if (i == 0) { reverse(begin(nums), end(nums)); return; } int j = n - 1; while (nums[j] <= nums[i - 1]) --j; swap(nums[i - 1], nums[j]); reverse(begin(nums) + i, end(nums)); } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution { public: voidnextPermutation(vector<int>& nums){ int n = nums.size(); int i = n - 1; while (i > 0 && nums[i - 1] >= nums[i]) --i; if (i == 0) { reverse(begin(nums), end(nums)); return; } int j = lower_bound(begin(nums) + i, end(nums), nums[i - 1], greater()) - begin(nums) - 1; // 二分查找右边降序序列里倒数第一个比nums[i - 1]大的数的位置 swap(nums[i - 1], nums[j]); reverse(begin(nums) + i, end(nums)); } };
classSolution: deffindSubstring(self, s: str, words: List[str]) -> List[int]: ifnot s ornot words: return [] d = defaultdict(int) for w in words: d[w] += 1 n, m, l = len(s), len(words), len(words[0]) total, res = m * l, [] for i inrange(l): td, cnt = d.copy(), m for j inrange(i, n, l): # 应该是j + l <= n但是python里字符串切片越界也不影响 t = s[j:j + l] td[t] -= 1 if td[t] >= 0: cnt -= 1 if j - total >= i: t = s[j - total:j - total + l] td[t] += 1 if td[t] > 0: cnt += 1 if cnt == 0: res.append(j - total + l) return res
classSolution: defstrStr(self, haystack: str, needle: str) -> int: h, n = len(haystack), len(needle) if h < n: return -1 highest_power, hh, nh = 1, 0, 0 M, B = 2**31 - 1, 256 for i inrange(n): highest_power = (highest_power * B) % M hh = (hh * B + ord(haystack[i])) % M nh = (nh * B + ord(needle[i])) % M for i inrange(h - n + 1): if i >= 1: hh = (hh * B + M - ord(haystack[i - 1]) * highest_power % M + ord(haystack[i + n - 1])) % M if hh == nh: for j inrange(n): if haystack[i + j] != needle[j]: break else: return i return -1
classSolution { public: intstrStr(string haystack, string needle){ int h = haystack.length(), n = needle.length(); long M = INT_MAX, B = 256; if (h < n) return-1; long highest_power = 1, hh = 0, nh = 0; for (int i = 0; i < n; ++i) { highest_power = (highest_power * B) % M; nh = (nh * B + needle[i]) % M; hh = (hh * B + haystack[i]) % M; } for (int i = 0; i <= h - n; ++i) { if (i >= 1) { hh = (hh * B + M - haystack[i - 1] * highest_power % M + haystack[i + n - 1]) % M; // 这里highest_power是B的n次方,因为先整体左移再减高位,如果先减高位再整体左移就是n-1次方了 } if (hh == nh && haystack.substr(i, n) == needle) { return i; } } return-1; } };