不積跬步,無以致千里;不積小流,無以成江海。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 ""