import requests
import base64
import time


def get_img_res():
img = ""
start_time = time.time()
with open('img1.png', 'rb') as image_file:
# 将图片内容转换为 base64 编码
base64_image = base64.b64encode(image_file.read()).decode('utf-8')
time1 = time.time()
# 打印 base64 编码
print(base64_image)
dst_url = 'http://127.0.0.1:1224/api/ocr'
param = {'base64': base64_image, 'options': {}}

res = requests.post(dst_url, json=param)
time2 = time.time()

print(f'Base64 encode time: {time1 - start_time}')

print(f'ocr response time: {time2 - time1}')
print(f'All time: {time2 - start_time}')


def kacoder():
import sys

n = int(input())
list_x = [int(i) for i in input().split(' ')]
list_y = [int(i) for i in input().split(' ')]
list_z = [int(i) for i in input().split(' ')]
sum_x = sorted([list_x[i] - list_y[i] - list_z[i] for i in range(n)], reverse=True)
sum_y = sorted([list_y[i] - list_x[i] - list_z[i] for i in range(n)], reverse=True)
sum_z = sorted([list_z[i] - list_y[i] - list_x[i] for i in range(n)], reverse=True)
sum_number = 0
max_x = 0
for i in range(n):
sum_number += sum_x[i]
if sum_number <= 0:
break
else:
max_x = i
sum_number = 0
max_y = 0
for i in range(n):
sum_number += sum_y[i]
if sum_number <= 0:
break
else:
max_y = i
sum_number = 0
max_z = 0
for i in range(n):
sum_number += sum_z[i]
if sum_number <= 0:
break
else:
max_z = i
res = max(max_x, max_y, max_z)
res = res + 1 if res > 0 else -1
print(res)


"""
有一个长度为 n 的 01 串,其中有一些位置标记为 ?,这些位置上可以任意填充 0 或者 1,请问如何填充这些位置使得这个 01 串中出现互不重叠的 00 和 11 子串最多,输出子串个数。
"""


def kacoder_b():
src_str = input()
len_str = len(src_str)
for i in range(len_str):
pass


# kacoder_b()

# -*- coding:utf-8 -*-
"""242. Valid Anagram
Given two strings s and t, return true if t is an anagram of s, and false otherwise.

An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.



Example 1:

Input: s = "anagram", t = "nagaram"
Output: true
Example 2:

Input: s = "rat", t = "car"
Output: false"""


def isAnagram(s: str, t: str) -> bool:
str_count = [0] * 26
for item in s:
str_count[ord(item) - ord('a')] += 1
for item in t:
str_count[ord(item) - ord('a')] -= 1
return set(str_count) == {0}


# isAnagram("anagram", "nagaram")
"""383. Ransom Note
Given two strings ransomNote and magazine, return true if ransomNote can be constructed by using the letters from magazine and false otherwise.

Each letter in magazine can only be used once in ransomNote."""


def canConstruct(ransomNote: str, magazine: str) -> bool:
str_count = [0] * 26
for item in ransomNote:
str_count[ord(item) - ord('a')] += 1
for item in magazine:
str_count[ord(item) - ord('a')] -= 1
for item in str_count:
if item > 0:
return False
return True


"""
49. Group Anagrams
Given an array of strings strs, group the anagrams together. You can return the answer in any order.

An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.



Example 1:

Input: strs = ["eat","tea","tan","ate","nat","bat"]
Output: [["bat"],["nat","tan"],["ate","eat","tea"]]
Example 2:

Input: strs = [""]
Output: [[""]]
Example 3:

Input: strs = ["a"]
Output: [["a"]]"""


def groupAnagrams(strs):
res = []
hashmap_list = []
for item_str in strs:
hashmap = [0] * 26
for item in item_str:
hashmap[ord(item) - ord('a')] += 1
if hashmap not in hashmap_list:
hashmap_list.append(hashmap)
res.append([item_str])
else:
index = hashmap_list.index(hashmap)
res[index].append(item_str)
return res


"""438. Find All Anagrams in a String
Given two strings s and p, return an array of all the start indices of p's anagrams in s. You may return the answer in any order.

An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.

class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:

Example 1:

Input: s = "cbaebabacd", p = "abc"
Output: [0,6]
Explanation:
The substring with start index = 0 is "cba", which is an anagram of "abc".
The substring with start index = 6 is "bac", which is an anagram of "abc".
Example 2:

Input: s = "abab", p = "ab"
Output: [0,1,2]
Explanation:
The substring with start index = 0 is "ab", which is an anagram of "ab".
The substring with start index = 1 is "ba", which is an anagram of "ab".
The substring with start index = 2 is "ab", which is an anagram of "ab"."""


def findAnagrams(s, p):
import copy
res = []
hashmap = [0] * 26
ls = len(s)
lp = len(p)
for item in p:
hashmap[ord(item) - ord('a')] += 1
hashmap_tmp = [0] * 26
i, j = 0, 0
while i < ls - lp + 1:
while j < i + lp:
hashmap_tmp[ord(s[j]) - ord('a')] += 1
j += 1
if hashmap_tmp == hashmap:
res.append(i)
hashmap_tmp[ord(s[i]) - ord('a')] -= 1
i += 1
return res


# print(findAnagrams("cbaebabacd", "abc"))


"""349. Intersection of Two Arrays
Given two integer arrays nums1 and nums2, return an array of their intersection. Each element in the result must be unique and you may return the result in any order.



Example 1:

Input: nums1 = [1,2,2,1], nums2 = [2,2]
Output: [2]
Example 2:

Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
Output: [9,4]
Explanation: [4,9] is also accepted."""


def intersection(nums1, nums2):
from collections import defaultdict
res = []
hashmap = defaultdict(int)
for item in nums1:
hashmap[item] += 1
for item in nums2:
if hashmap[item] > 0:
res.append(item) if item not in res else None
return res


# print(intersection([4,9,5],[9,4,9,8,4]))

"""350. Intersection of Two Arrays II
Given two integer arrays nums1 and nums2, return an array of their intersection. Each element in the result must appear as many times as it shows in both arrays and you may return the result in any order.



Example 1:

Input: nums1 = [1,2,2,1], nums2 = [2,2]
Output: [2,2]
Example 2:

Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
Output: [4,9]
Explanation: [9,4] is also accepted."""


