不积跬步,无以致千里;不积小流,无以成江海。python
内容主要是我的学习使用,题目分类以及部分参考资料来自于CyC的博客,很是感谢大佬,题目来源于LeetCode,很是感谢本站支持。git
给定一个已按照升序排列的有序数组,找到两个数使得它们相加之和等于目标数。函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。github
说明:
返回的下标值(index1 和 index2)不是从零开始的。你能够假设每一个输入只对应惟一的答案,并且你不能够重复使用相同的元素。算法
示例:数组
输入: numbers = [2, 7, 11, 15], target = 9 输出: [1,2] 解释: 2 与 7 之和等于目标数 9 。所以 index1 = 1, index2 = 2 。
解题思路:
本题是1. 两数之和的升级版本,题意给定的是一个升序排列的有序数组,利用双指针
,指针1指向值较小的元素,指针2指向值较大的元素。指针1从头向尾遍历,指针2从尾向头遍历。app
sum>target
,即须要减少某个元素,因此将指针2向左移动,指针1不动(之因此不把指针1向左移动是促使两个指针相遇,终止条件)sum<target
,即须要增大某个元素,因此将指针1向右移动,指针2不动sum==target
,且指针1和指针2不指向同一个元素代码实现:函数
class Solution: def twoSum(self, numbers: List[int], target: int) -> List[int]: left = 0 right = len(numbers)-1 while left<right: # 判断指针是否相遇 num = numbers[left] + numbers[right] if num>target: right-=1 # 指针2左移 elif num<target: left+=1 # 指针1右移 else: # 下标加一返回位置 left+=1 right+=1 return [left,right]
给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c。学习
示例1:ui
输入: 5 输出: True 解释: 1 * 1 + 2 * 2 = 5
示例2:指针
输入: 3 输出: False
解题思路:
本题实际上是上一题的变形,target等于两个数的平方和,题目核心条件:
0-√target
,由于a2+b2=target,极端状况是a=0,b=√target,因此当a不断增大,b必定须要小于√target0-√target
能够看做是一组有序的数组[0,1,2,3,4,5,6...]代码实现:
class Solution: def judgeSquareSum(self, c: int) -> bool: left = 0 right = int(c**0.5) # 至关于√target while left<=right: # 指针能够相遇,例如:1*1+1*1=2,即left指向1,right指向1 num = left*left+right*right if num>c: right-=1 # 指针2左移 elif num<c: left+=1 # 指针1右移 else: return True return False
编写一个函数,以字符串做为输入,反转该字符串中的元音字母。
示例 1:
输入: "hello" 输出: "holle"
示例 2:
输入: "leetcode" 输出: "leotcede"
说明:
元音字母不包含字母"y"。
解题思路:
{"a","e","i","o","u",'A', 'E', 'I', 'O', 'U'}
,采用集合存储时间复杂度优于列表,Python底层采用的是hash。代码实现:
class Solution: def reverseVowels(self, s: str) -> str: words = {"a", "e", "i", "o", "u", 'A', 'E', 'I', 'O', 'U'} l = list(s) # 拆分列表用于交换元素 left = 0 right = len(l) - 1 while left < right: if l[left] in words and l[right] in words: # 指针1,2都指向元音 l[left], l[right] = l[right], l[left] left += 1 right -= 1 elif l[left] not in words: # 指针1没有指向元音,指针2指向元音 left += 1 elif l[right] not in words: # 指针2没有指向元音,指针1指向元音 right -= 1 return "".join(l)
给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。
示例 1:
输入: "aba" 输出: True
示例 2:
输入: "abca" 输出: True 解释: 你能够删除c字符。
注意:
字符串只包含从 a-z 的小写字母。字符串的最大长度是50000。
解题思路:
本题是9. 回文数的升级版,即给回文字符串一次机会,注意这个机会存在两种状况,具体状况以下:
官方说明:贪心算法,即当左右指针相等,此时验证就是去头去尾后的字符串,保证它为回文,则整个字符串就是回文,依次递减。
代码实现:
class Solution: def validPalindrome(self, s: str) -> bool: left = 0 right = len(s) - 1 while left < right: if s[left] == s[right]: left += 1 right -= 1 else: return self.compare(s, left + 1, right) or self.compare(s, left, right - 1) # 删除一个元素,左边或右边,剩余的检查是否为回文字符串 return True def compare(self, s, left, right): while left < right: if s[left] != s[right]: return False left += 1 right -= 1 return True
给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
说明:
示例:
输入: nums1 = [1,2,3,0,0,0], m = 3 nums2 = [2,5,6], n = 3 输出: [1,2,2,3,5,6]
解题思路:
当时看到这个题仍是有点懵逼,主要是利用num1,由题意可知nums1有足够空间,采用双指针以下:
代码实现:
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. """ p1 = m - 1 p2 = n - 1 k = m + n - 1 while p1 >= 0 and p2 >= 0: if nums1[p1] > nums2[p2]: nums1[k] = nums1[p1] # nums1>nums2,将nums1当前元素添加在末尾 p1 -= 1 else: nums1[k] = nums2[p2] # nums2>nums1,将nums2当前元素添加在末尾 p2 -= 1 k -= 1 # 每添加一个末尾游标减一 nums1[:p2+1] = nums2[:p2+1] # 将剩余的nums2元素添加在nums对应位置(通常为头部)
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,咱们使用整数 pos 来表示链表尾链接到链表中的位置(索引从 0 开始)。 若是 pos 是 -1,则在该链表中没有环。
示例 1:
输入:head = [3,2,0,-4], pos = 1 输出:true 解释:链表中有一个环,其尾部链接到第二个节点。
解题思路:
这个题目用了一个很巧妙的方法,就像是脑筋急转弯,主要利用双指针+快慢指针
:
代码实现:
# 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: if(head == None or head.next == None): return False slow = head # 慢指针 quick = head.next # 快指针 while quick != None and quick.next != None: # 判断当前快指针和快指针下一个(防止溢出)是否走到链表尾部 if quick == slow: # 快慢相遇 return True slow = slow.next # 慢指针指向下一个 quick = quick.next.next # 快指针指向下下个 return False
给定一个字符串和一个字符串字典,找到字典里面最长的字符串,该字符串能够经过删除给定字符串的某些字符来获得。若是答案不止一个,返回长度最长且字典顺序最小的字符串。若是答案不存在,则返回空字符串。
示例 1:
输入: s = "abpcplea", d = ["ale","apple","monkey","plea"] 输出: "apple"
题意:
解题思路:
代码实现:
class Solution: def findLongestWord(self, s: str, d: List[str]) -> str: d.sort(key=lambda x: [-len(x), x]) # 排序,规则:长的靠前,相同长度按照字典顺序 for item in d: i = 0 j = 0 while i < len(item) and j < len(s): # 判断某一个串是否到达结尾 if item[i] == s[j]: # 相同,子串指针加一 i += 1 j += 1 # 主串指针始终加一 if len(item) == i: # 找到子串,因为已是有序的即直接返回 return item return ""