Leetcode(中文)笔记
最近在刷leetcode,顺便整理一下笔记,用于自我梳理。目前第一遍仅使用Python。
持续更新中。。。
双指针
26.删除排序数组中的重复项
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
暴力求解:
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
i = 0
while i < len(nums)-1:
if nums[i] == nums[i+1]:
nums.pop(i+1)
else:
i += 1
return len(nums)
双指针法:
第一个指针:遍历数组,每遇到nums[j] != nums[i],就说明遇到了新的不同数字,记录之;
第二个指针:每遇到新的不同数字时,执行i += 1, i指针有两个作用:记录数组中不同数字的数量;作为修改数组元素的索引index。
最终,返回i+1即可。
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
i = 0
for j in range(i+1, len(nums)):
if nums[j] != nums[i]:
i += 1
nums[i] = nums[j]
return i+1
27. 移除元素
给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
双指针法1:
定义指针j=0
从第一个元素开始遍历,对于num: 判断条件num != val,如果满足,将这个值填入nums[j],并令j += 1,指向下一位置
最后一次j加了1,所以返回长度时无需加1.
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
j = 0
for num in nums:
if num != val:
nums[j] = num
j += 1
return j
双指针法2:
定义左指针l=0和右指针r=n *特别注意:*这里右指针r=n,这样可以将很多特例如:[1],1包含在内
执行循环l<r
如果nums[l]==val,则交换nums[l]和nums[r],表示,如果左端值等于val,则和右端交换。并令右端r=r+1,表示这个位置已经放了val,和下一位置交换
若不满足条件,则令左端指向下一元素l=l+1
返回l,这里因为右指针初始化为n,可结合例子,发现i即为最终长度
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
l = 0
r = len(nums)
while (r>l):
if nums[l]==val:
nums[l], nums[r-1] = nums[r-1], nums[l]
r -= 1
else:
l += 1
return l
28. 实现 strStr()
实现 strStr() 函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。当 needle 是空字符串时我们应当返回 0 。
双指针法:
两个指针i和j分别指向haystack和needle串。
每次迭代逐位比较,主要是指针移动的条件判断:
当两个当前字符相等时,i+1,j+1,并判断j是否越界,若越界就找到了,返回结果i-j;否则继续。
当两个当前字符不相等时,i重置到i-j的下一个位置,j重置为0。
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
if len(needle) == 0:
return 0
j = 0
i = 0
while i < len(haystack):
if haystack[i] == needle[j]:
i += 1
j += 1
else:
i = i - j + 1
j = 0
if j == len(needle):
return i - len(needle)
return -1
88. 合并两个有序数组
给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
说明:
初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
双指针法:
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
nums = []
i = 0
j = 0
while i<m and j<n:
if nums1[i] <= nums2[j]:
nums.append(nums1[i])
i += 1
else:
nums.append(nums2[j])
j += 1
if i < m:
for k in range(i, m):
nums.append(nums1[k])
elif j < n:
for k in range(j, n):
nums.append(nums2[k])
nums1[:m+n] = nums[:m+n]
反向双指针法:
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
i = m - 1
j = n - 1
k = m + n - 1
while i>=0 and j>=0:
if nums1[i] >= nums2[j]:
nums1[k] = nums1[i]
k -= 1
i -= 1
else:
nums1[k] = nums2[j]
k -= 1
j -= 1
if j >= 0:
nums1[:j+1] = nums2[:j+1]
125. 验证回文串
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
双指针法:
class Solution:
def isPalindrome(self, s: str) -> bool:
list_s = list(s)
if not list_s:
return True
i = 0
j = len(list_s) - 1
while i < j:
if ('0' <= list_s[i] <= '9' or 'a' <= list_s[i] <= 'z' or 'A' <= list_s[i] <= 'Z') and ('0' <= list_s[j] <= '9' or 'a' <= list_s[j] <= 'z' or 'A' <= list_s[j] <= 'Z'):
if list_s[i].lower() == list_s[j].lower():
i += 1
j -= 1
else:
return False
if not ('0' <= list_s[i] <= '9' or 'a' <= list_s[i] <= 'z' or 'A' <= list_s[i] <= 'Z'):
i += 1
if not ('0' <= list_s[j] <= '9' or 'a' <= list_s[j] <= 'z' or 'A' <= list_s[j] <= 'Z'):
j -= 1
return True
141. 环形链表
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
双指针法:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: ListNode) -> bool:
i = head
j = head
while j and j.next:
i = i.next
j = j.next.next
if i == j:
return True
return False
167. 两数之和 II - 输入有序数组
给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。
函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。
说明:
返回的下标值(index1 和 index2)不是从零开始的。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
双指针法:
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
i = 0
j = len(numbers) - 1
while i<j:
if numbers[i] + numbers[j] < target:
i += 1
elif numbers[i] + numbers[j] > target:
j -= 1
else:
return [i+1,j+1]
283. 移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
双指针法:
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
i = 0
j = 1
while j<len(nums):
if nums[i] == 0:
if nums[j] != 0:
nums[i] , nums[j] = nums[j], nums[i]
i += 1
j += 1
else:
j +=1
else:
i += 1
j += 1
return nums
双指针法:
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
j = 0
for i in range(len(nums)):
if nums[i] != 0:
nums[i] , nums[j] = nums[j], nums[i]
j += 1
234. 回文链表
请判断一个链表是否为回文链表。
数组法: 时间复杂度:
使用数组将链表中的值存储起来,然后将数组截半,前半部分数组与后半部分数组的逆序进行逐项对比,判断两个数组是否相等,如果相等则是回文串。如果数组长度为基数,忽略中间的元素。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
linked_list = []
while head != None:
linked_list.append(head.val)
head = head.next
len_list = len(linked_list)
half_len = len_list // 2
if linked_list[:half_len+1] == linked_list[::-1][:half_len+1]:
return True
else:
return False
双指针+翻转法:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def isPalindrome(self, head):
"""
:type head: ListNode
:rtype: bool
"""
# 反转链表,快慢指针,找到链表的中心位置,一个指针跟在慢指针后反转链表
RHead = None
if not head or not head.next:
return True
else:
slow = head
quick = head.next
while quick and quick.next:
temp = slow
slow = slow.next
quick = quick.next.next
temp.next = RHead
RHead = temp
if quick: # 偶数
quick = slow.next
slow.next = RHead
else:
quick = slow.next
slow = RHead
while quick and slow:
if quick.val != slow.val:
return False
else:
quick = quick.next
slow = slow.next
return True
344. 反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
双指针法:
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
i = 0
j = len(s)-1
while i < j:
s[i], s[j] = s[j], s[i]
i += 1
j -= 1
345. 反转字符串中的元音字母
编写一个函数,以字符串作为输入,反转该字符串中的元音字母
双指针法:
class Solution:
def reverseVowels(self, s: str) -> str:
Univocalic = ['a','e','i','o','u','A','E','I','O','U']
s_list = list(s)
i = 0
j = len(s_list) - 1
while i<j:
if s_list[j] not in Univocalic:
j -= 1
elif s_list[i] not in Univocalic:
i += 1
else:
s_list[i], s_list[j] = s_list[j], s_list[i]
i += 1
j -= 1
return "".join(s_list)
350. 两个数组的交集 II
给定两个数组,编写一个函数来计算它们的交集。
暴力求解:
class Solution:
def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
inter_nums = []
for i in range(len(nums1)):
j = 0
while j < len(nums2):
if nums1[i] == nums2[j]:
inter_nums.append(nums1[i])
nums2.pop(j)
break
else:
j += 1
return inter_nums
排序+双指针法:
class Solution:
def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
inter_nums = []
nums1.sort()
nums2.sort()
i = 0
j = 0
while i<len(nums1) and j<len(nums2):
if nums1[i] == nums2[j]:
inter_nums.append(nums1[i])
i+=1
j+=1
elif nums1[i] < nums2[j]:
i += 1
else:
j += 1
return inter_nums
532. 数组中的K-diff数对
给定一个整数数组和一个整数 k, 你需要在数组里找到不同的 k-diff 数对。这里将 k-diff 数对定义为一个整数对 (i, j), 其中 i 和 j 都是数组中的数字,且两数之差的绝对值是 k.
排序+双指针法: 时间复杂度:
先排序,将符合的数对存到列表中,每次遇到符合条件的数对判断列表中是否已经存在了。最后统计列表长度。
class Solution:
def findPairs(self, nums: List[int], k: int) -> int:
nums.sort()
i = 0
j = 1
diff = []
while i<len(nums) and j<len(nums):
if i == j:
j +=1
elif nums[j] - nums[i] == k:
if [nums[i], nums[j]] not in diff:
diff.append([nums[i], nums[j]])
i += 1
j += 1
elif nums[j] - nums[i] > k:
i += 1
else:
j += 1
return len(diff)
排序+双指针法:
先排序,当指针j的值减去指针i的值等于k时,存下指针j的值,n+=1,i,j+=1.当指针j的值与缓存中的值相等时j+=1.
class Solution:
def findPairs(self, nums: List[int], k: int) -> int:
nums.sort()
i = 0
j = 1
n = 0
cache = 1e7+1
while i<len(nums) and j<len(nums):
if i == j:
j +=1
elif nums[j] - nums[i] == k and nums[j] != cache:
cache = nums[j]
n += 1
i += 1
j += 1
elif nums[j] - nums[i] > k:
i += 1
else:
j += 1
return n
哈希或SET法:
两个hash或set(当哈希用)存已访问的数和已发现的k-diff中的较小值
class Solution:
def findPairs(self, nums: List[int], k: int) -> int:
if k<0:
return 0
dif_nums = set()
ans = set()
for num in nums:
if num-k in dif_nums:
ans.add(num-k)
if num+k in dif_nums:
ans.add(num)
dif_nums.add(num)
return len(ans)
844. 比较含退格的字符串
给定 S 和 T 两个字符串,当它们分别被输入到空白的文本编辑器后,判断二者是否相等,并返回结果。 # 代表退格字符。
重构字符串法:
class Solution:
def backspaceCompare(self, S: str, T: str) -> bool:
list_s = []
list_t = []
i = 0
j = 0
while i<len(S):
if S[i] != '#':
list_s.append(S[i])
elif list_s:
list_s.pop()
i += 1
while j<len(T):
if T[j] != '#':
list_t.append(T[j])
elif list_t:
list_t.pop()
j +=1
if list_s == list_t:
return True
else:
return False
925. 长按键入
你的朋友正在使用键盘输入他的名字 name。偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次。
你将会检查键盘输入的字符 typed。如果它对应的可能是你的朋友的名字(其中一些字符可能被长按),那么就返回 True。
双指针法:
class Solution:
def isLongPressedName(self, name: str, typed: str) -> bool:
i = 0
j = 0
while i < len(name) and j < len(typed):
if name[i] == typed[j]:
i += 1
j += 1
elif(typed[j] == typed[j-1]):
j += 1
else:
return False
if i < len(name):
return False
else:
for k in range(j, len(typed)):
if typed[k] == typed[j-1]:
continue
else:
return False
return True
977. 有序数组的平方
给定一个按非递减顺序排序的整数数组 A,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。
双指针法:
class Solution:
def sortedSquares(self, A: List[int]) -> List[int]:
m = 0
while m < len(A):
if A[m] < 0:
m += 1
else:
break
ans = []
i = m - 1
j = m
while i>=0 and j<len(A):
if A[j] ** 2 < A[i] ** 2:
ans.append(A[j] ** 2)
j += 1
else:
ans.append(A[i] ** 2)
i -= 1
while i>=0:
ans.append(A[i] ** 2)
i -= 1
while j<len(A):
ans.append(A[j] ** 2)
j += 1
return ans
392. 判断子序列
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
双指针法:
class Solution:
def isSubsequence(self, s: str, t: str) -> bool:
a = 0
b = 0
while a < len(s) and b < len(t):
if s[a] == t[b]:
a += 1
b += 1
else:
b += 1
if a == len(s):
return True
else:
return False
1237. 找出给定方程的正整数解
给出一个函数 f(x, y) 和一个目标结果 z,请你计算方程 f(x,y) == z 所有可能的正整数 数对 x 和 y。
给定函数是严格单调的,也就是说:
f(x, y) < f(x + 1, y)
f(x, y) < f(x, y + 1)
函数接口定义如下:
interface CustomFunction {
public:
// Returns positive integer f(x, y) for any given positive integer x and y.
int f(int x, int y);
};
如果你想自定义测试,你可以输入整数 function_id 和一个目标结果 z 作为输入,其中 function_id 表示一个隐藏函数列表中的一个函数编号,题目只会告诉你列表中的 2 个函数。
你可以将满足条件的 结果数对 按任意顺序返回。
暴力循环:
"""
This is the custom function interface.
You should not implement it, or speculate about its implementation
class CustomFunction:
# Returns f(x, y) for any given positive integers x and y.
# Note that f(x, y) is increasing with respect to both x and y.
# i.e. f(x, y) < f(x + 1, y), f(x, y) < f(x, y + 1)
def f(self, x, y):
"""
class Solution:
def findSolution(self, customfunction: 'CustomFunction', z: int) -> List[List[int]]:
ans = []
for i in range(1, z+1):
for j in range(1, z+1):
if customfunction.f(i, j) == z:
ans.append([i,j])
return ans
双指针法:
"""
This is the custom function interface.
You should not implement it, or speculate about its implementation
class CustomFunction:
# Returns f(x, y) for any given positive integers x and y.
# Note that f(x, y) is increasing with respect to both x and y.
# i.e. f(x, y) < f(x + 1, y), f(x, y) < f(x, y + 1)
def f(self, x, y):
"""
class Solution:
def findSolution(self, customfunction: 'CustomFunction', z: int) -> List[List[int]]:
x = 1
y = z
f = customfunction.f
ans = []
while(x<=z and y>=1):
if f(x,y) == z:
ans.append([x,y])
x+=1
y-=1
elif f(x,y)>z:
y-=1
else:
x+=1
return ans
"""
This is the custom function interface.
You should not implement it, or speculate about its implementation
class CustomFunction:
# Returns f(x, y) for any given positive integers x and y.
# Note that f(x, y) is increasing with respect to both x and y.
# i.e. f(x, y) < f(x + 1, y), f(x, y) < f(x, y + 1)
def f(self, x, y):
"""
class Solution:
def findSolution(self, customfunction: 'CustomFunction', z: int) -> List[List[int]]:
ans = []
for x in range(1,1001):
if customfunction.f(x,1)<=z and customfunction.f(x,1000)>=z:
#bi search y
i = 1
j = 1000
while i<=j:
m = (i+j)//2
if customfunction.f(x,m)>z:
j = m-1
elif customfunction.f(x,m)<z:
i = m+1
else:
ans.append([x, m])
break
return ans
哈希表
1.两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
暴力法:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
ans = []
for i in range(len(nums)-1):
for j in range(i+1,len(nums)):
if nums[i] + nums[j] == target:
ans.append(i)
ans.append(j)
return ans
else:
continue
字典模拟Hash:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
_dict = {}
for i, m in enumerate(nums):
_dict[m] = i
for i, n in enumerate(nums):
j = _dict.get(target - n)
if j != i and j is not None:
return [i,j]
一遍字典模拟Hash:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
_dict = {}
for i, m in enumerate(nums):
if _dict.get(target - m) is not None:
return [i, _dict.get(target-m)]
_dict[m] = i
349. 两个数组的交集
给定两个数组,编写一个函数来计算它们的交集。
暴力求解法:
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
ans = []
for i in range(len(nums1)):
if nums1[i] in nums2 and nums1[i] not in ans:
ans.append(nums1[i])
return ans
转set法:
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
nums1_set = set(nums1)
return nums1_set.intersection(set(nums2))
二分查找法
35. 搜索插入位置
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
直接遍历法:
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
for i in range(len(nums)):
if nums[i] >= target:
return i
return len(nums)
二分查找法:
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
l, r = 0, len(nums)-1
while r>l:
mid = (l + r) // 2
if nums[mid] == target:
return mid
if nums[mid] < target:
l = mid + 1
else:
r = mid - 1
if nums[l] < target:
return l + 1
return l
69. x 的平方根
实现 int sqrt(int x) 函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去
二分查找法:
class Solution:
def mySqrt(self, x: int) -> int:
left = 0
right = x
while(left <= right):
mid = (left + right) // 2
if (mid*mid == x):
return mid
elif(mid*mid < x):
if((mid+1)*(mid+1)>x):
return mid
else:
left = mid + 1
else:
right = mid - 1
278. 第一个错误的版本
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
二分查找法:
# The isBadVersion API is already defined for you.
# @param version, an integer
# @return a bool
# def isBadVersion(version):
class Solution:
def firstBadVersion(self, n):
"""
:type n: int
:rtype: int
"""
left = 0
right = n
while left <= right:
mid = (left + right) // 2
if isBadVersion(mid) == False:
left = mid + 1
else:
if isBadVersion(mid - 1) == False:
return mid
else:
right = mid - 1
367. 有效的完全平方数
给定一个正整数 num,编写一个函数,如果 num 是一个完全平方数,则返回 True,否则返回 False。
说明:不要使用任何内置的库函数,如 sqrt。
二分查找法:
class Solution:
def isPerfectSquare(self, num: int) -> bool:
left = 0
right = num
while left < right:
mid = (left + right) // 2
if mid * mid < num:
left = mid + 1
elif mid * mid == num:
return True
else:
right = mid - 1
if left * left == num:
return True
else:
return False
374. 猜数字大小
我们正在玩一个猜数字游戏。 游戏规则如下:
我从 1 到 n 选择一个数字。 你需要猜我选择了哪个数字。
每次你猜错了,我会告诉你这个数字是大了还是小了。
你调用一个预先定义好的接口 guess(int num),它会返回 3 个可能的结果(-1,1 或 0):
-1 : 我的数字比较小
1 : 我的数字比较大
0 : 恭喜!你猜对了!
二分查找法:
# The guess API is already defined for you.
# @return -1 if my number is lower, 1 if my number is higher, otherwise return 0
# def guess(num: int) -> int:
class Solution:
def guessNumber(self, n: int) -> int:
left = 1
right = n
while left <= right:
mid = (left + right) // 2
if guess(mid) == -1:
right = mid - 1
elif guess(mid) == 1:
left = mid + 1
else:
return mid
441. 排列硬币
你总共有 n 枚硬币,你需要将它们摆成一个阶梯形状,第 k 行就必须正好有 k 枚硬币。
给定一个数字 n,找出可形成完整阶梯行的总行数。
n 是一个非负整数,并且在32位有符号整型的范围内。
直接遍历法:
class Solution:
def arrangeCoins(self, n: int) -> int:
sum_i = 0
for i in range(n+1):
sum_i += i
if sum_i == n or (sum_i < n and sum_i + i + 1 > n):
return i
二分查找法:
class Solution:
def arrangeCoins(self, n: int) -> int:
left = 0
right = n
while(left<=right):
mid = (left + right) // 2
sum_mid = (1+mid)*(mid) / 2
if (sum_mid < n):
sum_mid = (1+mid+1)*(mid+1) / 2
if(sum_mid > n):
return mid
else:
left = mid + 1
elif (sum_mid > n):
right = mid - 1
else:
return mid
直接求解法:
from math import sqrt, floor
class Solution:
def arrangeCoins(self, n: int) -> int:
return floor( sqrt(1/4+2*n)-1/2 )
704. 二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
二分查找法:
class Solution:
def search(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums)-1
while(left<right):
mid = (left + right) // 2
if(nums[mid]<target):
left = mid + 1
elif(nums[mid]==target):
return mid
else:
right = mid - 1
if nums[left] == target:
return left
else:
return -1
744. 寻找比目标字母大的最小字母
给定一个只包含小写字母的有序数组letters 和一个目标字母 target,寻找有序数组里面比目标字母大的最小字母。
数组里字母的顺序是循环的。举个例子,如果目标字母target = ‘z’ 并且有序数组为 letters = [‘a’, ‘b’],则答案返回 ‘a’。
二分查找法:
class Solution:
def nextGreatestLetter(self, letters: List[str], target: str) -> str:
left = 0
right = len(letters) - 1
while(left <= right):
mid = (left + right) // 2
if(ord(letters[mid]) <= ord(target)):
if(mid<len(letters)-1):
if(ord(letters[mid+1]) > ord(target)):
return letters[mid+1]
else:
left = mid + 1
else:
return letters[0]
else:
if(mid == 0):
return letters[mid]
else:
if(ord(letters[mid-1])<ord(target)):
return letters[mid]
else:
right = mid - 1
852. 山脉数组的峰顶索引
我们把符合下列属性的数组 A 称作山脉:
A.length >= 3
存在 0 < i < A.length - 1 使得A[0] < A[1] < … A[i-1] < A[i] > A[i+1] > … > A[A.length - 1]
给定一个确定为山脉的数组,返回任何满足 A[0] < A[1] < … A[i-1] < A[i] > A[i+1] > … > A[A.length - 1] 的 i 的值。
数组最大值索引:
class Solution:
def peakIndexInMountainArray(self, A: List[int]) -> int:
return A.index(max(A))
直接遍历法:
class Solution:
def peakIndexInMountainArray(self, A: List[int]) -> int:
for i in range(1, len(A)-1):
if (A[i] > A[i-1]) and (A[i] > A[i+1]):
return i
二分查找法:
class Solution:
def peakIndexInMountainArray(self, A: List[int]) -> int:
left = 0
right = len(A) - 1
while(left < right):
mid = (left + right) // 2
if A[mid] < A[mid+1]:
left = mid + 1
else:
right = mid
return left
475. 供暖器
冬季已经来临。 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。
现在,给出位于一条水平线上的房屋和供暖器的位置,找到可以覆盖所有房屋的最小加热半径。
所以,你的输入将会是房屋和供暖器的位置。你将输出供暖器的最小加热半径。
说明:
给出的房屋和供暖器的数目是非负数且不会超过 25000。
给出的房屋和供暖器的位置均是非负数且不会超过10^9。
只要房屋位于供暖器的半径内(包括在边缘上),它就可以得到供暖。
所有供暖器都遵循你的半径标准,加热的半径也一样。
二分查找法:
class Solution:
def findRadius(self, houses: List[int], heaters: List[int]) -> int:
ans = []
houses.sort()
heaters.sort()
for house in houses:
left = 0
right = len(heaters) - 1
while(left<right):
mid = (left + right)//2
if heaters[mid] < house:
left = mid + 1
else:
right = mid
if heaters[left] == house:
ans.append(0)
elif heaters[left] < house:
ans.append(house - heaters[left])
elif left != 0:
ans.append(min((house - heaters[left-1]),(heaters[left] - house)))
else:
ans.append(heaters[left] - house)
return max(ans)
来源:CSDN
作者:CV小菜鸟
链接:https://blog.csdn.net/weixin_43273742/article/details/104112784