def intersect(nums1, nums2):
from collections import defaultdict
res = []
hashmap = defaultdict(int)
for item in nums1:
hashmap[item] += 1
for item in nums2:
if hashmap[item] > 0:
res.append(item)
hashmap[item] -= 1
return res


# print(intersect([1,2,2,1], [2,2]))
"""202. Happy Number
Write an algorithm to determine if a number n is happy.

A happy number is a number defined by the following process:

Starting with any positive integer, replace the number by the sum of the squares of its digits.
Repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1.
Those numbers for which this process ends in 1 are happy.
Return true if n is a happy number, and false if not.



Example 1:

Input: n = 19
Output: true
Explanation:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
Example 2:

Input: n = 2
Output: false"""


def isHappy(n):
def sum_of_squares(num):
res = 0
while num:
digit = num % 10
res += digit * digit
num = num // 10
return res

res_list = []
while True:
next_n = sum_of_squares(n)
if next_n == 1:
return True
if next_n not in res_list:
res_list.append(next_n)
n = next_n
else:
return False


# print(isHappy(2))

"""1. Two Sum
Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
You can return the answer in any order.


Example 1:

Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].
Example 2:

Input: nums = [3,2,4], target = 6
Output: [1,2]
Example 3:

Input: nums = [3,3], target = 6
Output: [0,1]"""


def twoSum(nums, target):
from collections import defaultdict
res = []
hashmap = defaultdict(int)
for item in nums:
hashmap[item] += 1
for i in range(len(nums) - 1, -1, -1):
if nums[i] == target - nums[i]:
if hashmap[target - nums[i]] > 1:
return [i, nums.index(nums[i])]
elif hashmap[target - nums[i]] > 0:
return [i, nums.index(target - nums[i])]
return res


# print(twoSum([3,3], 6))

"""454. 4Sum II
Given four integer arrays nums1, nums2, nums3, and nums4 all of length n, return the number of tuples (i, j, k, l) such that:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

Example 1:
Input: nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]
Output: 2
Explanation:
The two tuples are:
1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0
2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0
Example 2:

Input: nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0]
Output: 1"""


def fourSumCount(nums1, nums2, nums3, nums4):
from collections import defaultdict
count = 0
hashmap_ab = defaultdict(int)
hashmap_cd = defaultdict(int)
for i in nums1:
for j in nums2:
hashmap_ab[i + j] += 1
for i in nums3:
for j in nums4:
hashmap_cd[i + j] += 1
for k, v in hashmap_cd.items():
if 0 - k in hashmap_ab:
count += v * hashmap_ab[0 - k]
return count


# print(fourSumCount([1,], [-2,], [-1], [2]))

"""15. 3Sum
Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.
Notice that the solution set must not contain duplicate triplets.

Example 1:
Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
Explanation:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0.
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0.
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0.
The distinct triplets are [-1,0,1] and [-1,-1,2].
Notice that the order of the output and the order of the triplets does not matter.
Example 2:

Input: nums = [0,1,1]
Output: []
Explanation: The only possible triplet does not sum up to 0.
Example 3:

Input: nums = [0,0,0]
Output: [[0,0,0]]
Explanation: The only possible triplet sums up to 0."""


def threeSum(nums):
res = []
nums.sort()
for i in range(len(nums)):
if nums[i] > 0:
break
if i > 0 and nums[i] == nums[i - 1]:
continue
left, right = i + 1, len(nums) - 1
while left < right:
if nums[left] + nums[right] + nums[i] == 0:
item = [nums[i], nums[left], nums[right]]
res.append(item) if item not in res else None
left += 1
right -= 1
elif nums[left] + nums[right] + nums[i] < 0:
left += 1
else:
right -= 1
i += 1

return res

nums.sort()
ans = []
for i in range(len(nums)):
if nums[i] > 0:
break
if i > 0 and nums[i] == nums[i - 1]:
continue
left, right = i + 1, len(nums) - 1
while left < right:
summary = nums[i] + nums[left] + nums[right]
if summary < 0:
left += 1
elif summary > 0:
right -= 1
else:
ans.append([nums[i], nums[left], nums[right]])
while left < right and nums[left] == nums[left + 1]:
left += 1
while left < right and nums[right] == nums[right - 1]:
right -= 1
left += 1
right -= 1
return ans


# print(threeSum([-1,0,1,2,-1,-4]))

"""
18. 4Sum
Given an array nums of n integers, return an array of all the unique quadruplets [nums[a], nums[b], nums[c], nums[d]] such that:

0 <= a, b, c, d < n
a, b, c, and d are distinct.
nums[a] + nums[b] + nums[c] + nums[d] == target
You may return the answer in any order.



Example 1:

Input: nums = [1,0,-1,0,-2,2], target = 0
Output: [[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
Example 2:

Input: nums = [2,2,2,2,2], target = 8
Output: [[2,2,2,2]]"""


def fourSum(nums, target):
nums.sort()
ans = []
for i in range(len(nums)):
if nums[i] > target and (nums[i] >=0 or target >= 0):
break
if i > 0 and nums[i] == nums[i - 1]:
continue
for j in range(i+1,len(nums)):
if j > i+1 and nums[j] == nums[j - 1]:
continue
left, right = j + 1, len(nums) - 1
while left < right:
summary = nums[i] + nums[j] + nums[left] + nums[right]
if summary < target:
left += 1
elif summary > target:
right -= 1
else:
ans.append([nums[i], nums[j], nums[left], nums[right]])
while left < right and nums[left] == nums[left + 1]:
left += 1
while left < right and nums[right] == nums[right - 1]:
right -= 1
left += 1
right -= 1
return ans

# print(fourSum([2,2,2,2,2],8))

"""Write a function that reverses a string. The input string is given as an array of characters s.

You must do this by modifying the input array in-place with O(1) extra memory.
Example 1:

Input: s = ["h","e","l","l","o"]
Output: ["o","l","l","e","h"]
Example 2:

Input: s = ["H","a","n","n","a","h"]
Output: ["h","a","n","n","a","H"]
Example 1:

Input: s = "abcdefg", k = 2
Output: "bacdfeg"
Example 2:

Input: s = "abcd", k = 2
Output: "bacd"
"""

