classSolution: defmaxProfit(self, prices: List[int]) -> int: result = 0 for i inrange(len(prices)): for j inrange(i+1, len(prices)): tmp = prices[j] - prices[i] if tmp > result: result = tmp return result
# Your MinStack object will be instantiated and called as such: # obj = MinStack() # obj.push(val) # obj.pop() # param_3 = obj.top() # param_4 = obj.getMin()
func (this *MinStack) Top() int { returnthis.stack[len(this.stack)-1] }
func (this *MinStack) GetMin() int { returnthis.minStack[len(this.minStack)-1] }
func min(x, y int) int { if x < y { return x } return y }
/** * Your MinStack object will be instantiated and called as such: * obj := Constructor(); * obj.Push(val); * obj.Pop(); * param_3 := obj.Top(); * param_4 := obj.GetMin(); */
# Your MinStack object will be instantiated and called as such: # obj = MinStack() # obj.push(val) # obj.pop() # param_3 = obj.top() # param_4 = obj.getMin()
func (this *MinStack) Top() int { if len(this.stack) > 0{ diff := this.stack[len(this.stack)-1] if diff < 0{ top := this.minValue return top }else{ top := diff + this.minValue return top } } return -1 }
func (this *MinStack) GetMin() int { returnthis.minValue }
/** * Your MinStack object will be instantiated and called as such: * obj := Constructor(); * obj.Push(val); * obj.Pop(); * param_3 := obj.Top(); * param_4 := obj.GetMin(); */
classSolution { public: intfindMin(vector<int>& nums){ int ans = INT_MAX; int left = 0, right = nums.size()-1; while (left <= right) { int mid = left + (right-left)/2; // 左边有序,left即为左边最小值,需要去右边找 if (nums[left] <= nums[mid]) { ans = min(ans, nums[left]); left = mid + 1; }else{ // 右边有序,mid即为右边最小值,需要去左边找 ans = min(ans, nums[mid]); right = mid - 1; } } // cout << left << " " << right << endl; return ans;
func mySqrt(x int) int { l, r := 0, x ans := -1 for l <= r{ mid:= l + (r-l)/2 ifmid*mid <= x{ ans = mid l = mid + 1 }else{ r = mid - 1 } } return ans }
funclengthOfLIS(nums []int)int { result := 0; length := len(nums); dp := make([]int, length); for j := 0; j < length; j++{ dp[j] = 1; for i := 0; i < j; i++{ if nums[i] < nums[j]{ if dp[i]+1 > dp[j]{ dp[j] = dp[i]+1; } } } if dp[j] > result{ result = dp[j]; } } return result;
}
python3语言版本
1 2 3 4 5 6 7 8 9 10
class Solution: def lengthOfLIS(self, nums: List[int]) -> int: result = 0 dp = [1]*len(nums) forj in range(0, len(nums)): for i in range(0, j): if nums[i] < nums[j] anddp[i]+1 > dp[j]: dp[j] = dp[i]+1 result = dp[j] ifdp[j] > result else result return result
二分查找
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
class Solution: def lengthOfLIS(self, nums: List[int]) -> int: # 开一个栈,每次取栈顶元素top和读到的元素temp做比较,如果temp > top 则将temp入栈;如果temp < top则二分查找栈中的比temp大的第1个数,并用temp替换它。 最长序列长度即为栈的大小top。 stack = list() forein nums: if not stack or stack[-1] < e: stack.append(e) else: # 二分查找,寻找第一个大于e的数 low = 0 high = len(stack) - 1 while low <= high: mid = low + (high-low)//2 ife > stack[mid]: low = mid + 1 else: high = mid -1 stack[low] = e return len(stack)
classSolution: defthreeSum(self, nums: List[int]) -> List[List[int]]: n = len(nums) result = list() for i inrange(n): for j inrange(i+1, n): for k inrange(j+1, n): if nums[i]+nums[j]+nums[k] == 0: tmp = [nums[i], nums[j], nums[k]] tmp.sort() if tmp in result: continue result.append(tmp) return result
classSolution: defthreeSum(self, nums: List[int]) -> List[List[int]]: n = len(nums) result = list() nums.sort()
for i inrange(n): if i > 0and nums[i] == nums[i-1]: continue # print(n,i) target = -nums[i] k = n - 1 for j inrange(i+1, n): # 需要保证j和前一个不同 if j > i+1and nums[j] == nums[j-1]: continue # 选定i,j后选k while j < k and nums[k] + nums[j] > target: k = k - 1 if j == k: break if nums[k] + nums[j] == target: result.append([nums[i],nums[j],nums[k]]) return result
classSolution: deflongestPalindrome(self, s: str) -> str: defhelper(s, i, j): while i >= 0and j < length and s[i] == s[j]: i = i - 1 j += 1 return i+1, j-1 length = len(s) count = 0 result = "" for i inrange(length): left,right = helper(s, i, i+1) if right -left >= count: count = right - left result = s[left:right+1] # 这个地方比较巧妙 left,right = helper(s, i, i) if right -left >= count: count = right - left result = s[left:right+1] return result
classSolution: deflongestPalindrome(self, s: str) -> str: n = len(s) if n < 2: return s dp = [[False]*n for _ inrange(n)] max_length = 1 left = 0 # L 表示子串长度 for L inrange(1, n+1): # i表示左index,j表示右index for i inrange(n): j = L + i - 1 # j非法时,退出循环 if j > n - 1: break if s[i] != s[j]: dp[i][j] = False else: if L <= 2: dp[i][j] = True else: dp[i][j] = dp[i+1][j-1] if dp[i][j] and L > max_length: max_length = L left = i return s[left:left+max_length]
left = 0 right = columns - 1 top = 0 bottom = rows - 1 result = [] while total > 0: for i inrange(left, right+1): # 通过总数控制循环是否停止 if total == 0: break # print(top, i) result.append(matrix[top][i]) total = total - 1 # 每次循环完成后,某一个坐标需要改变 top += 1
for i inrange(top, bottom+1): if total == 0: break # print(i, right) result.append(matrix[i][right]) total = total - 1 right = right - 1
for i inrange(right, left-1, -1): if total == 0: break # print(bottom, i) result.append(matrix[bottom][i]) total = total - 1 bottom = bottom - 1
for i inrange(bottom, top-1, -1): if total == 0: break # print("----", i, left) result.append(matrix[i][left]) total = total - 1 left += 1 return result
classSolution: defreverseString(self, s: List[str]) -> None: """ Do not return anything, modify s in-place instead. """ length = len(s) i = 0 j = length - 1 while i < j: s[i], s[j] = s[j], s[i] i = i + 1 j = j - 1 return s
C++版本
1 2 3 4 5 6 7 8 9 10 11
classSolution { public: voidreverseString(vector<char>& s){ int n = s.size(); for (int i = 0, j = n-1; i < n/2; i++, j--){ char tmp = s[i]; s[i] = s[j]; s[j] = tmp; } } };
541. 反转字符串 II
给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
如果剩余字符少于 k 个,则将剩余字符全部反转。 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例 1:
输入:s = “abcdefg”, k = 2 输出:”bacdfeg” 示例 2:
输入:s = “abcd”, k = 2 输出:”bacd”
1 2 3 4 5 6 7 8 9 10
classSolution { public: string reverseStr(string s, int k){ int n = s.size(); for (int i = 0; i < n; i += 2*k){ reverse(s.begin()+i, s.begin()+min(i+k, n)); } return s; } };
# Definition for singly-linked list. # class ListNode: # def __init__(self, x): # self.val = x # self.next = None
classSolution: defgetIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode: a = 0 b = 0 p = headA q = headB # 先计算各自长度 while p: p = p.next a += 1
while q: q = q.next b += 1 p = headA q = headB print('a,b', a, b) c = a - b if c > 0: p = headA q = headB else: p = headB q = headA c = -c
# 长链表先走,然后一起走 while c: ifnot p ornot q: returnNone p = p.next c = c - 1 while p and q: if p == q: return p p = p.next q = q.next returnNone
classSolution: deffindLength(self, nums1: List[int], nums2: List[int]) -> int: ans = 0 for i inrange(len(nums1)): for j inrange(len(nums2)): k = 0 while i+k < len(nums1) and j+k < len(nums2) and nums1[i+k] == nums2[j+k]: k += 1 ans = max(ans, k) return ans
classSolution: deffindLength(self, nums1: List[int], nums2: List[int]) -> int: m = len(nums1) n = len(nums2) ans = 0 j = 0 for offset inrange(m): i = offset j = 0 while i < m and j < n: count = 0 while i < m and j < n and nums1[i] == nums2[j]: count += 1 i += 1 j += 1 j += 1 i += 1 ans = max(ans, count) for offset inrange(n): j = offset i = 0 while i < m and j < n: count = 0 # print('i, j, count', i, j, count) while i < m and j < n and nums1[i] == nums2[j]: count += 1 i += 1 j += 1 j += 1 i += 1 ans = max(ans, count) return ans
classSolution: deffindLength(self, nums1: List[int], nums2: List[int]) -> int: defhelper(start1, start2, length): k = 0 ans = 0 for i inrange(length): if nums1[start1+i] == nums2[start2+i]: k += 1 else: k = 0 ans = max(ans, k) return ans
m = len(nums1) n = len(nums2) ans = 0 for i inrange(m): length = min(m-i, n) # 小优化,length如果小于ans,则无需比较了 if length > ans: ans = max(ans, helper(i, 0, length)) for i inrange(n): length = min(n-i, m) if length > ans: ans = max(ans, helper(0, i, length)) return ans
classSolution: deffindLength(self, nums1: List[int], nums2: List[int]) -> int: m = len(nums1) n = len(nums2) dp = [[0]*(n+1) for _ inrange(m+1)] ans = 0 for i inrange(1, m+1): for j inrange(1, n+1): if nums1[i-1] == nums2[j-1]: dp[i][j] = dp[i-1][j-1] + 1 else: dp[i][j] = 0 ans = max(dp[i][j], ans) return ans
# Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None
class Solution: def levelOrder(self, root: TreeNode) -> List[List[int]]: ans = [] ifnot root: return ans queue = collections.deque() queue.append(root) flag = False while queue: length = len(queue) # 结果集也用双端队列,省去一次翻转动作 result = collections.deque() for i in range(length): p = queue.popleft() if flag: result.appendleft(p.val) else: result.append(p.val) if p.left: queue.append(p.left) if p.right: queue.append(p.right) ans.append(list(result)) flag = not flag return ans
# Definition fora binary tree node. # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None
class Solution: def levelOrder(self, root: TreeNode) -> List[List[int]]: ans = [] if not root: return ans queue = collections.deque() queue.append(root) while queue: # 处理奇数层 从左向右打印 从左向右添加下层节点 length = len(queue) result = list() for i in range(length): p = queue.popleft() result.append(p.val) ifp.left: queue.append(p.left) ifp.right: queue.append(p.right) ans.append(list(result)) if not queue: break # 处理偶数层 从右向左打印 从右向左添加下层节点 length = len(queue) result = list() for i in range(length): p = queue.pop() result.append(p.val) ifp.right: queue.appendleft(p.right) ifp.left: queue.appendleft(p.left) ans.append(list(result)) return ans
class Solution: def addStrings(self, num1: str, num2: str) -> str: if not num1: return num2 if not num2: return num1 i = len(num1)-1 j = len(num2)-1 carry = 0 result = "" while i >= 0 or j >= 0 or carry: if i >= 0: first = num1[i] else: first = 0 if j >= 0: second = num2[j] else: second = 0 # print('i, j', i, j) # print('first, second, carry', first, second, carry) tmp = int(first) + int(second) + carry result = str(tmp%10) + result carry = tmp // 10 i = i - 1 j = j - 1 return result
# 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: ListNode, n: int) -> ListNode: dummy = ListNode() dummy.next = head
early = dummy while early and n > 0: early = early.next n = n - 1
normal = dummy prev = dummy while early: prev = normal normal = normal.next early = early.next # print(early, normal) prev.next = normal.next del normal return dummy.next
# Definition for singly-linked list. # class ListNode: # def __init__(self, x): # self.val = x # self.next = None
classSolution: defdetectCycle(self, head: ListNode) -> ListNode: exists = dict() while head: if head in exists: return head exists[head] = 1 head = head.next returnNone
快慢指针
设链表中环外部分的长度为 a。 slow指针进入环后,又走了 b 的距离与fast 相遇。 此时,fast 指针已经走完了环的 n 圈,因此它走过的总距离为 a+n(b+c)+b=a+(n+1)b+nc
classSolution: defmaxSubArray(self, nums: List[int]) -> int: ifnot nums: return0 result = nums[0] f = [nums[0]] for i inrange(1, len(nums)): tmp = f[i-1] + nums[i] if tmp >= nums[i]: f.append(tmp) else: f.append(nums[i]) returnmax(f)
考虑到题目中只需要求出最大值即可,可以对空间复杂度做一些优化
1 2 3 4 5 6 7 8 9 10
class Solution: def maxSubArray(self, nums: List[int]) ->int: if not nums: return0 result= nums[0] f = nums[0] for i inrange(1, len(nums)): f =max(f+nums[i], nums[i]) result=max(f, result) returnresult
classSolution: defmaxSubArray(self, nums: List[int]) -> int: ifnot nums: return0 result = nums[0] f = nums[0] maxIndex = 0 for i inrange(1, len(nums)): tmp = f + nums[i] if tmp >= nums[i]: f = tmp else: f = nums[i] if f > result: result = f maxIndex = i # print(f,maxIndex) resultList = [] for i inrange(maxIndex, -1, -1): ifsum(resultList) == result: print(resultList) break else: resultList.insert(0, nums[i]) return result
# 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, tail): if not head: return head # 注意这里需要保留与tail之后数据的连接 pre = tail.next p = head whilepre != tail: q = p.next p.next = pre pre = p p = q returnpre, head
def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]: dummy = ListNode() dummy.next = head left = dummy tail = dummy # print('left,right,head',left.val, right.val,head.val) while head: for i in range(k): tail = tail.next if not tail: return dummy.next # print('head,tail',head,tail) # 开始翻转前先记录被翻转部分的左右两部分 right = tail.next new_head, new_tail = self.reverseList(head, tail) # print('new_head,new_tail',new_head,new_tail) # 翻转后的新链表连接到原链表中间 left.next = new_head new_tail.next = right
# 重新初始化待翻转链表的head、tail以及左半部分 head = new_tail.next tail = new_tail
classSolution: defclimbStairs(self, n: int) -> int: if n == 0or n == 1: return1 if n == 2: return2 return self.climbStairs(n-1) + self.climbStairs(n-2)
动态规划的方法
时间复杂度和空间复杂度都是O(n)
1 2 3 4 5 6 7 8 9 10
classSolution: defclimbStairs(self, n: int) -> int: if n == 0or n == 1: return1 result = [1] * (n+1) result[2] = 1 for i inrange(2, n+1): result[i] = result[i-1] + result[i-2] return result[n]
classSolution: defclimbStairs(self, n: int) -> int: if n == 0or n == 1: return1 p = 0 q = 0 r = 1 for i inrange(1, n+1): p = q q = r r = p + q return r
def partitionK(self, nums, left, right, k): while left < right: index = self.partition(nums, left, right) length = index-left+1 if k == length: break if k < length: right = index-1 if k > length: left = index + 1 k = k - length
class Solution: def getLeastNumbers(self, arr: List[int], k: int) -> List[int]: if not arr or k == 0: return [] self.partitionK(arr, 0, len(arr)-1, k) return arr[:k]
def partitionK(self, nums, l, r, k): index = self.partition(nums, l, r) length = index - l + 1 # print("index,nums,l,r,k, length",index,nums,l,r,k, length) if k > length: self.partitionK(nums, index+1, r, k-length) if k < length: self.partitionK(nums, l, index-1, k)
def partition(self, nums, l, r): self.swap(nums, l, l+(r-l)//2) # print("partition,nums", nums) pivot = l index = l+1 for i in range(index, r+1): # print('i,index,nums', i,index,nums) if nums[i] < nums[pivot]: self.swap(nums, index, i) index += 1 # print("partition2,nums", nums) self.swap(nums, pivot, index-1) returnindex-1
def swap(self, nums, i, j): nums[i],nums[j] = nums[j], nums[i]
# Definition fora 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]]: result = [] if not root: return result p = root queue = [root] while queue: levelQueue = [] level = len(queue) # print("queue, level", [e.val fore in queue], level) for i in range(level): p = queue.pop(0) levelQueue.append(p.val) ifp.left: queue.append(p.left) ifp.right: queue.append(p.right) result.append(list(levelQueue)) return result
# 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 classSolution: defpreorderTraversal(self, root: Optional[TreeNode]) -> List[int]: result = [] ifnot root: return result result.append(root.val) result += self.preorderTraversal(root.left) result += self.preorderTraversal(root.right) return result
class Solution: def partition(self, nums, left, right): # 选择pivot是一个比较关键的点,影响最好最快的复杂度 if nums[left] < nums[right]: self.swap(nums, left, left+(right-left)//2) pivot = left index = left+1 for i in range(index, right+1): # 同样的,升序或降序只需要修改下面的比较符号即可 if nums[i] < nums[pivot]: self.swap(nums, i, index) index += 1 self.swap(nums, index-1, pivot) returnindex-1
class Solution: def partition(self, nums, left, right): if nums[left] < nums[right]: self.swap(nums, left, left+(right-left)//2) pivot = left index = left+1 for i in range(index, right+1): if nums[i] < nums[pivot]: self.swap(nums, i, index) index += 1 self.swap(nums, index-1, pivot) returnindex-1
def swap(self, nums, left, right): nums[left], nums[right] = nums[right], nums[left] def quickSort(self, nums, left, right): ifleft < right: stack = [right, left] while stack: i = stack.pop() j = stack.pop() pivot_index = self.partition(nums, i, j) if i < pivot_index: stack.append(pivot_index-1) stack.append(i) if pivot_index < j: stack.append(j) stack.append(pivot_index+1) return nums
// 递归版本 voidquickSort(vector<int>& nums, int left, int right){ if (left < right){ int pivot = partition(nums, left, right); quickSort(nums, left, pivot-1); quickSort(nums, pivot+1, right); } }
// 非递归版本 voidquickSort2(vector<int>& nums, int left, int right){ if (left < right){ stack<int> s; s.push(right); s.push(left); while (!s.empty()){ int l = s.top(); s.pop(); int r = s.top(); s.pop(); int pivot = partition(nums, l, r); // l, pivot-1 // pivot+1, r if (l < pivot-1){ s.push(pivot-1); s.push(l); } if (pivot+1 < r){ s.push(r); s.push(pivot+1); } } } }
//快排的核心函数 intpartition(vector<int>& nums, int left, int right){ int mid = left + (right - left)/2; if (nums[left] < nums[right]){ swap(nums[left], nums[mid]); } int pivot = left; int index = left+1; for (int i = left+1; i <= right; i++){ if (nums[i] < nums[pivot]){ swap(nums[i], nums[index++]); } } swap(nums[index-1], nums[pivot]); return index-1; } };
def merge(self, nums, begin, mid, end): result = [] i, j = begin, mid while i < midand j < end: if nums[i] <= nums[j]: result.append(nums[i]) i += 1 else: result.append(nums[j]) j += 1 result += nums[i:mid] result += nums[j:end] nums[begin:end] = result
defheapSort(self, nums): self.buildHeap(nums) for i inrange(len(nums)-1, -1, -1): self.swap(nums, i, 0) self.adjust(nums, 0, i) return nums defswap(self, nums, i, j): nums[i], nums[j] = nums[j], nums[i]
defbuildHeap(self, nums): for i inrange(len(nums)//2, -1, -1): self.adjust(nums, i, len(nums))
defadjust(self, nums, i, length): temp = nums[i] k = 2*i + 1 while k < length: # 升序和降序修改此处第二个比较符号 if k+1 < length and nums[k+1] > nums[k]: k += 1 # 升序和降序修改此处比较符号 if nums[k] > temp: nums[i] = nums[k] i = k k = 2*k + 1 nums[i] = temp
# Definition for singly-linked list. # class ListNode: # def __init__(self, val=0, next=None): # self.val = val # self.next = next # pre初始指向空,p指向当前待处理节点,初始为head,q记录p的下一个节点 # p连上上一个节点pre,pre变为当前节点p,p后移指向下一个待处理节点q # 结束时,p为空,pre为最后被处理的节点,即新链表的头节点 classSolution: defreverseList(self, head: ListNode) -> ListNode: ifnot head: return head pre = None p = head while p: q = p.next p.next = pre pre = p p = q return pre
方法三:迭代求解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
# Definition for singly-linked list. # class ListNode: # def __init__(self, val=0, next=None): # self.val = val # self.next = next # 以第一个节点为未反转部分,剩下部分为已求解部分 # 第二个节点为已求解部分最后的一个节点,将最后一个未反转节点加入已求解部分 # 注意两点:1. head.next为空需要提前判断,否则有语法错误 2.最终一个节点的next为None classSolution: defreverseList(self, head: ListNode) -> ListNode: ifnot head ornot head.next: return head right = self.reverseList(head.next) head.next.next = head head.next = None return right
Golang
C
C++
92. 反转链表 II
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
# Definition for singly-linked list. # class ListNode: # def __init__(self, val=0, next=None): # self.val = val # self.next = next classSolution: defreverseBetween(self, head: ListNode, left: int, right: int) -> ListNode: # head为第一个要处理的节点,tail为要处理节点的下一个节点,可能为None defreverseList(head, tail): prev = tail cur = head p = head while p != tail: p = p.next cur.next = prev prev = cur cur = p return prev
dummy = ListNode(next=head) p = dummy count = 0 prev_node = dummy right_node = None while p: if count == left-1: prev_node = p if count == right: right_node = p break p = p.next count += 1 # print(prev_node.val, right_node.val) ifnot right_node: prev_node.next = reverseList(prev_node.next, None) else: prev_node.next = reverseList(prev_node.next, right_node.next) return dummy.next
As you get ready for your interviews, consider these suggestions:
Write Code on Paper
Know Your Resume
Don’t Memorize Solutions
Talk Out Loud
Receiving an offer is not about solving questions flawlessly (very few candidates do!), but rather, it is about answering questions better than other candidates. So don’t stress out when you get a tricky question - everyone else probably thought it was hard too!