def conv(data, k, stride, bias):
row, col = data.shape
krow, kcol = k.shape
res = []
for i in range(row-krow, stride):
rowlist = []
for j in range(col-kcol, stride):
curdata = data[i:i+krow, j:j+kcol]
rowlist.append(np.sum(np.multiply(curdata, k)) + bias)
res.append(rowlist)
return res
def psnr(img1, img2):
imgmse = np.mean((img1-img2)**2)
if imgmse == 0:
return 100
return 20 * math.log10(255 / math.sqrt(imgmse))
1. 两数之和
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
twoSumDic = dict()
for i in range(len(nums)):
if target-nums[i] in twoSumDic:
return [twoSumDic[target-nums[i]], i]
twoSumDic[nums[i]] = i
return []
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> twoSumMap;
int n = nums.size();
for (int i = 0; i<n; i++){
if (twoSumMap.find(target-nums[i]) != twoSumMap.end()){
return {twoSumMap[target-nums[i]], i};
}
twoSumMap[nums[i]] = i;
}
return {};
}
};
2. 两数相加+1
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
# def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
# flag = 0
# out = ListNode()
# tem = out
# while l1 or l2 or flag:
# if l1 and l2:
# tem.next = ListNode((l1.val + l2.val + flag) % 10)
# flag = (l1.val + l2.val + flag) // 10
# l1 = l1.next
# l2 = l2.next
# elif l1:
# tem.next = ListNode((l1.val + flag) % 10)
# flag = (l1.val + flag) // 10
# l1 = l1.next
# elif l2:
# tem.next = ListNode((l2.val + flag) % 10)
# flag = (l2.val + flag) // 10
# l2 = l2.next
# elif flag:
# tem.next = ListNode(flag)
# flag = 0
# tem = tem.next
# return out.next
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
out = tem = ListNode()
R = 0
while l1 or l2 or R:
if l1:
R += l1.val
l1 = l1.next
if l2:
R += l2.val
l2 = l2.next
tem.next = ListNode(R % 10)
R = R // 10
tem = tem.next
return out.next
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
// ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
// ListNode* out = new ListNode(0);
// ListNode* tem = out;
// int flag = 0;
// while (l1 || l2){
// if (l1 && l2){
// tem->next = new ListNode((l1->val + l2->val + flag) % 10);
// flag = (l1->val+ l2->val+flag) / 10;
// l1 = l1->next;
// l2 = l2->next;
// }else if (l1){
// tem->next = new ListNode((l1->val + flag) % 10);
// flag = (l1->val + flag) / 10;
// l1 = l1->next;
// }else if (l2){
// tem->next = new ListNode((l2->val + flag) % 10);
// flag = (l2->val + flag) / 10;
// l2 = l2->next;
// }
// tem = tem->next;
// }
// if (flag){
// tem->next = new ListNode(flag);
// }
// return out->next;
// }
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* out = new ListNode();
ListNode* tem = out;
int R = 0;
while (l1 or l2 or R){
if (l1){
R += l1->val;
l1 = l1->next;
}
if (l2){
R += l2->val;
l2 = l2->next;
}
tem->next = new ListNode(R % 10);
R = R / 10;
tem = tem->next;
}
return out->next;
}
};
3. 无重复字符的最长子串+1
class Solution:
def mystring(self, s):
ans = 0
subStr = ''
for curs in s:
for i in range(len(subStr)):
if subStr[i] == curs:
subStr = subStr[i+1:]
break
subStr += curs
ans = max(ans, len(subStr))
return ans
def myset(self, s):
setS = set()
ans, left = 0, 0
for i in range(len(s)):
if s[i] in setS:
while s[left] != s[i]:
setS.remove(s[left])
left +=1
left +=1
else:
setS.add(s[i])
ans = max(ans, i-left+1)
return ans
def mydic(self, s):
ans, left = 0, 0
dic = dict()
for i in range(len(s)):
if dic.get(s[i], 'no') != 'no':
while s[left] != s[i]:
del dic[s[left]]
left += 1
left += 1
else:
dic[s[i]] = 1
ans = max(ans, i-left+1)
return ans
def mydeque(self, s):
ans = 0
que = collections.deque()
for i in range(len(s)):
while s[i] in que:
que.popleft()
que.append(s[i])
ans = max(ans, len(que))
return ans
def lengthOfLongestSubstring(self, s: str) -> int:
return self.mystring(s)
# return self.myset(s)
# return self.mydic(s)
# return self.mydeque(s)
class Solution {
public:
int mymax(int a, int b){
if (a>=b) return a;
return b;
}
int mystring(string s){
int ans = 0;
string subS;
for (int j=0; j<s.size(); ++j){
for (int i=0; i<subS.size(); ++i){
if (s[j] == subS[i]){
subS = subS.substr(i+1, subS.size());
break;
}
}
subS += s[j];
ans = mymax(ans, subS.size());
}
return ans;
}
int myset(string s){
int ans=0, left=0;
unordered_set<char> setS;
for (int i=0; i<s.size(); ++i){
if (setS.find(s[i]) != setS.end()){
while (s[left] != s[i]){
setS.erase(s[left]);
left += 1;
}
left += 1;
}else{
setS.emplace(s[i]);
}
ans = mymax(ans, i-left+1);
}
return ans;
}
int mymap(string s){
int ans=0, left=0;
unordered_map<char, int> mapS;
for (int i=0; i<s.size(); ++i){
if (mapS.find(s[i]) != mapS.end()){
while (s[left] != s[i]){
mapS.erase(s[left]);
left += 1;
}
left += 1;
}
else{
mapS[s[i]] = 1;
ans = mymax(ans, i-left+1);
}
}
return ans;
}
int mydeque(string s){
int ans=0;
deque<char> que;
for (int i=0; i<s.size(); ++i){
while (true){
deque<char>::iterator it = find(que.begin(), que.end(), s[i]);
if (it != que.end()){
que.pop_front();
}else{
break;
}
}
que.push_back(s[i]);
ans = ans > que.size() ? ans:que.size();
}
return ans;
}
int lengthOfLongestSubstring(string s) {
// return mystring(s);
// return myset(s);
// return mymap(s);
return mydeque(s);
}
};
5. 最长回文子串+1
class Solution:
def longestPalindrome(self, s: str) -> str:
begin, end, res, n = 0, 1, 0, len(s)
def expend(i, j):
while i > 0 and j < n and s[i] == s[j]:
i -= 1
j += 1
return i, j
for i in range(n):
left1, right1 = expend(i, i)
left2, right2 = expend(i, i+1)
if end - begin < right1 - left1:
begin, end = left1, right1
if end - begin < right2 - left2:
begin, end = left2, right2
print(begin, end)
return s[begin+1:end]
class Solution:
def longestPalindrome(self, s: str) -> str:
ans = s[0]
for i in range(1, len(s)):
shift = 1
while i-shift>=0 and i+shift<= len(s)-1 and s[i-shift]==s[i+shift]:
shift += 1
ans = s[i-shift+1: i+shift] if (shift-1)*2+1>len(ans) else ans
if s[i] == s[i-1]:
shift = 1
while i-shift-1>=0 and i+shift <= len(s)-1 and s[i-shift-1] == s[i+shift]:
shift += 1
ans = s[i-shift: i+shift] if shift*2>len(ans) else ans
return ans
class Solution {
public:
string longestPalindrome(string s) {
string ans = s.substr(0, 1);
int n = s.size();
for (int i=1; i<n; ++i){
int shift=1;
while ((i-shift)>=0 && (i+shift)<= (n-1) && s[i-shift]==s[i+shift]){
shift += 1;
}
ans = (shift-1)*2+1>ans.size() ? s.substr(i-shift+1, shift*2-1) : ans;
if (s[i] == s[i-1]){
int shift = 1;
while ((i-1-shift)>=0 && (i+shift) <= (n-1) && s[i-1-shift]==s[i+shift]){
shift +=1;
}
ans = shift*2 > ans.size() ? s.substr(i-shift, shift*2) : ans;
}
}
return ans;
}
};
11. 盛最多水的容器+1
class Solution:
def maxArea(self, height: List[int]) -> int:
left, right = 0, len(height)-1
ans = 0
while left<right:
ans = max(ans, min(height[left], height[right])*(right-left))
if height[left] < height[right]:
left +=1
else:
right -= 1
return ans
class Solution {
public:
int maxArea(vector<int>& height) {
int left=0, right=height.size()-1, ans=0;
while (left < right){
ans = max(ans, min(height[left], height[right])*(right-left));
if (height[left] > height[right]){
right--;
}
else{
left++;
}
}
return ans;
}
};
15. 三数之和+1
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
ans = []
n = len(nums)
for i in range(n):
if i>0 and nums[i]==nums[i-1]:
continue
if nums[i]>0:
break
left, right = i+1, n-1
while left < right:
if nums[right] < 0:
break
curSum = nums[i] + nums[left] + nums[right]
if curSum > 0:
right -=1
elif curSum < 0:
left += 1
else:
if left > i+1 and nums[left] == nums[left-1]:
left += 1
continue
ans.append([nums[i], nums[left], nums[right]])
left += 1
return ans
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
sort(nums.begin(), nums.end());
int n = nums.size();
for (int i=0; i<n; ++i){
if (i>0 && nums[i]==nums[i-1]) continue;
if (nums[i] > 0) break;
int l = i+1, r = n-1;
while (l < r){
if (nums[r]<0) break;
int curSum = nums[i] + nums[l] + nums[r];
if (curSum>0){
--r;
}
else if (curSum<0){
++l;
}
else{
if (l > i+1 && nums[l]==nums[l-1]){
++l;
continue;
}
ans.push_back({nums[i], nums[l], nums[r]});
// if (ans.size()==0){
// ans.push_back({nums[i], nums[l], nums[r]});
// }
// else{
// vector lastans = ans.end()[-1];
// if (lastans[0] != nums[i] || lastans[1] != nums[l] || lastans[2] !=nums[r]){
// ans.push_back({nums[i], nums[l], nums[r]});
// }
// }
++l;
}
}
}
return ans;
}
};
17. 电话号码的字母组合+1
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
# # 队列
# if len(digits) == 0:
# return []
# letterTable = {'2':'abc','3':'def', '4':'ghi', '5':'jkl', '6':'mno',
# '7':'pqrs', '8':'tuv', '9':'wxyz'}
# ans = [""]
# for i in range(len(digits)):
# curAnsNum = len(ans)
# while curAnsNum > 0:
# curAns, ans = ans[0], ans[1:]
# # curAns = ans.pop(0)
# curDigit = letterTable[digits[i]]
# for j in range(len(curDigit)):
# ans.append(curAns+curDigit[j])
# curAnsNum -= 1
# return ans
# 回溯
if len(digits) == 0:
return []
letterTable = {'2':'abc','3':'def', '4':'ghi', '5':'jkl', '6':'mno',
'7':'pqrs', '8':'tuv', '9':'wxyz'}
ans = []
def backtrack(path, chooses):
if len(chooses) == 0:
ans.append(path)
return
else:
for choose in letterTable[chooses[0]]:
backtrack(path+choose, chooses[1:])
backtrack('', digits)
return ans
class Solution {
public:
// vector ans;
unordered_map<char, string> letterTable{{'2',"abc"},{'3',"def"},{'4',"ghi"} ,{'5',"jkl"} ,{'6',"mno"}, {'7',"pqrs"},{'8',"tuv"}, {'9',"wxyz"}};
void backtrack(vector<string>&ans, string digits, string tem, int start, int target){
if (start==target){
ans.push_back(tem);
return;
}
else{
char curdigit = digits[start];
for (int i=0; i<letterTable[curdigit].size(); ++i){
char choose = letterTable[curdigit][i];
tem.push_back(choose);
backtrack(ans, digits, tem, start+1, target);
tem.pop_back();
}
}
}
vector<string> letterCombinations(string digits) {
vector<string> ans;
if (digits.size()==0){
return ans;
}
// // 队列
// int n = digits.size();
// ans = {""};
// for (int i=0; i
// int count = ans.size();
// while (count > 0){
// string curansleft = ans[0];
// ans.erase(ans.begin());
// string curdigt = letterTable[digits[i]];
// for (int j=0; j
// ans.push_back(curansleft+curdigt[j]);
// }
// --count;
// }
// }
// 回溯
// vector ans;
string tem;
backtrack(ans, digits, tem, 0, digits.size());
return ans;
}
};
19. 删除链表的倒数第 N 个结点
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
pfirst = head
psecond = head
for i in range(n):
pfirst = pfirst.next
if pfirst:
while pfirst.next:
pfirst = pfirst.next
psecond = psecond.next
psecond.next = psecond.next.next
else:
head = head.next
return head
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* pfirst = head;
ListNode* psecond = head;
for (int i=0; i<n; i++){
pfirst = pfirst->next;
}
if (pfirst){
while (pfirst->next){
pfirst = pfirst->next;
psecond = psecond->next;
}
psecond->next = psecond->next->next;
}else{
head = head->next;
}
return head;
}
};
20. 有效的括号
class Solution:
def isValid(self, s: str) -> bool:
n = len(s)
if n % 2 == 1:
return False
pairsTable = {')':'(', '}':'{', ']':'['}
leftTable = []
for i in range(n):
if s[i] in [')', '}', ']']:
if len(leftTable) == 0:
return False
else:
if leftTable.pop() != pairsTable[s[i]]:
return False
else:
leftTable.append(s[i])
if len(leftTable)==0:
return True
else:
return False
class Solution {
public:
bool isValid(string s) {
int n = s.size();
if (1 == n%2){
return false;
}
unordered_map<char, char> pair={
{'}','{'},
{']','['},
{')','('}
};
stack<char> stk;
for (char ch:s){
if (pair.count(ch)){
if (stk.empty() || stk.top() != pair[ch]){
return false;
}
stk.pop();
}
else{
stk.push(ch);
}
}
return stk.empty();
}
};
21.合并两个有序链表(递归+迭代)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
# class Solution:
# def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
# if list1 is None:
# return list2
# if list2 is None:
# return list1
# ret = ListNode(0)
# tem = ret
# while list1 and list2:
# if list1.val <= list2.val:
# tem.next = list1
# list1 = list1.next
# else:
# tem.next = list2
# list2 = list2.next
# tem = tem.next
# tem.next = list1 if list1 else list2
# return ret.next
class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
if list1 is None:
return list2
if list2 is None:
return list1
if list1.val <= list2.val:
list1.next = self.mergeTwoLists(list1.next, list2)
return list1
else:
list2.next = self.mergeTwoLists(list2.next, list1)
return list2
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
// class Solution {
// public:
// ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
// ListNode* ret = new ListNode(-1);
// ListNode* tem = ret;
// if (list1 == nullptr){
// return list2;
// }
// if (list2 == nullptr){
// return list1;
// }
// while (list1 and list2){
// if (list1->val <= list2->val){
// tem->next = list1;
// list1 = list1->next;
// }
// else{
// tem->next = list2;
// list2 = list2->next;
// }
// tem = tem->next;
// }
// tem->next = list1 == nullptr ? list2 :list1;
// return ret->next;
// }
// };
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
if (list1 == nullptr){
return list2;
}
if (list2 == nullptr){
return list1;
}
if (list1->val <= list2->val){
list1->next = mergeTwoLists(list1->next, list2);
return list1;
}else{
list2->next = mergeTwoLists(list1, list2->next);
return list2;
}
}
};
22. 括号生成+1
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
res = []
def backtrack(s, left, right):
if len(s) == n:
res.append(s)
if left<n:
s += "("
backtrack(s, left+1, right)
s = s[:-1]
if left>right:
s += ")"
backtrack(s,left,right+1)
s = s[:-1]
backtrack("",0,0)
return res
class Solution:
def backtrack(self, ans, tem, n, start, brackets):
if start[0]==n and start[1]==n:
ans.append(tem)
return
if start[0] > n or start[1] > n or start[0] < start[1]:
return
for j, s in enumerate(brackets):
tem += s
start[j%2] += 1
self.backtrack(ans, tem, n, start, brackets)
tem = tem[:-1]
start[j%2] -= 1
def generateParenthesis(self, n: int) -> List[str]:
ans = []
tem = ''
self.backtrack(ans, tem, n, [0, 0], ['(', ')'])
return ans
class Solution {
public:
void backtrack(vector<string>& ans, string tem, int n, vector<int> &start){
if (start[0] == n && start[1] == n){
ans.push_back(tem);
return;
}
if (start[0] > n || start[1] > n || start[0] < start[1]){
return;
}
for (int i=0; i<2; i++){
if (start[0]==start[1]){
tem.push_back('(');
}else if (start[0]>start[1]){
tem.push_back(i==0 ? '(' : ')');
}
++start[i];
backtrack(ans, tem, n, start);
tem.pop_back();
--start[i];
}
}
vector<string> generateParenthesis(int n) {
vector<string> ans;
string tem;
vector<int> start{0, 0};
backtrack(ans, tem, n, start);
return ans;
}
};
31. 下一个排列+1
class Solution:
def reverse(self, nums, l, r):
while l < r:
nums[l], nums[r] = nums[r], nums[l]
l += 1
r -= 1
def nextPermutation(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n = len(nums)
plarge = n-1
for i in range(n-1, 0, -1):
if nums[i] > nums[i-1]:
break
plarge -= 1
if plarge != 0:
ptem = n - 1
while nums[ptem] <= nums[plarge-1]:
ptem -= 1
nums[ptem], nums[plarge-1] = nums[plarge-1], nums[ptem]
self.reverse(nums, plarge, n-1)
class Solution {
private:
void reverse(vector<int>& nums, int left, int right){
while (left<right){
int tem = nums[left];
nums[left] = nums[right];
nums[right] = tem;
++left;
--right;
}
}
public:
void nextPermutation(vector<int>& nums) {
int n = nums.size();
int plarge = n - 1;
for (int i=n-1; i>0; --i){
if (nums[i]<=nums[i-1]){
--plarge;
}else{
break;
}
}
if (plarge != 0){
for (int i=n-1; i>0; --i){
if (nums[plarge-1] < nums[i]){
int tem = nums[plarge-1];
nums[plarge-1] = nums[i];
nums[i] = tem;
break;
}
}
}
reverse(nums, plarge, n-1);
}
};
二分
class Solution:
def triangleNumber(self, nums: List[int]) -> int:
n, res = len(nums), 0
if n<3:
return 0
nums.sort()
print(nums)
for i in range(n):
for j in range(i+1, n):
left, right, k = j+1, n-1, j
while left <= right:
mid = (left + right) // 2
if nums[i] + nums[j] > nums[mid]:
k = mid
left = mid+1
else:
right = mid-1
res += k - j
return res
双指针
class Solution:
def triangleNumber(self, nums: List[int]) -> int:
res, n = 0, len(nums)
nums.sort()
print(nums)
if n < 3:
return 0
for i in range(n):
k = i+2
for j in range(i+1, n):
while k < n and nums[i] + nums[j] > nums[k]:
k += 1
res += max(k-j-1, 0)
return res
33. 搜索旋转排序数组+1
二分,判断哪边是有序的
class Solution:
def bisection(self, nums, l, r, target):
while l <= r:
mid = (r-l)//2 + l
if nums[mid] == target:
return mid
if nums[l] <= nums[mid]:
if nums[l] <= target and target < nums[mid]:
l, r = l, mid-1
else:
l, r = mid+1, r
else:
if nums[mid] < target and target <= nums[r]:
l, r = mid+1, r
else:
l, r = l, mid-1
return -1
def search(self, nums: List[int], target: int) -> int:
return self.bisection(nums, 0, len(nums)-1, target)
class Solution {
private:
int bisection(vector<int>& nums, int target){
int mid, l=0, r=nums.size()-1;
while (l<=r){
mid = (r-l) / 2 + l;
if (nums[mid] == target){
return mid;
}
if (nums[l] <= nums[mid]){
if (nums[l] <= target && target < nums[mid]){
r = mid - 1;
}else{
l = mid + 1;
}
}else{
if (nums[mid]<target && target<= nums[r]){
l = mid + 1;
}
else{
r = mid -1 ;
}
}
}
return -1;
}
public:
int search(vector<int>& nums, int target) {
return bisection(nums, target);
}
};
34. 在排序数组中查找元素的第一个和最后一个位置+1
class Solution:
def bisection(self, nums, target):
l, r, mid = 0, len(nums)-1, inf
findtarget = False
while l <= r:
mid = (r-l)//2+l
if nums[mid] == target:
findtarget = True
break
elif nums[mid] < target:
l = mid + 1
else:
r = mid - 1
if not findtarget:
return [-1, -1]
else:
l, r = mid, mid
while l>=1 and nums[l] == nums[l-1]:
l -= 1
while r <= len(nums)-2 and nums[r]==nums[r+1]:
r += 1
return [l, r]
def searchRange(self, nums: List[int], target: int) -> List[int]:
return self.bisection(nums, target)
class Solution {
private:
vector<int> bisection(vector<int> &nums, int target){
int l=0, r=nums.size()-1, findtarget=0, mid;
while (l<=r){
mid = (r-l) / 2 + l;
if (nums[mid]==target){
findtarget = 1;
break;
}else if(nums[l]<=target && target< nums[mid]){
r = mid-1;
}else{
l = mid+1;
}
}
if (findtarget){
l = mid, r = mid;
while (l>0 && nums[l]==nums[l-1]){
--l;
}
while (r<nums.size()-1 && nums[r]==nums[r+1]){
++r;
}
return vector<int>{l, r};
}else{
return vector<int>{-1, -1};
}
}
public:
vector<int> searchRange(vector<int>& nums, int target) {
return bisection(nums, target);
}
};
39. 组合总和+1
输入: candidates = [2,3,6,7], target = 7
输出: [[7],[2,2,3]]
回溯,模板
res = [] # 定义全局变量
backtrack(curres, choice):
if 满足条件:
res.append(curres) # 增加当前合理的选择
if 跳出界限:
return # 返回
for i in choice: # 做选择
backtrack(curres + 选择, 剩余选择)
backtrack([], 题干的input)
return res
class Solution:
def backtrack(self, ans, tem, candidates, start, target):
if sum(tem)==target:
ans.append(tem[:])
if sum(tem)>target:
return
for i in range(start, len(candidates)):
tem.append(candidates[i])
self.backtrack(ans, tem, candidates, i, target)
tem.pop()
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
ans = []
self.backtrack(ans, [], candidates, 0, target)
return ans
class Solution {
private:
void backtrack(vector<vector<int>> &ans, vector<int> &tem, vector<int> &candidates, int start, int target, int temsum){
if (temsum == target){
ans.push_back(tem);
return;
}
if (temsum > target){
return;
}
for (int i=start; i<candidates.size(); ++i){
tem.push_back(candidates[i]);
temsum += candidates[i];
backtrack(ans, tem, candidates, i, target, temsum);
temsum -= tem.back();
tem.pop_back();
}
}
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> ans;
vector<int> tem;
backtrack(ans, tem, candidates, 0, target, 0);
return ans;
}
};
46. 全排列+1
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
回溯
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
res = []
n = len(nums)
def backtrack(curres, choice):
if len(curres) == n:
res.append(curres)
return
for i in range(len(choice)):
backtrack(curres + [choice[i]], choice[:i]+choice[i+1:])
backtrack([], nums)
return res
class Solution:
def backtrack(self, ans, tem, chooses, target, visit):
if len(tem) == target:
ans.append(tem[:])
return
if len(tem) > target:
return
for i in range(len(chooses)):
if visit[i] == 1:
continue
tem.append(chooses[i])
visit[i] = 1
self.backtrack(ans, tem, chooses, target, visit)
tem.pop()
visit[i] = 0
def permute(self, nums: List[int]) -> List[List[int]]:
ans = []
visit = [0 for i in range(len(nums))]
self.backtrack(ans, [], nums, len(nums), visit)
return ans
class Solution {
private:
void backtrack(vector<vector<int>>& ans, vector<int>& nums, vector<int>& tmp, vector<int>& visit, int target){
if (tmp.size()==target){
ans.push_back(tmp);
return;
}
if (tmp.size() > target){return;}
for (int i=0; i<nums.size(); ++i){
if (visit[i] == 1){continue;}
tmp.push_back(nums[i]);
visit[i] = 1;
backtrack(ans, nums, tmp, visit, target);
tmp.pop_back();
visit[i] = 0;
}
}
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> ans;
vector<int> tmp, visit(nums.size(), 0);
backtrack(ans, nums, tmp, visit, nums.size());
return ans;
}
};
48. 旋转图像+1(顺时针旋转 90 度)
class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
h, w = len(matrix), len(matrix[0])
for i in range(h//2):
for j in range(w):
matrix[i][j], matrix[h-i-1][j] = matrix[h-i-1][j], matrix[i][j]
for i in range(h-1):
for j in range(i+1, w):
matrix[i][j], matrix[j][i]= matrix[j][i], matrix[i][j]
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int h=matrix.size(), w=matrix[0].size();
for (int i=0; i<h/2; ++i){
for (int j=0; j<w; ++j){
int tmp = matrix[i][j];
matrix[i][j] = matrix[h-1-i][j];
matrix[h-1-i][j] = tmp;
}
}
for (int i=0; i<h-1; ++i){
for (int j=i+1; j<w; ++j){
int tmp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = tmp;
}
}
}
};
49. 字母异位词分组+1
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
class Solution:
def baseSort(self, strs):
ans = dict()
for str in strs:
cur_key = "".join(sorted(str))
if ans.get(cur_key, 0) != 0:
ans[cur_key].append(str)
else:
ans[cur_key] = [str]
return list(ans.values())
def keyTable(self, strs):
ans = collections.defaultdict(list)
for str in strs:
keyTable = [0] * 26
for s in str:
keyTable[ord(s)-ord('a')] += 1
ans[tuple(keyTable)].append(str)
return list(ans.values())
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
# return self.baseSort(strs)
return self.keyTable(strs)
class Solution {
public:
vector<vector<string>> basesort(vector<string>& strs){
unordered_map<string, vector<string>> mp;
for (string str:strs){
string curKey = str;
sort(curKey.begin(), curKey.end());
// mp[curKey].push_back(str);
mp[curKey].emplace_back(str);
}
vector<vector<string>> ans;
for (auto it=mp.begin(); it!=mp.end(); ++it){
// ans.push_back(it->second);
ans.emplace_back(it->second);
}
return ans;
}
vector<vector<string>> baseAscll(vector<string>& strs){
vector<vector<string>> ans;
unordered_map<string, vector<string>> mp;
for (auto str:strs){
// string curKey(26, 'NUL');
string curKey(26, 'DEL');
for (auto s:str){
++curKey[s-'a'];
}
mp[curKey].emplace_back(str);
}
for (auto c:mp){
ans.emplace_back(c.second);
}
return ans;
}
vector<vector<string>> groupAnagrams(vector<string>& strs) {
// return basesort(strs);
return baseAscll(strs);
}
};
53. 最大子数组和
class Solution:
def baseTable(self, nums):
ans = nums[0]
table = [0] * len(nums)
table[0] = ans
for i in range(1, len(nums)):
table[i] = max(table[i-1]+nums[i], nums[i])
ans = max(ans, table[i])
return ans
def bisection(self, nums):
n = len(nums)
if n == 1:
return nums[0]
else:
mid = len(nums) // 2
max_left = self.bisection(nums[:mid])
max_right = self.bisection(nums[mid:])
max_mid = nums[mid]
tem = 0
max_l = tem
for i in range(mid-1, -1, -1):
tem += nums[i]
max_l = max(max_l, tem)
tem = 0
max_r = tem
for i in range(mid+1, len(nums)):
tem += nums[i]
max_r = max(max_r, tem)
return max(max_left, max_right, max_l+max_r+max_mid)
def maxSubArray(self, nums: List[int]) -> int:
# return self.baseTable(nums)
return self.bisection(nums)
class Solution {
private:
int baseDP(vector<int>& nums){
int ans=nums[0];
// vector table(nums.size(), 0);
// table[0] = ans;
int preMax = ans;
for (int i=1; i<nums.size(); ++i){
// table[i] = max(table[i-1]+nums[i], nums[i]);
preMax = max(preMax+nums[i], nums[i]);
// ans = max(ans, table[i]);
ans = max(ans, preMax);
}
return ans;
}
int bisection(vector<int>& nums){
int n = nums.size();
int mid = nums.size()/2;
int max_left, max_right;
if (n == 1){return nums[0];}
else{
vector<int> numsLeft(nums.begin(), nums.begin()+mid);
vector<int> numsRight(nums.begin()+mid, nums.end());
max_left = bisection(numsLeft);
max_right = bisection(numsRight);
}
int max_mid = nums[mid];
int max_l=0, tem=0;
for (int i=mid-1; i>=0; --i){
tem += nums[i];
max_l = max(max_l, tem);
}
int max_r=0;
tem=0;
for (int i=mid+1; i<nums.size(); ++i){
tem += nums[i];
max_r = max(max_r, tem);
}
return max(max(max_left, max_right), max_l+max_r+max_mid);
}
public:
int maxSubArray(vector<int>& nums) {
// return baseDP(nums);
return bisection(nums);
}
};
55. 跳跃游戏+1
输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。
class Solution:
def canJump(self, nums: List[int]) -> bool:
n = len(nums)
curMaxIndex = 0
for i in range(n):
curMaxIndex = max(i + nums[i], curMaxIndex)
if curMaxIndex >= n-1:
return True
if curMaxIndex == i:
return False
class Solution {
public:
bool canJump(vector<int>& nums) {
int n = nums.size();
int curMaxIndex = 0;
for (int i=0; i<n; ++i){
curMaxIndex = max(curMaxIndex, i+nums[i]);
if (curMaxIndex >= n-1){
return true;
}
if (curMaxIndex == i){
return false;
}
}
return true;
}
};
56. 合并区间+1
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort()
n = len(intervals)
ans = [intervals[0]]
for i in range(1, n):
if intervals[i][0] <= ans[-1][1]:
ans[-1][1] = max(ans[-1][1], intervals[i][1])
else:
ans.append(intervals[i])
return ans
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end());
int n = intervals.size();
vector<vector<int>> ans={intervals[0]};
for (int i=1; i<n; ++i){
if (ans.back()[1]>= intervals[i][0]){
ans.back()[1] = max(ans.back()[1], intervals[i][1]);
}
else{
ans.push_back(intervals[i]);
}
}
return ans;
}
};
62. 不同路径+1
不同路径
输入:m = 3, n = 7
输出:28
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
table = [[1 for i in range(n)] for j in range(m)]
for i in range(1, m):
for j in range(1, n):
table[i][j] = table[i-1][j] + table[i][j-1]
return table[m-1][n-1]
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> table(m, vector<int>(n, 1));
for (int i=1; i<m; ++i){
for (int j=1; j<n; ++j){
table[i][j] = table[i-1][j]+table[i][j-1];
}
}
return table[m-1][n-1];
}
};
64. 最小路径和+1
最小路径和
输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
输出:7
解释:因为路径 1→3→1→1→1 的总和最小。
class Solution:
def minPathSum(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
DP = [[0 for i in range(n)] for j in range(m)]
DP[0][0] = grid[0][0]
for i in range(1, n):
DP[0][i] = DP[0][i-1] + grid[0][i]
for i in range(1, m):
DP[i][0] = DP[i-1][0] + grid[i][0]
for i in range(1, m):
for j in range(1, n):
DP[i][j] = min(DP[i-1][j], DP[i][j-1]) + grid[i][j]
return DP[m-1][n-1]
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
int m=grid.size(), n=grid[0].size();
vector<vector<int>> DP(m, vector<int>(n));
DP[0][0] = grid[0][0];
for (int i=1; i<n; ++i){
DP[0][i] = DP[0][i-1] + grid[0][i];
}
for (int i=1; i<m; ++i){
DP[i][0] = DP[i-1][0] + grid[i][0];
}
for (int i=1; i<m; ++i){
for (int j=1; j<n; ++j){
DP[i][j] = min(DP[i-1][j], DP[i][j-1]) + grid[i][j];
}
}
return DP[m-1][n-1];
}
};
70. 爬楼梯
# class Solution:
# def climbStairs(self, n: int) -> int:
# f, s = 1, 2
# if n == 1 or n == 2:
# return n
# while n-2>0:
# f, s = s, f+s
# n -= 1
# return s
# class Solution:
# def climbStairs(self, n: int) -> int:
# if n == 1 or n == 2:
# return n
# dp = [0 for _ in range(n)]
# dp[0] = 1
# dp[1] = 2
# for i in range(2, n):
# dp[i] = dp[i-1] + dp[i-2]
# return dp[n-1]
class Solution:
def climbStairs(self, n: int) -> int:
@lru_cache
def dfs(n):
if n == 1 or n == 2:
return n
return dfs(n-1) + dfs(n-2)
return dfs(n)
// class Solution {
// public:
// int climbStairs(int n) {
// int f = 1, s = 2, t = 3;
// if (1==n || 2==n ||3==n){
// return n;
// }
// for (int i = 3; i
// f = s;
// s = t;
// t = f + s;
// }
// return t;
// }
// };
class Solution {
public:
int climbStairs(int n) {
if (1==n || 2==n ||3==n){
return n;
}
int dp[46] = {0, 1, 2, 3};
for (int i=4; i<n+1; ++i){
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
};
// 超出时间限制
// class Solution {
// public:
// int climbStairs(int n) {
// if (1==n || 2==n ||3==n){
// return n;
// }
// return climbStairs(n-1)+climbStairs(n-2);
// }
// };
75. 颜色分类+1
颜色分类
输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
class Solution:
def sortColors(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
l, r = 0, len(nums)-1
start = 0
while start<=r:
if nums[start] == 0:
nums[start], nums[l] = nums[l], nums[start]
l += 1
start += 1
elif nums[start] == 2:
nums[start], nums[r] = nums[r], nums[start]
r -= 1
else:
start += 1
class Solution {
public:
void sortColors(vector<int>& nums) {
int l=0, r=nums.size()-1, start=0;
while (start<=r){
if (nums[start]==0){
int tem = nums[start];
nums[start] = nums[l];
nums[l] = tem;
++start;
++l;
}
else if(nums[start] == 2){
int tem = nums[start];
nums[start] = nums[r];
nums[r] = tem;
--r;
}
else{
++start;
}
}
}
};
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = [[]]
for i in nums:
stack = res
for j in range(len(stack)):
res.append(stack[j] + [i])
return res
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
res = [False]
n = len(word)
row, col = len(board), len(board[0])
def backtrack(i, j, index):
if index == n-1:
res[0] = True
return
table.add((i,j))
for temi, temj in [[i+1,j], [i-1,j], [i,j+1], [i,j-1]]:
if 0 <= temi < row and 0 <= temj < col and board[temi][temj] == word[index+1]:
if (temi, temj) not in table:
backtrack(temi, temj, index+1)
table.remove((i,j))
table = set()
for i in range(row):
for j in range(col):
if board[i][j] == word[0]:
backtrack(i, j, 0)
return res[0]
94. 二叉树的中序遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
# class Solution:
# def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# def dfs(curRoot, curList):
# if curRoot == None:
# return curList
# dfs(curRoot.left, curList)
# curList.append(curRoot.val)
# dfs(curRoot.right, curList)
# out = []
# dfs(root, out)
# return out
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
stk = []
out = []
while root or len(stk)!=0:
while root:
stk.append(root)
root = root.left
root = stk.pop()
out.append(root.val)
root = root.right
return out
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
// class Solution {
// public:
// void dfs(TreeNode* root, vector& List){
// if (!root){
// return ;
// }
// dfs(root->left, List);
// List.push_back(root->val);
// dfs(root->right, List);
// }
// vector inorderTraversal(TreeNode* root) {
// vector out;
// dfs(root, out);
// return out;
// }
// };
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> out;
stack<TreeNode*> stk;
while (root!=nullptr || !stk.empty()){
while (root != nullptr){
stk.push(root);
root = root->left;
}
root = stk.top();
stk.pop();
out.push_back(root->val);
root= root->right;
}
return out;
}
};
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
class Solution:
def numTrees(self, n: int) -> int:
table = [1] + [0] * (n)
for i in range(1, n+1):
for j in range(i):
table[i] += table[j] * table[i-j-1]
return table[n]
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
中序遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
res = [True]
pre = [-inf]
def leftrootright(root):
if not root:
return
leftrootright(root.left)
val = root.val
if val <= pre[0]:
res[0] = False
return
pre[0] = val
leftrootright(root.right)
leftrootright(root)
return res[0]
101. 对称二叉树
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
# class Solution:
# def isSymmetric(self, root: Optional[TreeNode]) -> bool:
# def check(l, r):
# if l is None and r is None:
# return True
# if l is None or r is None:
# return False
# return l.val == r.val and check(l.right, r.left) and check(l.left, r.right)
# return check(root.left, root.right)
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
def check(l, r):
stk = [l, r]
while len(stk):
pre = stk.pop(0)
nex = stk.pop(0)
if pre is None and nex is None:
continue
if pre is None or nex is None or pre.val != nex.val:
return False
stk.append(pre.left)
stk.append(nex.right)
stk.append(pre.right)
stk.append(nex.left)
return True
return check(root, root)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
// class Solution {
// public:
// bool check(TreeNode* L, TreeNode* R){
// if (!L && !R){
// return true;
// }
// if (!L || !R){
// return false;
// }
// return L->val==R->val && check(L->left, R->right) && check(L->right, R->left);
// }
// bool isSymmetric(TreeNode* root) {
// return check(root, root);
// }
// };
class Solution {
public:
bool check(TreeNode* L, TreeNode* R){
queue<TreeNode*> q;
q.push(L);
q.push(R);
while (!q.empty()){
L = q.front(); q.pop();
R = q.front(); q.pop();
if (!L && !R){
continue;
}
if (!L || !R || L->val!=R->val){
return false;
}
q.push(L->left); q.push(R->right);
q.push(L->right); q.push(R->left);
}
return true;
}
bool isSymmetric(TreeNode* root) {
return check(root, root);
}
};
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
res = [[]]
if not root:
return []
stack = [root, "flag"]
while stack != ["flag"]:
tem = stack.pop(0)
if tem == "flag":
res.append([])
stack.append("flag")
else:
res[-1].append(tem.val)
if tem.left:
stack.append(tem.left)
if tem.right:
stack.append(tem.right)
return res
104. 二叉树的最大深度
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
# 前序遍历
# class Solution:
# def maxDepth(self, root: Optional[TreeNode]) -> int:
# def dfs(root, cur, out):
# if root is None:
# out[0] = max(cur, out[0])
# return
# dfs(root.left, cur+1, out)
# dfs(root.right, cur+1, out)
# out = [0]
# dfs(root, 0, out)
# return out[0]
# dfs
# class Solution:
# def maxDepth(self, root: Optional[TreeNode]) -> int:
# if root is None: return 0
# L = self.maxDepth(root.left)
# R = self.maxDepth(root.right)
# return max(L, R) + 1
# bfs
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
if root is None: return 0
stk = [root]
out = 0
while stk:
n = len(stk)
for i in range(n):
curRoot = stk.pop(0)
if curRoot.left:
stk.append(curRoot.left)
if curRoot.right:
stk.append(curRoot.right)
out += 1
return out
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
// // 前序遍历
// class Solution {
// public:
// void def(TreeNode* root, int cur, int out[]){
// if (!root){
// if (cur > out[0]){
// out[0] = cur;
// }
// return;
// }
// def(root->left, cur+1, out);
// def(root->right, cur+1, out);
// }
// int maxDepth(TreeNode* root) {
// int ret[1] = {0};
// def(root, 0, ret);
// return ret[0];
// }
// };
// // dfs
// class Solution {
// public:
// int mymax(int L, int R){
// if (L > R){
// return L;
// }else{
// return R;
// }
// }
// int maxDepth(TreeNode* root) {
// if (!root){
// return 0;
// }
// int L = maxDepth(root->left);
// int R = maxDepth(root->right);
// return mymax(L, R) + 1;
// }
// };
// bfs
class Solution {
public:
int maxDepth(TreeNode* root) {
if (!root){return 0;}
queue<TreeNode*> q;
q.push(root);
int out = 0;
while (!q.empty()){
int n = q.size();
for (int j=0; j<n; ++j){
TreeNode* curRoot = q.front();
q.pop();
if (curRoot->left){
q.push(curRoot->left);
}
if (curRoot->right){
q.push(curRoot->right);
}
}
out += 1;
}
return out;
}
};
给定一棵树的前序遍历 preorder 与中序遍历 inorder。请构造二叉树并返回其根节点。
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
if not preorder:
return
root = TreeNode(preorder[0])
inorderroot = inorder.index(preorder[0])
root.left = self.buildTree(preorder[1:inorderroot+1], inorder[:inorderroot])
root.right = self.buildTree(preorder[inorderroot+1:], inorder[inorderroot+1:])
return root
给你二叉树的根结点 root ,请你将它展开为一个单链表:
展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
展开后的单链表应该与二叉树 先序遍历 顺序相同。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def flatten(self, root: TreeNode) -> None:
"""
Do not return anything, modify root in-place instead.
"""
while root:
temright = root.right
root.right = root.left
root.left = None
cur = root
while cur.right:
cur = cur.right
cur.right = temright
root = root.right
121. 买卖股票的最佳时机
class Solution:
def maxProfit(self, prices: List[int]) -> int:
temMin, Out = inf, 0
for i in range(len(prices)):
curPrice = prices[i]
if curPrice < temMin:
temMin = curPrice
else:
Out = max(Out, curPrice-temMin)
return Out
class Solution {
public:
int maxProfit(vector<int>& prices) {
int temMin = INT_MAX;
int out = 0;
for (int price:prices){
if (price < temMin){
temMin = price;
}
else{
out = max(out, price-temMin);
}
}
return out;
}
};
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
class Solution:
def longestConsecutive(self, nums: List[int]) -> int:
nums.sort()
if not nums:
return 0
n = len(nums)
table = [1] * n
for i in range(1, n):
if nums[i] == nums[i-1]+1:
table[i] = table[i-1] + 1
if nums[i] == nums[i-1]:
table[i] = table[i-1]
return max(table)
136. 只出现一次的数字
class Solution:
def singleNumber(self, nums: List[int]) -> int:
out = 0
for i in range(len(nums)):
out = out ^ nums[i]
return out
class Solution {
public:
int singleNumber(vector<int>& nums) {
int out = 0;
for (int num:nums){
out = out ^ num;
}
return out;
}
};
输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。
动态规划。用回溯超时
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
n = len(s)
table = [True] + [False] * n
for i in range(1, n+1):
for c in wordDict:
if len(c)<=i:
if table[i-len(c)] and c == s[i-len(c):i]:
table[i] = True
return table[n]
141. 环形链表
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
if head is None:
return False
fastP = head
slowP = head
while fastP.next and fastP.next.next:
fastP = fastP.next.next
slowP = slowP.next
if fastP == slowP:
return True
return False
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
if (!head){
return false;
}
while (fast->next and fast->next->next){
fast = fast->next->next;
slow = slow->next;
if (fast == slow){
return true;
}
}
return false;
}
};
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。
说明:不允许修改给定的链表。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
fast = head
slow = head
flag = False
if not head:
return None
while fast.next and fast.next.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
flag = True
break
if flag:
cur = head
fast = head
while fast != slow:
fast = fast.next
slow = slow.next
return fast
else:
return None
实现 LRUCache 类:
LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
class LRUCache:
def __init__(self, capacity: int):
self.cap = capacity
self.LRU = collections.OrderedDict()
def get(self, key: int) -> int:
if self.LRU.get(key, "flag") != "flag":
self.LRU.move_to_end(key, last = True)
return self.LRU.get(key, False)
else:
return -1
def put(self, key: int, value: int) -> None:
if self.LRU.get(key, "flag") != "flag":
self.LRU[key] = value
self.LRU.move_to_end(key, last = True)
else:
if len(self.LRU) == self.cap:
self.LRU.popitem(last = False)
self.LRU[key] = value
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def sortList(self, head: ListNode) -> ListNode:
def mergeList(List1, List2):
cur = ListNode()
res = cur
while List1 and List2:
if List1.val < List2.val:
cur.next = List1
List1 = List1.next
else:
cur.next = List2
List2 = List2.next
cur = cur.next
cur.next = List1 if List1 else List2
return res.next
if not head or not head.next:
return head
fast, slow = head.next, head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
rightList = slow.next
slow.next = None
left, right = self.sortList(head), self.sortList(rightList)
return mergeList(left, right)
给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积
输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
class Solution:
def maxProduct(self, nums: List[int]) -> int:
res, temmax, temmin = nums[0], nums[0], nums[0]
n = len(nums)
for i in range(1, n):
temmax, temmin = max(nums[i], temmin*nums[i], temmax*nums[i]), min(nums[i], temmin*nums[i], temmax*nums[i])
res = max(res, temmax)
return res
160. 相交链表
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
tableA = []
while headA:
tableA.append(headA)
headA = headA.next
while headB:
if headB in tableA:
return headB
headB = headB.next
return None
# class Solution:
# def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
# if headB is None or headA is None:
# return None
# pa = headA
# pb = headB
# while pa != pb:
# pa = pa.next if pa else headB
# pb = pb.next if pb else headA
# return pa
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
// class Solution {
// public:
// ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
// unordered_set table;
// ListNode *tema = headA;
// while (tema != nullptr){
// table.insert(tema);
// tema = tema->next;
// }
// ListNode *temb = headB;
// while (temb != nullptr){
// if (table.count(temb)){
// return temb;
// }
// temb = temb->next;
// }
// return nullptr;
// }
// };
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (headA == nullptr || headB == nullptr){return nullptr;}
ListNode *tema = headA;
ListNode *temb = headB;
while (tema != temb){
tema = tema == nullptr ? headB:tema->next;
temb = temb == nullptr ? headA:temb->next;
}
return temb;
}
};
169. 多数元素
class Solution:
def majorityElement(self, nums: List[int]) -> int:
# # 1 排序
# numsSorted = sorted(nums)
# return numsSorted[(len(nums)//2)]
# # 2 字典
# keyTable, maj, majn = dict(), 0, 0
# for num in nums:
# if keyTable.get(num, 'no') != 'no':
# keyTable[num] += 1
# else:
# keyTable[num] = 1
# if keyTable[num] > majn:
# maj = num
# majn = keyTable[num]
# return maj
# # 3 随机化
# majn = len(nums)//2
# while True:
# curN = random.choice(nums)
# if sum(1 for i in nums if i==curN) > majn:
# return curN
# # 4 分治
# def DAC(l, r):
# if l == r:
# return nums[l]
# mid = (r-l) // 2 + l
# majL = DAC(l, mid)
# majR = DAC(mid+1, r)
# if majL == majR:
# return majL
# majLN = sum(1 for i in range(l, r+1) if nums[i] == majL)
# majNR = sum(1 for i in range(l, r+1) if nums[i] == majR)
# return majL if majLN > majNR else majR
# return DAC(0, len(nums)-1)
# 5 投票
maj, count = 0, 0
for num in nums:
if count == 0:
maj = num
count += 1 if num == maj else -1
return maj
class Solution {
public:
// int dac(vector& nums, int l, int r){
// if (l == r){
// return nums[l];
// }
// int mid = (r-l)/2 +l;
// int majL = dac(nums, l, mid);
// int majR = dac(nums, mid+1, r);
// if (majL == majR){
// return majL;
// }
// int majLN = 0, majRN = 0;
// for (int i = l; i<=r; ++i){
// if (majL == nums[i]){
// ++majLN;
// }
// if (majR == nums[i]){
// ++majRN;
// }
// }
// return majLN > majRN ? majL:majR;
// }
int majorityElement(vector<int>& nums) {
// // 1 排序
// sort(nums.begin(), nums.end());
// return nums[nums.size()/2];
// // 2 字典
// unordered_map keyTable;
// int maj = 0, majn = 0;
// for (int num:nums){
// ++keyTable[num];
// if (keyTable[num] > majn){
// maj = num;
// majn = keyTable[num];
// }
// }
// return maj;
// // 3 随机化
// int majn = nums.size()/2;
// while (true){
// int curMaj = nums[rand() % nums.size()];
// int curMajN = 0;
// for (int num:nums){
// if (curMaj == num){
// ++curMajN;
// }
// if (curMajN > majn){
// return curMaj;
// }
// }
// }
// // 4 分治
// return dac(nums, 0, nums.size()-1);
// 5 投票
int maj = 0, majn = 0;
for (int num:nums){
if (majn == 0){
maj = num;
}
if (maj == num){
++majn;
}
else{
--majn;
}
}
return maj;
}
};
输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
class Solution:
def rob(self, nums: List[int]) -> int:
n = len(nums)
table = [0] * n
if n == 1:
return nums[0]
table[0], table[1] = nums[0], max(nums[0], nums[1])
for i in range(2, n):
table[i] = max(table[i-2]+nums[i], table[i-1])
return table[-1]
给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
res = [0]
def backtrack(i, j):
# if grid[i][j] == "0":
# return
# table.add((i,j))
grid[i][j] = "0"
for temi, temj in [[i+1, j], [i-1, j], [i, j+1], [i, j-1]]:
if 0 <= temi < row and 0 <= temj < col and grid[temi][temj] == "1":
# if (temi, temj) not in table:
backtrack(temi, temj)
# table.remove((i,j))
# table = set()
row, col = len(grid), len(grid[0])
for i in range(row):
for j in range(col):
if grid[i][j] == "1":
backtrack(i, j)
res[0] += 1
return res[0]
206. 反转链表
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
tem = head
out = ListNode().next
while tem:
tem = head.next
head.next = out
out = head
head = tem
return out
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* tmp = head;
ListNode* out = nullptr;
while (head!=nullptr){
tmp = head->next;
head->next = out;
out = head;
head = tmp;
}
return out;
}
};
你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。
例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。
请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
table = [0] * numCourses
learnDic = {}
for c in prerequisites:
learnDic[c[1]] = learnDic.get(c[1], []) + [c[0]]
table[c[0]] += 1
learnNow = [x for x in range(numCourses) if table[x] == 0]
while learnNow:
# print(learnNow)
curlearn = learnNow.pop()
for iflearn in learnDic.get(curlearn, []):
table[iflearn] -= 1
if table[iflearn] == 0:
learnNow.append(iflearn)
return max(table) == 0
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
import random
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
def outindex(left, right):
randomindex = random.randint(left, right)
nums[randomindex], nums[left] = nums[left], nums[randomindex]
flag = nums[left]
left += 1
while left <= right:
if nums[left] >= flag:
nums[left-1] = nums[left]
left += 1
else:
nums[left], nums[right] = nums[right], nums[left]
right -= 1
nums[left-1] = flag
return left-1 # 注意要-1, 才是falg的索引
left, right, index = 0, len(nums)-1, 0
while left <= right:
index = outindex(left, right)
if index == k-1:
return nums[index]
elif index > k-1:
right = index - 1
else:
left = index + 1
在一个由 '0' 和 '1' 组成的二维矩阵内,找到只包含 '1' 的最大正方形,并返回其面积。
class Solution:
def maximalSquare(self, matrix: List[List[str]]) -> int:
m, n = len(matrix), len(matrix[0])
table = [[0]*n for _ in range(m)]
for i in range(m):
if matrix[i][0] == "1":
table[i][0] = 1
for j in range(n):
if matrix[0][j] == "1":
table[0][j] = 1
for i in range(1, m):
for j in range(1, n):
if matrix[i][j] == "1":
table[i][j] = min(table[i-1][j-1], table[i-1][j], table[i][j-1]) + 1
s = max([max(x) for x in table])
return s*s
226. 翻转二叉树
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def dfs(self, root):
if root is None:
return root
tem = root.left
root.left = root.right
root.right = tem
self.dfs(root.left)
self.dfs(root.right)
return root
def bfs(self, root):
que = [root]
while que:
curRoot= que.pop(0)
if curRoot.left is None and curRoot.right is None:
continue
tem = curRoot.left
curRoot.left = curRoot.right
curRoot.right = tem
if curRoot.left is not None:
que.append(curRoot.left)
if curRoot.right is not None:
que.append(curRoot.right)
return root
def rec(self, root):
if root is None:
return root
L = self.rec(root.left)
R = self.rec(root.right)
root.left, root.right = R, L
return root
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if root is None:
return root
# # 1 dfs
# return self.dfs(root)
# 2 bfs
return self.bfs(root)
# # 3 rec
# return self.rec(root)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* rec(TreeNode* root){
if (!root) return root;
TreeNode* L = rec(root->left);
TreeNode* R = rec(root->right);
root->left = R;
root->right = L;
return root;
}
TreeNode* dfs(TreeNode* root){
if (!root) return root;
TreeNode* tem = root->left;
root->left = root->right;
root->right = tem;
dfs(root->left);
dfs(root->right);
return root;
}
TreeNode* bfs(TreeNode* root){
queue<TreeNode*> que;
que.push(root);
while (!que.empty()){
TreeNode* curRoot = que.front();
que.pop();
if (!curRoot->left && !curRoot->right) continue;
TreeNode* tem = curRoot->left;
curRoot->left = curRoot->right;
curRoot->right = tem;
if (curRoot->left){
que.push(curRoot->left);
}
if (curRoot->right){
que.push(curRoot->right);
}
}
return root;
}
TreeNode* invertTree(TreeNode* root) {
if (!root) return root;
// // 1 rec
// return rec(root);
// 2 dfs
return dfs(root);
// // 3 bfs
// return bfs(root);
}
};
234. 回文链表
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def isPalindrome(self, head: Optional[ListNode]) -> bool:
fast, slow = head, head
L = ListNode(-1).next
while fast.next and fast.next.next:
fast = fast.next.next
tem = slow.next
slow.next = L
L = slow
slow = tem
if fast.next:
if slow.val != slow.next.val:
return False
R = slow.next.next
else:
R = slow.next
while L:
if R.val != L.val:
return False
R, L = R.next, L.next
return True
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
ListNode* fast = head;
ListNode* slow = head;
ListNode* L = nullptr;
ListNode* R;
while (fast->next && fast->next->next){
fast = fast->next->next;
ListNode* tem = slow->next;
slow->next = L;
L = slow;
slow = tem;
}
if (fast->next){
if (slow->val != slow->next->val){
return false;
}
R = slow->next->next;
}
else{
R = slow->next;
}
while (L){
if (R->val != L->val){
return false;
}
R = R->next;
L = L->next;
}
return true;
}
};
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if not root or root == p or root == q:
return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
if not left:
return right
if not right:
return left
return root
给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
n = len(nums)
table1 = [1] + [0] * (n) + [1]
table2 = [1] + [0] * (n) + [1]
res = [0] * (n)
for i in range(1, n+1):
table1[i] = table1[i-1] * nums[i-1]
for j in range(n, 0, -1):
table2[j] = table2[j+1] * nums[j-1]
for i in range(n):
res[i] = table1[i] * table2[i+2]
return res
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
row, col = len(matrix), len(matrix[0])
i, j = row-1, 0
while i >= 0 and j < col:
if matrix[i][j] == target:
return True
elif matrix[i][j] > target:
i -= 1
else:
j += 1
return False
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
给你一个整数 n ,返回和为 n 的完全平方数的 最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。
class Solution:
def numSquares(self, n: int) -> int:
table = [x for x in range(n+1)]
for i in range(2, n+1):
j = 1
while j*j <= i:
table[i] = min(table[i], table[i-j*j]+1)
j += 1
return table[n]
283. 移动零
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
zeroIndex = 0
for i in range(len(nums)):
if nums[i] != 0:
nums[zeroIndex], nums[i] = nums[i], nums[zeroIndex]
zeroIndex += 1
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int zeroIndex = 0;
for (int i=0; i<nums.size(); i++){
if (nums[i] != 0){
swap(nums[i], nums[zeroIndex]);
++zeroIndex;
}
}
}
};
给定一个包含 n + 1 个整数的数组 nums ,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。
假设 nums 只有 一个重复的整数 ,找出 这个重复的数 。
你设计的解决方案必须不修改数组 nums 且只用常量级 O(1) 的额外空间。
定义表格
class Solution:
def findDuplicate(self, nums: List[int]) -> int:
n = len(nums)
table = [0] * n
for num in nums:
if table[num] == 1:
return num
else:
table[num] = 1
快慢指针
class Solution:
def findDuplicate(self, nums: List[int]) -> int:
slow, fast = 0, 0
while True:
fast = nums[nums[fast]]
slow = nums[slow]
if fast == slow:
fast = 0
while fast != slow:
fast = nums[fast]
slow = nums[slow]
return fast
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
n = len(nums)
table = [1] * n
for i in range(1, n):
for j in range(i):
if nums[i] > nums[j]:
table[i] = max(table[i], table[j] + 1)
return max(table)
给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
示例:
输入: [1,2,3,0,2]
输出: 3
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
class Solution:
def maxProfit(self, prices: List[int]) -> int:
# 当前天处理之后,f0代表拥有, f1代表冷冻期, f2没有拥有也没有处于冷冻期
f0, f1, f2 = -prices[0], 0, 0
for i in range(1, len(prices)):
temf0 = max(f0, f2-prices[i])
temf1 = f0 + prices[i]
temf2 = max(f1, f2)
f0, f1, f2 = temf0, temf1, temf2
return max(f0, f1, f2)
给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
你可以认为每种硬币的数量是无限的。
示例 1:
输入:coins = [1, 2, 5], amount = 11
输出:3
解释:11 = 5 + 5 + 1
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
table = [0] + [inf] * (amount)
for i in range(amount+1):
for coin in coins:
if i-coin >= 0:
table[i] = min(table[i], table[i-coin] + 1)
return table[amount] if table[amount] != inf else -1
在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def rob(self, root: TreeNode) -> int:
def backtrack(root):
if not root:
return 0,0
yl, nl = backtrack(root.left)
yr, nr = backtrack(root.right)
return root.val+nl+nr, max(yl,nl)+max(yr,nr)
return max(backtrack(root))
338. 比特位计数
class Solution:
def contOne1(self, n):
count = 0
while n > 0:
n = n & (n-1)
count += 1
return count
def contOne2(self, n):
out = [0]
hightBit = 0
for i in range(1, n+1):
if (i & (i -1)) == 0:
hightBit = i
out.append(out[i-hightBit]+1)
return out
def contOne3(self, n):
out = [0]
for i in range(1, n+1):
# out.append(out[i//2] + i % 2)
out.append(out[i>>1] + (i & 1))
return out
def contOne4(self, n):
out = [0]
for i in range(1, n+1):
out.append(out[i&(i-1)]+1)
return out
def countBits(self, n: int) -> List[int]:
# # 1 Brian Kernighan 算法
# return [self.contOne1(i) for i in range(n+1)]
# # 2 动态规划-最高比特位
# return self.contOne2(n)
# # 3 动态规划-最低比特位
# return self.contOne3(n)
# 4 动态规划-最低设置位
return self.contOne4(n)
class Solution {
public:
vector<int> countOne1(int n){
vector<int> out(n+1);
for (int i=1; i<n+1; ++i){
int count = 0;
int tem = i;
while (tem>0){
tem = tem & (tem-1);
++count;
}
out[i] = count;
}
return out;
}
vector<int> countOne2(int n){
vector<int> out(n+1);
out[0] = 0;
int higtBit = 0;
for (int i=1; i<n+1; ++i){
if ((i&(i-1))==0){
higtBit = i;
}
out[i] = out[i-higtBit]+1;
}
return out;
}
vector<int> countOne3(int n){
vector<int> out(n+1);
out[0] = 0;
for (int i=1; i<n+1; ++i){
out[i] = out[i>>1] + (i&1);
}
return out;
}
vector<int> countOne4(int n){
vector<int> out(n+1);
out[0] = 0;
for (int i=1; i<n+1; ++i){
out[i] = out[(i&(i-1))] + 1;
}
return out;
}
vector<int> countBits(int n) {
// // 1 Brian Kernighan 算法
// return countOne1(n);
// // 2 动态规划-最高有效位
// return countOne2(n);
// // 3 动态规划-最低有效位
// return countOne3(n);
// 4 动态规划-最低设置位
return countOne4(n);
}
};
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
nums = sorted(nums)
res = [[nums[0],1]]
n = len(nums)
for i in range(1, n):
if nums[i] == res[-1][0]:
res[-1][1] += 1
else:
res.append([nums[i],1])
res.sort(key=lambda x:x[1], reverse=True)
out = []
for i in range(k):
out.append(res[i][0])
return out
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
输入:s = "3[a]2[bc]"
输出:"aaabcbc"
class Solution:
def decodeString(self, s: str) -> str:
stack, res, multi = [[1,""]], "", 0
for c in s:
if "0" <= c <= "9":
multi = multi*10 + int(c)
elif c == '[':
stack.append([multi, ""])
multi = 0
elif c == "]":
curmutlti, curres = stack.pop()
stack[-1][1] += curmutlti*curres
else:
stack[-1][1] += c
return stack[0][1]
输入:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
输出:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
class Solution:
def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
people.sort(key=lambda x:[-x[0], x[1]])
res = []
for per in people:
res[per[1]:per[1]] = [per]
return res
给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
示例 1:
输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。
class Solution:
def canPartition(self, nums: List[int]) -> bool:
n = len(nums)
if n == 1:
return False
if sum(nums) % 2 == 1:
return False
target = sum(nums) // 2
table = [True] + [False] * target
for curnum in nums:
for i in range(target, 0, -1):
if i >= curnum:
table[i] = table[i-curnum] or table[i]
return table[-1]
给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。
路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
采用先序遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def pathSum(self, root: TreeNode, targetSum: int) -> int:
res = [0]
def backtrack(root, cursum, sumDic):
if not root:
return
cursum += root.val
if sumDic.get(cursum - targetSum, None):
res[0] += sumDic.get(cursum - targetSum, None)
sumDic[cursum] = sumDic.get(cursum, 0) + 1
backtrack(root.left, cursum, sumDic)
backtrack(root.right, cursum, sumDic)
sumDic[cursum] -= 1
backtrack(root, 0, {0:1})
return res[0]
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指字母相同,但排列不同的字符串。
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
tableS = [0] * 26
tableP = [0] * 26
for c in p:
tableP[ord(c) - ord("a")] += 1
lenp = len(p)
lens = len(s)
if lenp>lens:
return []
for i in range(lenp):
tableS[ord(s[i]) - ord("a")] += 1
if tableP == tableS:
res = [0]
else:
res = []
for j in range(1, lens-lenp+1):
tableS[ord(s[j-1]) - ord("a")] -= 1
tableS[ord(s[j+lenp-1]) - ord("a")] += 1
if tableS == tableP:
res.append(j)
return res
448. 找到所有数组中消失的数字
class Solution:
# def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
# out = []
# for i in range(len(nums)):
# index = nums[i] - 1
# while nums[i]!=0 and nums[index] != 0:
# tmpIndex = nums[index] - 1
# nums[index] = 0
# index = tmpIndex
# for i in range(len(nums)):
# if nums[i] != 0:
# out.append(i+1)
# return out
def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
# out = []
n = len(nums)
for i in range(n):
nums[(nums[i] - 1)%n] += n
# for i in range(len(nums)):
# if nums[i] <= n:
# out.append(i+1)
return [i+1 for i, num in enumerate(nums) if num<=n]
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
vector<int> out;
int n=nums.size();
for (int num:nums){
int index = (num-1) % n;
nums[index] += n;
}
for (int i=0; i<n; ++i){
if (nums[i]<=n){
out.push_back(i+1);
}
}
return out;
}
};
461. 汉明距离
class Solution:
def countOne(self, n):
if n == 1:
return 1
if n == 0:
return 0
return self.countOne(n&(n-1))+1
def hammingDistance(self, x: int, y: int) -> int:
return self.countOne(x^y)
class Solution {
public:
int countOne(int n){
if (0==n) return 0;
if (1==n) return 1;
return countOne(n&(n-1))+1;
}
int hammingDistance(int x, int y) {
return countOne(x^y);
}
};
输入:nums = [1,1,1,1,1], target = 3
输出:5
解释:一共有 5 种方法让最终目标和为 3 。
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3
# 递归
# class Solution:
# def findTargetSumWays(self, nums: List[int], target: int) -> int:
# allsum = sum(nums)
# if (allsum + target) % 2 == 1:
# return 0
# tar = (allsum + target) // 2
# res = [0]
# def backtrack(choice, cursum):
# if cursum == tar:
# res[0] += 1
# if cursum > tar:
# return
# for i in range(len(choice)):
# backtrack(choice[i+1:], cursum+choice[i])
# nums.sort()
# backtrack(nums, 0)
# return res[0]
# 动态规划
class Solution:
def findTargetSumWays(self, nums: List[int], target: int) -> int:
allsum = sum(nums)
if (allsum - target) % 2 == 1 or (allsum - target) < 0:
return 0
tar = (allsum - target) // 2
table = [1] + [0] * tar
for num in nums:
for i in range(tar, -1, -1):
if i>= num:
table[i] = table[i] + table[i-num]
return table[-1]
543. 二叉树的直径
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def dfs(self, root, out):
if root is None:
return 0
L = self.dfs(root.left, out)
R = self.dfs(root.right, out)
out[0] = max(out[0], L+R+1)
return max(L,R)+1
def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int:
out = [0]
self.dfs(root, out)
return out[0]-1
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int out;
int dfs(TreeNode* root){
if (!root) return 0;
int L = dfs(root->left);
int R = dfs(root->right);
out = max(out, R+L+1);
return max(L, R)+1;
}
int diameterOfBinaryTree(TreeNode* root) {
dfs(root);
return out-1;
}
};
输入:nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
sumDic = {0:1}
res = 0
temSum = 0
for num in nums:
temSum += num
if sumDic.get(temSum - k, "no") != "no":
res += sumDic.get(temSum - k, "no")
sumDic[temSum] = sumDic.get(temSum, 0) + 1
return res
输入:nums = [2,6,4,8,10,9,15]
输出:5
解释:你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。
class Solution:
def findUnsortedSubarray(self, nums: List[int]) -> int:
n = len(nums)
left, right, leftmin, rightmax = 1, 0, inf, -inf
for i in range(n):
if nums[i] < rightmax:
right = i
else:
rightmax = nums[i]
if nums[n-i-1] > leftmin:
left = n -i - 1
else:
leftmin = nums[n-i-1]
return right-left+1
617. 合并二叉树
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def dfs(self, root1, root2):
if root1 is None or root2 is None:
return root1 if root1 else root2
root1.left = self.dfs(root1.left, root2.left)
root1.right = self.dfs(root1.right, root2.right)
root1.val = root1.val + root2.val
return root1
def bfs(self, root1, root2):
if root1 is None or root2 is None:
return root1 if root1 else root2
merged = TreeNode(root1.val + root2.val)
que = [merged]
que1 = [root1]
que2 = [root2]
while que1 and que2:
node = que.pop()
node1 = que1.pop()
node2 = que2.pop()
L1, R1 = node1.left, node1.right
L2, R2 = node2.left, node2.right
if L1 or L2:
if L1 and L2:
left = TreeNode(L1.val + L2.val)
node.left = left
que.append(left)
que1.append(L1)
que2.append(L2)
elif L1:
node.left = L1
elif L2:
node.left = L2
if R1 or R2:
if R1 and R2:
right = TreeNode(R1.val + R2.val)
node.right = right
que.append(right)
que1.append(R1)
que2.append(R2)
elif R1:
node.right = R1
elif R2:
node.right = R2
return merged
def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
# return self.dfs(root1, root2)
return self.bfs(root1, root2)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* dfs(TreeNode* root1, TreeNode* root2){
if (!root1) return root2;
if (!root2) return root1;
root1->left = dfs(root1->left, root2->left);
root1->right = dfs(root1->right, root2->right);
root1->val = root1->val + root2->val;
return root1;
}
TreeNode* bfs(TreeNode* t1, TreeNode* t2){
if (!t1) return t2;
if (!t2) return t1;
TreeNode* merged = new TreeNode(t1->val + t2->val);
queue<TreeNode*> que;
queue<TreeNode*> que1;
queue<TreeNode*> que2;
que.push(merged);
que1.push(t1);
que2.push(t2);
while (!que1.empty() && !que2.empty()){
TreeNode* node = que.front();
que.pop();
TreeNode* node1 = que1.front();
que1.pop();
TreeNode* node2 = que2.front();
que2.pop();
TreeNode* L1 = node1->left;
TreeNode* R1 = node1->right;
TreeNode* L2 = node2->left;
TreeNode* R2 = node2->right;
if (L1 || L2){
if (L1 && L2){
TreeNode* left = new TreeNode(L1->val + L2->val);
node->left = left;
que.push(left);
que1.push(L1);
que2.push(L2);
}
else if (L1){
node->left = L1;
}
else if (L2){
node->left = L2;
}
}
if (R1 || R2){
if (R1 && R2){
TreeNode* right = new TreeNode(R1->val + R2->val);
node->right = right;
que.push(right);
que1.push(R1);
que2.push(R2);
}
else if (R1){
node->right = R1;
}
else if (R2){
node->right = R2;
}
}
}
return merged;
}
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
// return dfs(root1, root2);
return bfs(root1, root2);
}
};
输入:tasks = ["A","A","A","B","B","B"], n = 2
输出:8
解释:A -> B -> (待命) -> A -> B -> (待命) -> A -> B
在本示例中,两个相同类型任务之间必须间隔长度为 n = 2 的冷却时间,而执行一个任务只需要一个单位时间,所以中间出现了(待命)状态。
class Solution:
def leastInterval(self, tasks: List[str], n: int) -> int:
table = [0] * 26
for c in tasks:
table[ord(c)-ord("A")] += 1
maxc = max(table)
total = (maxc-1) * (n+1)
for i in table:
if i == maxc:
total += 1
return max(total, len(tasks))
输入:"aaa"
输出:6
解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"
class Solution:
def countSubstrings(self, s: str) -> int:
def countCurstring(left, right):
cur = 0
while left>=0 and right<len(s) and s[left] == s[right]:
cur += 1
left -= 1
right += 1
return cur
res = 0
for i in range(len(s)):
res += countCurstring(i, i)
res += countCurstring(i, i+1)
return res
请根据每日 气温 列表 temperatures ,请计算在每一天需要等几天才会有更高的温度。如果气温在这之后都不会升高,请在该位置用 0 来代替。
示例 1:
输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]
class Solution:
def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
stack = [0]
res = [0] * len(temperatures)
for i in range(1, len(temperatures)):
while stack and temperatures[i] > temperatures[stack[-1]]:
cur = stack.pop(-1)
res[cur] = i - cur
stack.append(i)
return res