def reverseString(s):
i, j = 0, len(s)-1
while i < j:
s[i], s[j] = s[j], s[i]
i += 1
j -= 1

def reverseStr(s, k):
s = list(s)
n = len(s)
for i in range(0,n,2*k):
s[i:i+k] = s[i:i+k][::-1]
return ''.join(s)

# print(reverseStr("abcdef", 2))

def replaceNum():
s = input()
s = list(s)
for i in range(len(s)):
if ord(s[i]) - ord('0') < 10:
s[i] = 'number'
print(''.join(s))
return ''.join(s)

# print(replaceNum())

"""151. Reverse Words in a String
Given an input string s, reverse the order of the words.
A word is defined as a sequence of non-space characters. The words in s will be separated by at least one space.
Return a string of the words in reverse order concatenated by a single space.
Note that s may contain leading or trailing spaces or multiple spaces between two words. The returned string should only have a single space separating the words. Do not include any extra spaces.
Example 1:

Input: s = "the sky is blue"
Output: "blue is sky the"
Example 2:

Input: s = " hello world "
Output: "world hello"
Explanation: Your reversed string should not contain leading or trailing spaces.
Example 3:

Input: s = "a good example"
Output: "example good a"
Explanation: You need to reduce multiple spaces between two words to a single space in the reversed string."""
def reverseWords(s):
# res = []
# cache = ""
# for i in s:
# if i != ' ':
# cache += i
# else:
# if cache != '':
# res.append(cache)
# cache = ''
# if cache != '':
# res.append(cache)
# return ' '.join(res[::-1])
words = s.split()
return ' '.join(words[::-1])
# print(reverseWords('the sky is blue'))

def rightReverse():
k = int(input())
s = input()
print(s[-k:] + s[:-k])

# rightReverse()

def strStr(haystack, needle):
# if not needle:
# return 0
# n = len(needle)
# for i in range(len(haystack) - n+1):
# if haystack[i:i+n] == needle:
# return i
# return -1
def getNext(next, s) -> None:
j = -1
next[0] = j
for i in range(1, len(s)):
while j >= 0 and s[i] != s[j + 1]:
j = next[j]
if s[i] == s[j + 1]:
j += 1
next[i] = j

if not needle:
return 0
next = [0] * len(needle)
getNext(next, needle)
j = -1
for i in range(len(haystack)):
while j >= 0 and haystack[i] != needle[j + 1]:
j = next[j]
if haystack[i] == needle[j + 1]:
j += 1
if j == len(needle) - 1:
return i - len(needle) + 1
return -1
# print(strStr("sadsadbutsad",'sadsadsad'))
def getNext(next, s):
pass

"""Given a string s, find the length of the longest
substring
without repeating characters.

Example 1:

Input: s = "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.
Example 2:

Input: s = "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.
Example 3:

Input: s = "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3.
Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.
"""
def lengthOfLongestSubstring(s):
if not s:
return 0
i,j = 0,0
count = 1
from collections import defaultdict
hashmap = defaultdict(int)
while j < len(s):
hashmap[s[j]] += 1
if hashmap[s[j]]>1:
count = max(count, j-i)
while hashmap[s[j]] > 1 and i<j:
hashmap[s[i]] -= 1
i += 1
j += 1
count = max(count, j - i)
return count
# print(lengthOfLongestSubstring('au'))

"""76. Minimum Window Substring
Given two strings s and t of lengths m and n respectively, return the minimum window
substring of s such that every character in t (including duplicates) is included in the window. If there is no such substring, return the empty string "".

The testcases will be generated such that the answer is unique.
Example 1:

Input: s = "ADOBECODEBANC", t = "ABC"
Output: "BANC"
Explanation: The minimum window substring "BANC" includes 'A', 'B', and 'C' from string t.
Example 2:

Input: s = "a", t = "a"
Output: "a"
Explanation: The entire string s is the minimum window.
Example 3:

Input: s = "a", t = "aa"
Output: ""
Explanation: Both 'a's from t must be included in the window.
Since the largest window of s only has one 'a', return empty string."""

def minWindow(s, t):
if len(s) < len(t):
return ""
from collections import defaultdict
hashmap = defaultdict(int)
for item in t:
hashmap[item] -= 1
tmp_set = set(list(t))
i, j = 0, 0
count = len(s)
res = ""
while j < len(s):
if s[j] in hashmap:
hashmap[s[j]] += 1
if hashmap[s[j]] == 0:
tmp_set.remove(s[j])
if not tmp_set:
while i < j:
if s[i] not in t:
i += 1
continue
if hashmap[s[i]] == 0:
break
hashmap[s[i]] -=1
i += 1
if j-i < count:
res = s[i:j+1]
count = j-i

tmp_set.add(s[i])
hashmap[s[i]] -= 1
i += 1
j += 1
return res

# print(minWindow(s = "ADOBECODEBANC", t = "ABC"))

class ListNode(object):
def __init__(self, val=0, next=None):
self.val = val
self.next = next

def removeElements(head, val):
"""
:type head: ListNode
:type val: int
:rtype: ListNode
"""
pre = ListNode(next=head)
cur = pre
while cur.next:
if cur.next.val == val:
cur.next = cur.next.next
continue
cur = cur.next
return pre.next

class MyLinkedList(object):

def __init__(self):
self.pre = ListNode()
self.size = 0

def get(self, index):
"""
:type index: int
:rtype: int
"""
if index < 0 or index >= self.size:
return -1
cur = self.pre.next
for i in range(index):
cur = cur.next
return cur.val

def addAtHead(self, val):
"""
:type val: int
:rtype: None
"""
new_node = ListNode(val=val, next=self.pre.next)
self.pre.next = new_node
self.size += 1

def addAtTail(self, val):
"""
:type val: int
:rtype: None
"""
cur = self.pre
while cur.next:
cur = cur.next
cur.next = ListNode(val=val)
self.size += 1

def addAtIndex(self, index, val):
"""
:type index: int
:type val: int
:rtype: None
"""
if index < 0 or index > self.size:
return
cur = self.pre
for i in range(index):
cur = cur.next
cur.next = ListNode(val=val, next=cur.next)
self.size += 1

def deleteAtIndex(self, index):
"""
:type index: int
:rtype: None
"""
if index < 0 or index > self.size:
return
cur = self.pre
for i in range(index):
cur = cur.next
if not cur.next:
return
cur.next = cur.next.next
self.size -= 1

# Your MyLinkedList object will be instantiated and called as such:
# 1,2,3,4,5
def reverseList(head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head:
return
pre = None
cur = head
while cur.next:
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
cur.next = pre
return cur

def swapPairs(head):
"""
:type head: ListNode
:rtype: ListNode
1 2 3 4 -> 2 1 4 3
"""
pre = ListNode(next=head)
cur = pre
while cur.next and cur.next.next:
node1 = cur.next
node2 = cur.next.next
node1.next = node2.next
node2.next = node1
cur.next = node2
cur = node1
return pre.next

# swapPairs(pre)

def removeNthFromEnd(head, n):
# set pre = cur - n, while cur = end,pre = target;
# 1 2 3 4 5, 2 1 2 3 5
pre = ListNode(next=head)
dhead = pre
cur = head
for i in range(n):
cur = cur.next
while cur:
pre = pre.next
cur = cur.next
pre.next = pre.next.next
return dhead.next



pre = ListNode(next=head)
pre_head = pre
cur = head
for i in range(n-1):
cur = cur.next
while cur.next:
pre = pre.next
cur = cur.next
pre.next = pre.next.next
return pre_head

def getIntersectionNode(headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
size1, size2 = 0,0
cur = headA
while cur:
size1 +=1
cur=cur.next
cur = headB
while cur:
size2 +=1
cur=cur.next
if size1>size2:
long_li = headA
short_li = headB
else:
long_li = headB
short_li = headA
for i in range(abs(size1-size2)):
long_li = long_li.next
while long_li and short_li:
if long_li == short_li:
return long_li
long_li = long_li.next
short_li=short_li.next
return None





size1, size2 = 0, 0
cur = headA
while cur:
size1 += 1
cur = cur.next
cur = headB
while cur:
size2 += 1
cur = cur.next
if size1 > size2:
for i in range(size1-size2):
headA = headA.next
elif size1 < size2:
for i in range(size2-size1):
headB = headB.next
while headA and headB:
if headA == headB:
return headA
headA = headA.next
headB = headB.next
return None

def detectCycle(head):
"""
:type head: ListNode
:rtype: ListNode
"""
# 3 2 0 -4 , 1 pos = 1,x = 3,len = 4/ len-pos=x? 2x = len+x-pos
pre = ListNode(next=head)
slow = pre
fast = pre
while fast and fast.next:
if fast == slow:
while pre != fast:
pre = pre.next
fast = fast.next
return pre
fast = fast.next.next
slow = slow.next
return -1




pre = ListNode(next=head)
slow, fast = ListNode(next=head), ListNode(next=head)
count = -1
while fast and fast.next:
if fast == slow:
while fast != pre:
fast = fast.next
pre = pre.next
count += 1
return pre
fast = fast.next.next
slow = slow.next
return None


# vals = [1,2,3,4]
# pre = None
# for item in vals[::-1]:
# new_node = ListNode(val=item, next=pre)
# pre = new_node

#-------- 双指针 ------------------------
def removeElement(nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
[2,3,4,1,2,4] 2
"""
slow, fast = 0, 0
k = 0
while fast < len(nums):
if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1
fast += 1
return nums

# print(removeElement([2,3,4,1,2,4],2))

def reverseArray(nums):
"""
:type nums: List[int]
:type val: int
:rtype: int
[2,3,4,1,2,4] 2
"""
l, r = 0, len(nums)-1
while l < r:
nums[l], nums[r] = nums[r], nums[l]
l += 1
r -= 1
return nums

# print(reverseArray([1,2,3,4,5]))

def replaceNumber(s):
s = input()
n = len(s)
count = 0
for i in s:
if 0< ord(i) - ord('0') < 10:
count += 1
s.resize(n+5*count)

def reverseWords3(s):
"""
:type s: str
:rtype: str
"""
# return ' '.join(s.split()[::-1])
s = list(s)
slow, fast = 0, 0
while fast < len(s):
if s[fast] != ' ':
if slow != 0:
s[slow] = ' '
slow += 1
while fast < len(s) and s[fast] != ' ':
s[slow] = s[fast]
fast += 1
slow += 1
fast += 1
new_len = slow
s[:slow] = s[:slow][::-1]
i, j = 0,0
for j in range(slow):
if s[j] == ' ':
s[i:j] = s[i:j][::-1]
i = j + 1
s[i:slow] = s[i:slow][::-1]
return ''.join(s[:slow])

# print(reverseWords3('the sky is blue'))

def sum3(nums):
# [-1, 0, 1, -1, -4,2, 2, ]
nums.sort()
res = []
start = 0
while start < len(nums):
if nums[start] > 0:
break
if start > 0 and nums[start - 1] == nums[start]:
start += 1
continue
i, j = start+1, len(nums) - 1
while i<j:
if nums[start] + nums[i] + nums[j]<0:
i += 1
elif nums[start] + nums[i] + nums[j]>0:
j -= 1
else:
res.append([nums[start],nums[i],nums[j]])
while i<j and nums[j-1] == nums[j]:
j -= 1
while i<j and nums[i+1] == nums[i]:
i += 1
i += 1
j -= 1
start += 1
return res

# print(sum3([-1, 2, 1, -2]))

def nSum(nums, n, start, target):
res = []
nums.sort()
lens = len(nums)
if n == 2:
left, right = start, lens - 1
while left < right:
num_left, num_right = nums[left], nums[right]
sums = nums[left] + nums[right]
if sums < target:
while left < right and num_left == nums[left]:
left += 1
elif sums > target:
while left < right and nums[right] == num_right:
right -= 1
else:
res.append([nums[left], nums[right]])
while left < right and nums[left] == num_left:
left += 1
while left < right and nums[right] == num_right:
right -= 1
else:
for i in range(start,lens):
if i > start and nums[i] == nums[i-1]:
continue
sub_res = nSum(nums, n-1, i+1, target-nums[i])
for item in sub_res:
item.append(nums[i])
res.append(item)
return res

# print(nSum([-2,0,1,1,2],3,0,0))

class MyQueue(object):

def __init__(self):
self.stack_in = []
self.stack_out = []

def push(self, x):
"""
:type x: int
:rtype: None
"""
self.stack_in.append(x)

def pop(self):
"""
:rtype: int
"""
if self.stack_out:
res = self.stack_out.pop()
return res
if self.stack_in:
while self.stack_in:
self.stack_out.append(self.stack_in.pop())
res = self.stack_out.pop()
return res
else:
return None

def peek(self):
"""
:rtype: int
"""
if self.stack_in:
while self.stack_in:
self.stack_out.append(self.stack_in.pop())
res = self.stack_out[-1]
while self.stack_out:
self.stack_in.append(self.stack_out.pop())
return res
else:
return None

def empty(self):
"""
:rtype: bool
"""
return True if not self.stack_in else False

# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()

class MyStack(object):

def __init__(self):
self.queue = []

def push(self, x):
"""
:type x: int
:rtype: None
"""
self.queue.append(x)

def pop(self):
"""
:rtype: int
"""
if self.empty():
return None

queue2 = []
for i in range(len(self.queue)-1):
queue2.append(self.queue.pop(0))
res = self.queue.pop(0)
self.queue = queue2
return res

def top(self):
"""
:rtype: int
"""
res = self.pop()
self.queue.append(res)
return res

def empty(self):
"""
:rtype: bool
"""
return False if self.queue else True


# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()

def postorderTraversal(root):
if not root:
return []
res = []
stack = [root]
while stack:
node = stack.pop()
if node:
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
stack.append(node.val)
stack.append(None)
else:
val = stack.pop()
res.append(val)
return res

def isValid(s):
"""
:type s: str
:rtype: bool
"""
stack = []
for item in s:
if not stack:
stack.append(item)
continue
if (item == '}' and stack[-1] == '{') or (item == ')' and stack[-1] == '(') or (item == ']' and stack[-1] == '['):
stack.pop()
else:
stack.append(item)
return True if not stack else False

def removeDuplicates(s):
"""
:type s: str
:rtype: str
"""
stack = []
for item in s:
if not stack:
stack.append(item)
continue
if item == stack[-1]:
stack.pop()
else:
stack.append(item)
return stack

def evalRPN(tokens):
"""
:type tokens: List[str]
:rtype: int
"""
stack_cal = []
stack_num = []
for item in tokens:
if item in ['+', '-', '*', '/']:
if len(stack_num) < 2:
return
num2 = stack_num.pop()
num1 = stack_num.pop()
if item == '+':
res = int(num1) + int(num2)
elif item == '-':
res = int(num1) - int(num2)
elif item == '*':
res = int(num1) * int(num2)
elif item == '/':
res = int(num1) / int(num2)
else:
return None
stack_num.append(res)
else:
stack_num.append(item)
return int(stack_num[0])

# print(evalRPN(["10","6","9","3","+","-11","*","/","*","17","+","5","+"]))

def maxSlidingWindow(nums, k):
import collections
res = []
queue = collections.deque()
for i, num in enumerate(nums):
if queue and queue[0] == i - k:
queue.popleft()
print(queue)
while queue and nums[queue[-1]] < num:
queue.pop()
print(queue)
queue.append(i)
print(queue)
if i >= k - 1:
res.append(nums[queue[0]])
return res

# print(maxSlidingWindow([1,3,-1,-3,5,3,6,7], k = 3))

def deleteN(nums,n,m):
lens = len(nums)
if m >= lens:
return sum(nums)
deleted_indexs = []
index = 0
for _ in range(lens-m):
jump_count = 0
while jump_count < n+1:
target = (index +1) % lens
if target not in deleted_indexs:
jump_count += 1
index = target
deleted_indexs.append(index)
res = 0
for i in range(lens):
if i not in deleted_indexs:
res += nums[i]
return res

# print(deleteN([1, 2, 3, 4, 5, 6, 7, 8, 9, 10],2,5))


"""70. 爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
示例 1:
输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
示例 2:
输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶"""

def climbStairs(n):
dp = [0]*(n+1)
dp[0],dp[1] = 1,1
for i in range(2,n+1):
dp[i] = dp[i-1]+dp[i-2]
return dp[-1]

# print(climbStairs(3))

"""88. 合并两个有序数组
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。
合并结果是 [1] 。
示例 3:
输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。"""
def merge(nums1,m,nums2,n):
if m ==0:
return nums2
if n == 0:
return nums1
i, j = m-1, n-1
target = m+n-1
while i >=0 and j >=0:
if nums1[i]> nums2[j]:
nums1[target] = nums1[i]
i -= 1
else:
nums1[target] = nums2[j]
j -= 1
target -= 1
while i >= 0:
nums1[target] = nums1[i]
i -= 1
target -= 1
while j >= 0:
nums1[target] = nums2[j]
j -= 1
target -= 1
return nums1

# print(merge(nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3))

def maximumProduct(nums):
"""
628.
:type nums: List[int]
:rtype: int
"""
nums.sort()
if nums[-1] <= 0:
return nums[-1]*nums[-2]*nums[-3]
else:
return max(nums[0]*nums[1], nums[-2]*nums[-3])*nums[-1]

# print(maximumProduct([1,2,3,4]))

def levelOrder(root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
from collections import deque
if not root:
return []
dq = deque([root])
res = []
while dq:
size = len(dq)
tmp_res = []
for i in range(size):
node = dq.popleft()
tmp_res.append(node.val)
if node.left:
dq.append(node.left)
if node.right:
dq.append(node.right)
res.append(tmp_res)
return res
"""
if not root:
return []
queue = collections.deque([root])
result = []
while queue:
level = []
for _ in range(len(queue)):
cur = queue.popleft()
level.append(cur.val)
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
result.append(level)
return result
"""

"""107. 给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)"""

def levelOrderBottom(root):

from collections import deque
if not root:
return []
dq = deque([root])
res = []
while dq:
size = len(dq)
tmp_res = []
for i in range(size):
node = dq.popleft()
tmp_res.append(node.val)
if node.left:
dq.append(node.left)
if node.right:
dq.append(node.right)
res.append(tmp_res)
return res[::-1]

"""199. 二叉树的右视图
给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。"""

def rightSideView(root):
from collections import deque
if not root:
return []
dq = deque([root])
res = []
while dq:
size = len(dq)
tmp_res = []
for i in range(size):
node = dq.popleft()
tmp_res.append(node.val)
if node.left:
dq.append(node.left)
if node.right:
dq.append(node.right)
res.append(tmp_res)
return [item[-1] for item in res]

"""637. 二叉树的层平均值
给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。"""
def averageOfLevels(root):
from collections import deque
if not root:
return []
dq = deque([root])
res = []
while dq:
size = len(dq)
tmp_res = []
for i in range(size):
node = dq.popleft()
tmp_res.append(node.val)
if node.left:
dq.append(node.left)
if node.right:
dq.append(node.right)
res.append(tmp_res)
return [sum(item)/len(item) for item in res]


"""
# Definition for a Node.
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""

def levelOrderN(root):
from collections import deque
if not root:
return []
dq = deque([root])
res = []
while dq:
size = len(dq)
tmp_res = []
for i in range(size):
node = dq.popleft()
tmp_res.append(node.val)
for item in node.children:
if item:
dq.append(item)
res.append(tmp_res)
return res

def largestValues(root):
from collections import deque
if not root:
return []
dq = deque([root])
res = []
while dq:
size = len(dq)
tmp_res = float('-inf')
for i in range(size):
node = dq.popleft()
tmp_res = max(tmp_res, node.val)
if node.left:
dq.append(node.left)
if node.right:
dq.append(node.right)
res.append(tmp_res)
return res

"""116. 填充每个节点的下一个右侧节点指针"""
def connect(root):
from collections import deque
if not root:
return root
dq = deque([root])
res = []
while dq:
size = len(dq)
# tmp_res = float('-inf')
for i in range(size):
node = dq.popleft()
# res.append(node.val)
if node.left:
dq.append(node.left)
if node.right:
dq.append(node.right)
node.next = dq[0]
return root

def maxDepth(root):
from collections import deque
if not root:
return 0
dq = deque([root])
res = 0
while dq:
size = len(dq)
# tmp_res = float('-inf')
for i in range(size):
node = dq.popleft()
# res.append(node.val)
if node.left:
dq.append(node.left)
if node.right:
dq.append(node.right)
res += 1
return res

def maxDepthN(root):
if not root:
return 0
depth = 0
dq = collections.deque([root])
while dq:
size = len(dq)
for i in range(size):
node = dq.popleft()
for item in node.children:
dq.append(item)
depth += 1
return depth

def minDepth(root):
if not root:
return 0
import collections
dq = collections.deque([root])
res = 0
while dq:
size = len(dq)
res += 1
for i in range(size):
node = dq.popleft()
if not node.left and not node.right:
return res
if node.left:
dq.append(node.left)
if node.right:
dq.append(node.right)
return res

"""297. 二叉树的序列化与反序列化
序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。
请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
提示: 输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。"""


# Definition for a binary tree node.
class TreeNode(object):
def __init__(self, x):
self.val = x
self.left = None
self.right = None

class Codec:

def serialize(self, root):
"""Encodes a tree to a single string.

:type root: TreeNode
:rtype: str
"""
import json
from collections import deque
if not root:
return json.dumps([])
dq = deque([root])
res = []
while dq:
node = dq.popleft()
if not node:
res.append(None)
continue
res.append(node.val)
dq.append(node.left)
dq.append(node.right)
return json.dumps(res)


def deserialize(self, data):
"""Decodes your encoded data to tree.

:type data: str
:rtype: TreeNode
"""
import json, collections
data = json.loads(data)
if not data:
return None
root = TreeNode(data[0])
# lastlevel = [root]
# next_level = []
index = 1
queue = collections.deque([root])
while queue:
node = queue.popleft()
# if not node:
# continue
if data[index] != None:
node.left = TreeNode(data[index])
queue.append(node.left)
index += 1
if data[index] != None:
node.right = TreeNode(data[index])
queue.append(node.right)
index += 1
if index == len(data):
break
return root


class Codec_fail:

def serialize(self, root):
"""Encodes a tree to a single string.
:type root: TreeNode
:rtype: str
"""
import json
from collections import deque
if not root:
return json.dumps([])
dq = deque([root])
res = []
while dq:
tmp_res = []
size = len(dq)
for i in range(size):
node = dq.popleft()
if not node:
tmp_res.append('-')
dq.append(None)
dq.append(None)
continue
tmp_res.append(node.val)
dq.append(node.left)
dq.append(node.right)
if set(tmp_res) == {'-'}:
break
res.append(tmp_res)
return json.dumps(res)


def deserialize(self, data):
"""Decodes your encoded data to tree.

:type data: str
:rtype: TreeNode
"""
import json
data = json.loads(data)
if not data:
return None
root = TreeNode(data[0][0])
next_level = [root]


return root
# Your Codec object will be instantiated and called as such:
# root = TreeNode(1)
# root.left = None
# root.right = TreeNode(2)
# deser = Codec()
# root = deser.deserialize("[1,2,3,null,null,4,5,6,7]")
# ser = Codec()
# deser = Codec()
# ans = deser.deserialize(ser.serialize(root))

def invertTree(root):
if not root:
return root
from collections import deque
dq = deque([root])
while dq:
node = dq.popleft()
node.left, node.right = node.right, node.left
if node.left:
dq.append(node.left)
if node.right:
dq.append(node.right)
return root

def isSymmetric(root):

def compare(left,right):
if left and right:
if left.val != right.val:
return False
else:
ouside = compare(left.left, right.right)
inside = compare(left.right, right.left)
isSame = ouside and inside
return isSame
elif left or right:
return False
return True
if not root:
return True
return compare(root.left,root.right)
import collections
# def isSymmetric(root):
# if not root:
# return True
# res = []
# dq = collections.deque([root])
# while dq:
# size = len(dq)
# tmp_val = []
# for i in range(size):
# node = dq.popleft()
# if node:
# tmp_val.append(node.val)
# dq.append(node.left)
# dq.append(node.right)
# else:
# tmp_val.append(None)
# print(tmp_val)
# if tmp_val != tmp_val[::-1]:
# return False
# return True

# root = Codec().deserialize("[1,2,2,3,4,4,3]")
# print(isSymmetric(root))

def countNodes(root):
# if not root:
# return 0
# return 1 + countNodes(root.left) + countNodes(root.right)
# 写法2: 根据完全二叉树的定义,向下寻找完美二叉树;(完美二叉树left.left和right.right同时到底;)
if not root:
return 0
left, right = root.left, root.right
count = 1
while left and right:
left = left.left
right = right.right
count += 1
if not left and not right:
return 2**count - 1
return 1 + countNodes(root.left) + countNodes(root.right)

def isBalanced(root):
def getHeight(node):
if not node:
return 0
left_height, right_height = getHeight(node.left), getHeight(node.right)
if left_height == -1 or right_height == -1:
return -1
if -1 <= left_height - right_height <= 1:
return 1 + max(left_height, right_height)
return -1
return getHeight(root) != -1

# print(isBalanced(root))

def binaryTreePaths(root):
if not root:
return []
# left_paths = binaryTreePaths(root.left)
# right_paths = binaryTreePaths(root.right)
# if not left_paths and not right_paths:
# return [str(root.val)]
# result = [f'{root.val}->{item}' for item in left_paths+right_paths]
# return result
path_stack = [f'{root.val}']
node_stack = [root]
result = []
while node_stack:
node = node_stack.pop()
path = path_stack.pop()

if node.left:
node_stack.append(node.left)
path_stack.append(f'{path}->{node.left.val}')
if node.right:
node_stack.append(node.right)
path_stack.append(f'{path}->{node.right.val}')
if not node.left and not node.right:
result.append(path)
return result


def isSymmetric2(root):
# def compare(left, right):
# if not left and not right:
# return True
# if not left or not right:
# return False
# if left.val != right.val:
# return False
# return compare(left.left, right.right) and compare(left.right, right.left)
# return compare(root.left,root.right)
queue = collections.deque([root.left, root.right])
while queue:
left = queue.popleft()
right = queue.popleft()
if not left and not right:
continue
if not left or not right:
return False
if left.val != right.val:
return False
queue.append(left.left)
queue.append(right.right)
queue.append(left.right)
queue.append(right.left)
return True

def isSameTree(p, q):
if not p and not q:
return True
if not p or not q:
return False
if p.val != q.val:
return False
return isSameTree(p.left, q.left) and isSameTree(p.right, q.right)

def isSubtree(root, subRoot):
def isSameTree(p, q):
if not p and not q:
return True
if not p or not q:
return False
if p.val != q.val:
return False
return isSameTree(p.left, q.left) and isSameTree(p.right, q.right)
queue = collections.deque([root])
while queue:
node = queue.popleft()
if node.val == subRoot.val and isSameTree(node,subRoot):
return True
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return False

def sumOfLeftLeaves(root):
if not root:
return 0
val = 0
if root.left:
if not root.left.left and not root.left.right:
val = root.left.val
return val + sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right)


root = '[1,2,2,3,4,4,3]'
root = Codec().deserialize(root)
# print(sumOfLeftLeaves(root))



def difference(nums, queries):
"""
数组差分问题
- **问题描述**:给定初始数组 `nums` 和一系列查询,每个查询包含起始位置、结束位置和差分值,求最终数组。
- **解决方案**:使用差分数组技巧根据查询对原数组进行差分操作,得到最终数组。
"""

prefix_diff = [0] * len(nums)
for q in queries:
start, end, diff = q
prefix_diff[start] += diff
if end + 1 < len(nums):
prefix_diff[end + 1] -= diff
for i in range(1, len(nums)):
prefix_diff[i] += prefix_diff[i - 1]
return prefix_diff

# print(difference([1,2,3,4,5,6,7],[[1,2,10],[2,3,20],[2,5,25]]))

from collections import OrderedDict
class MyCalendarThree:

def __init__(self):
self.hashmap = OrderedDict()
self.k = 0

def book(self, startTime: int, endTime: int):
self.hashmap[startTime] = self.hashmap.get(startTime, 0) + 1
self.hashmap[endTime] = self.hashmap.get(endTime, 0) - 1
self.hashmap = OrderedDict(sorted(self.hashmap.items()))

active = 0
max_k = 0
for time, delta in self.hashmap.items():
active += delta
max_k = max(max_k, active)
self.k = max(self.k, max_k)
return self.k

# prefix_list = [[10,20],[50,60],[10,40],[5,15],[5,10],[25,55]]
# ca = MyCalendarThree()
# for item in prefix_list:
# print(ca.book(item[0], item[1]))
# print(ca.hashmap)

def maxSlidingWindow2(nums, k):
n = len(nums)
res = []
queue = collections.deque()
for i in range(len(nums)):
if queue and queue[0] == i-k:
queue.popleft()

while queue and nums[queue[-1]] < nums[i]:
queue.pop()
queue.append(i)
if i >= k-1:
res.append(nums[queue[0]])
return res
# print(maxSlidingWindow2([7,2,4],2))

def minWindow2(s,t):
hashmap = collections.defaultdict(int)
for item in t:
hashmap[item] += 1
count = len(t)
i, j = 0,0
min_str = [0, len(s)+2]
while j < len(s):
if s[j] in hashmap:
if hashmap[s[j]] > 0:
count -= 1
hashmap[s[j]] -= 1
if count == 0:
while i<j:
if s[i] not in hashmap:
i+=1
elif hashmap[s[i]] < 0:
hashmap[s[i]] +=1
i += 1
else:
break
if j - i < min_str[1] - min_str[0]:
min_str = [i,j]
j += 1
i,j = min_str[0], min_str[1]
if min_str[1] < len(s)+2:
return s[i:j+1]
else:
return ""

# print(minWindow2(s = "ab", t = "a"))


def maxSubArray(nums):
n = len(nums)
if not n:
return 0
dp = [0]*n
dp[0] = nums[0]
for i in range(1,n):
if dp[i-1] <=0:
dp[i] = nums[i]
else:
dp[i] = dp[i-1] + nums[i]
return max(dp)

# print(maxSubArray([-2,1,-3,4,-1,2,1,-5,4]))

def minCostClimbingStairs(cost):
n = len(cost)
dp = [0] * (n+1)
# dp[0], dp[1] =
for i in range(2,n+1):
dp[i] = min(dp[i-2]+cost[i-2], dp[i-1] + cost[i-1])
return dp[-1]

# print(minCostClimbingStairs([1,100,1,1,1,100,1,1,100,1]))

def uniquePaths(m, n):
dp = [[1 for _ in range(n)]for _ in range(m)]
for i in range(1,m):
for j in range(1,n):
dp[i][j] = dp[i-1][j] + dp[i][j-1]
print(dp)
return dp[-1][-1]

# print(uniquePaths(3,7))

def uniquePathsWithObstacles(obstacleGrid):
if not obstacleGrid or not obstacleGrid[0]:
return 0
m = len(obstacleGrid)
n = len(obstacleGrid[0])
dp = [[0 for _ in range(n)] for _ in range(m)]
for j in range(n):
if obstacleGrid[0][j] == 1:
break
dp[0][j] = 1
for i in range(m):
if obstacleGrid[i][0] == 1:
break
dp[i][0] = 1
for i in range(1,m):
for j in range(1,n):
if obstacleGrid[i][j] == 1:
dp[i][j] = 0
else:
dp[i][j] = dp[i-1][j] + dp[i][j-1]
# print(dp)
return dp[-1][-1]

# print(uniquePathsWithObstacles([[0,0,0],[0,1,0],[0,1,0],[0,0,0],[0,0,0]]))


def integerBreak(n):
dp = [0] * (n+1)
# dp[0] = 0
# dp[1] = 1
dp[2] = 1
for i in range(3,n+1):
for j in range(1,i//2+1):
dp[i] = max(dp[i], max(dp[i-j]*j, (i-j)*j))
# print(dp)
return dp[-1]

# print(integerBreak(10))

def numTrees(n):
dp = [0] * (n+1)
dp[0] = 1
# dp[1] = 1
# dp[2] = 2
# dp[3] = 5
for i in range(1, n+1):
for j in range(1,i+1):
dp[i] += dp[j-1]*dp[i-j]
return dp[-1]
# 12+12+5+5+4
# print(numTrees(5))

def package_problem_01(m,n,weight, value_list):
"""
0 0 2 2 2 2
0 0 3 3 5 5
0 0 3 3 5 6
"""
dp = [0 for _ in range(n+1)]
for i in range(m):
for j in range(n, weight[i]-1, -1):
dp[j] = max(dp[j], dp[j-weight[i]] + value_list[i])
print(dp)
return dp[-1]



# print(package_problem_01(6,5,[2,2,3,1,5,2],[2,3,1,5,4,3]))

def canPartition(nums):
sums = sum(nums)
if sums %2 == 1:
return False
target = sums//2
dp = [0] * (target+1)
for i in range(len(nums)):
for j in range(target,nums[i]-1,-1):
dp[j] = max(dp[j], dp[j-nums[i]] + nums[i])
print(dp)
if dp[target] == target:
return True
return False

# print(canPartition([1,5,5,11]))

def lastStoneWeightII(stones):
nums = stones
sums = sum(nums)
target = sums//2
dp = [0] * (target+1)
for i in range(len(nums)):
for j in range(target,nums[i]-1,-1):
dp[j] = max(dp[j], dp[j-nums[i]] + nums[i])
print(dp)

return sums - dp[target] - dp[target]

# print(lastStoneWeightII([2,7,4,1,8,1]))

def findTargetSumWays(nums, target):
sums = sum(nums)
if (target + sums) % 2 == 1:
return 0
if abs(target) > sums:
return 0
x = (target + sums) // 2
dp = [0] * (x + 1)
dp[0] = 1
for item in nums:
for j in range(x, item-1, -1):
dp[j] = dp[j] + dp[j-item]
# print(dp)
return dp[x]

# print(findTargetSumWays([1,1,1,1,1],3))

def findMaxForm(strs, m, n):
dp = [[0 for _ in range(n+1)] for _ in range(m+1)]
# dp[0][0] = 1
for item in strs:
count_0 = item.count('0')
count_1 = len(item) - count_0
for i in range(m, count_0-1, -1):
for j in range(n, count_1-1, -1):
dp[i][j] = max(dp[i][j], dp[i-count_0][j-count_1]+1)
# print(dp)
# print('---\n')
return dp[m][n]

# print(findMaxForm(["10", "0001", "111001", "1", "0"], m = 5, n = 3))

def lengthOfLIS(nums):
# dp = [1] * len(nums) # 含义:dp[i] 表示到nums[i] 的最长递增子序列长度
# # 递推公式: dp[j-1] + 1 or dp[i]
# for i in range(1, len(nums)):
# for j in range(i):
# if nums[i] > nums[j]:
# dp[i] = max(dp[i], dp[j] + 1)
#
# return max(dp)
if len(nums) <= 1:
return len(nums)

tails = [nums[0]] # 存储递增子序列的尾部元素
for num in nums[1:]:
if num > tails[-1]:
tails.append(num) # 如果当前元素大于递增子序列的最后一个元素,直接加入到子序列末尾
else:
# 使用二分查找找到当前元素在递增子序列中的位置,并替换对应位置的元素
left, right = 0, len(tails) - 1
while left < right:
mid = (left + right) // 2
if tails[mid] < num:
left = mid + 1
else:
right = mid
tails[left] = num
print(tails)

return len(tails) # 返回递增子序列的长度

# print(lengthOfLIS([1,3,6,7,9,4,10,5,6]))

def nSum2(nums,n,start,target):
nums.sort()
if n == 2:
res = []
left, right = start, len(nums) - 1
while left < right:
left_item, right_item = nums[left], nums[right]
sums = left_item + right_item
if sums < target:
left += 1
elif sums > target:
right -= 1
else:
res.append([left_item, right_item])
while left < right and nums[left] == left_item:
left += 1
while left < right and nums[right] == right_item:
right -= 1
return res
else:
res = []
for i in range(len(nums)-2):
if i >=1 and nums[i] == nums[i-1]:
continue
tmp_res = nSum2(nums,n-1,i+1,target-nums[i])
for item in tmp_res:
item.append(nums[i])
res += tmp_res
return res

# print(nSum2([-2,0,1,1,2],3,0,0))