双指针

1. 两数之和

难度简单

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
 1 class Solution:
 2     def twoSum(self, nums: List[int], target: int) -> List[int]:
 3         nums_len = len(nums)
 4         nums_copy = list()
 5 
 6         for index in range(nums_len):
 7             nums_copy.append([nums[index],index])
 8   
 9         nums_copy.sort(key=lambda x: x[0])
10         front_point, back_point =  0, nums_len - 1
11 
12         while front_point < back_point:
13             if nums_copy[front_point][0] + nums_copy[back_point][0] > target:
14                 back_point -= 1
15             elif nums_copy[front_point][0] + nums_copy[back_point][0] < target:
16                 front_point += 1
17             else:
18                 return [nums_copy[front_point][1], nums_copy[back_point][1]]
19         return []
View Code

11. 盛最多水的容器

难度中等

给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (iai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (iai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器,且 n 的值至少为 2。

图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例:

输入:[1,8,6,2,5,4,8,3,7]
输出:49
 1 class Solution:
 2     def maxArea(self, height: List[int]) -> int:
 3         front_point, back_point = 0, len(height) - 1
 4         max_area = 0
 5         
 6         while back_point > front_point:
 7             min_height = min(height[front_point], height[back_point])
 8             temp_max_area = min_height *(back_point - front_point)
 9 
10             if temp_max_area > max_area:
11                 max_area = temp_max_area
12             if height[front_point] == min_height:
13                 front_point += 1
14             else:
15                 back_point -= 1
16 
17         return max_area
View Code

15. 三数之和

难度中等

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]
 1 class Solution:
 2     def threeSum(self, nums: List[int]) -> List[List[int]]:
 3         if not nums:
 4             return []
 5         
 6         nums_size = len(nums)
 7         if nums_size <= 1:
 8             return []
 9         
10         nums.sort()
11         
12         res = []
13         
14         for index in range(nums_size-2):
15             if nums[index] > 0:
16                 break
17             if index > 0 and nums[index] == nums[index - 1]:
18                 continue
19             front_point, back_point = index + 1, nums_size - 1
20             
21             while front_point < back_point:
22                 sum_3_nums = nums[index] + nums[front_point] + nums[back_point]
23                 if sum_3_nums < 0:
24                     front_point += 1
25                     while front_point  < back_point and nums[front_point - 1] == nums[front_point]:
26                         front_point += 1
27                 elif sum_3_nums > 0:
28                     back_point -= 1 
29                     while front_point < back_point and nums[back_point + 1] == nums[back_point]:
30                         back_point -= 1
31                 else:
32                     temp = [nums[index], nums[front_point], nums[back_point]]
33                     res.append(temp[:])
34                     front_point += 1
35                     back_point -= 1 
36                     while front_point  < back_point and nums[front_point - 1] == nums[front_point]:
37                         front_point += 1
38                     while front_point < back_point and nums[back_point + 1] == nums[back_point]:
39                         back_point -= 1            
40             
41         return res
View Code

16. 最接近的三数之和

难度中等

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.

与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).
 1 class Solution:
 2     def threeSumClosest(self, nums: List[int], target: int) -> int:
 3         if not nums:
 4             return None
 5         nums_size = len(nums)
 6         
 7         if nums_size <= 1:
 8             return None
 9         
10         nums.sort()
11         min_difference = float("inf")
12         
13         for index in range(nums_size - 2):
14             
15             #去重
16             if index > 0 and nums[index - 1] == nums[index]:
17                 continue
18                 
19             front_point, back_point = index + 1, nums_size - 1
20         
21             while front_point < back_point:
22                 sums_3_nums = nums[index] + nums[front_point] + nums[back_point]
23                 difference =  sums_3_nums - target
24                 if abs(difference) < abs(min_difference):
25                     min_difference = difference
26                     
27                 if difference < 0:
28                     front_point += 1
29                     #去重
30                     while front_point < back_point and nums[front_point] == nums[front_point - 1]:
31                         front_point += 1
32                 elif difference > 0:
33                     back_point -= 1
34                     #去重
35                     while front_point < back_point and nums[back_point] == nums[back_point + 1]:
36                         back_point -= 1                    
37                 else:
38                     return target
39                     
40         return target + min_difference
View Code

18. 四数之和

难度中等

给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。

注意:

答案中不可以包含重复的四元组。

示例:

给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。

满足要求的四元组集合为:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]
 1 class Solution:
 2     def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
 3         if not nums:
 4             return []
 5         
 6         nums_size = len(nums)
 7         if nums_size <= 3:
 8             return []
 9         
10         nums.sort()
11         print(nums)
12         res = []
13         
14         for index in range(nums_size - 3):
15             
16             if nums[index] > target //4:
17                 break
18             
19             if index > 0 and nums[index] == nums[index - 1]:
20                 continue
21                 
22             for j_index in range(index + 1, nums_size-2):
23                 if j_index > index + 1 and nums[j_index] == nums[j_index - 1]:
24                     continue
25                 
26                 front_point, back_point = j_index + 1, nums_size - 1
27             
28                 while front_point < back_point:
29                     sum_4_nums = nums[index] + nums[j_index] + nums[front_point] + nums[back_point]
30                     diffirence = sum_4_nums - target    
31                     if diffirence < 0:
32                         front_point += 1
33                         while front_point  < back_point and nums[front_point - 1] == nums[front_point]:
34                             front_point += 1
35                     elif diffirence > 0:
36                         back_point -= 1 
37                         while front_point < back_point and nums[back_point + 1] == nums[back_point]:
38                             back_point -= 1
39                     else:
40                         temp = [nums[index], nums[j_index], nums[front_point], nums[back_point]]
41                         res.append(temp[:])
42                         front_point += 1
43                         back_point -= 1 
44                         while front_point  < back_point and nums[front_point - 1] == nums[front_point]:
45                             front_point += 1
46                         while front_point < back_point and nums[back_point + 1] == nums[back_point]:
47                             back_point -= 1    
48                                     
49         return res
View Code

19. 删除链表的倒数第N个节点

难度中等

给定一个链表,删除链表的倒数第 个节点,并且返回链表的头结点。

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5.
 1 # Definition for singly-linked list.
 2 # class ListNode:
 3 #     def __init__(self, x):
 4 #         self.val = x
 5 #         self.next = None
 6 
 7 class Solution:
 8     def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
 9         slow_point, fast_point = head, head
10         
11         for _ in range(n):
12             fast_point = fast_point.next
13                 
14         if not fast_point:
15             return head.next
16         
17         while fast_point.next:
18             slow_point = slow_point.next
19             fast_point = fast_point.next
20             
21         slow_point.next = slow_point.next.next
22         
23         return head
View Code

26. 删除排序数组中的重复项

难度简单

给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

示例 1:

给定数组 nums = [1,1,2], 

函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 

你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,0,1,1,1,2,2,3,3,4],

函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。

你不需要考虑数组中超出新长度后面的元素。

 1 class Solution:
 2     def removeDuplicates(self, nums: List[int]) -> int:
 3         if not nums:
 4             return 0
 5         
 6         nums_size = len(nums)
 7         if nums_size == 1:
 8             return 1
 9         
10         slow_point, fast_point = 1, 1
11         
12         for fast_point in range(1, nums_size):
13             if nums[fast_point] != nums[fast_point - 1]:
14                 nums[slow_point] = nums[fast_point]
15                 slow_point += 1
16             else:
17                 continue
18                 
19         return slow_point
View Code

27. 移除元素

难度简单

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:

给定 nums = [3,2,2,3], val = 3,

函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。

你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,1,2,2,3,0,4,2], val = 2,

函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。

注意这五个元素可为任意顺序。

你不需要考虑数组中超出新长度后面的元素。
 1 class Solution:
 2     def removeElement(self, nums: List[int], val: int) -> int:
 3         if not nums:
 4             return 0
 5         
 6         slow_point, fast_point = 0, 0
 7         
 8         for fast_point in range(len(nums)):
 9             if nums[fast_point] != val:
10                 nums[slow_point] = nums[fast_point]
11                 slow_point += 1
12         
13         return slow_point
View Code

28. 实现 strStr()

难度简单

实现 strStr() 函数。

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回  -1。

示例 1:

输入: haystack = "hello", needle = "ll"
输出: 2

示例 2:

输入: haystack = "aaaaa", needle = "bba"
输出: -1
 1 class Solution:
 2     def strStr(self, haystack: str, needle: str) -> int:
 3         if not needle:
 4             return 0
 5 
 6         haystack_size, needle_size = len(haystack), len(needle)
 7         slow_point = 0
 8         
 9         while slow_point <= haystack_size - needle_size:
10             if haystack[slow_point: slow_point + needle_size] == needle:
11                 return slow_point
12             slow_point += 1
13             
14         return -1
View Code

61. 旋转链表

难度中等

给定一个链表,旋转链表,将链表每个节点向右移动 个位置,其中 是非负数。

示例 1:

输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL

示例 2:

输入: 0->1->2->NULL, k = 4
输出: 2->0->1->NULL
解释:
向右旋转 1 步: 2->0->1->NULL
向右旋转 2 步: 1->2->0->NULL
向右旋转 3 步: 0->1->2->NULL
向右旋转 4 步: 2->0->1->NULL
 1 # Definition for singly-linked list.
 2 # class ListNode:
 3 #     def __init__(self, x):
 4 #         self.val = x
 5 #         self.next = None
 6 
 7 class Solution:
 8     def rotateRight(self, head: ListNode, k: int) -> ListNode:
 9         if not head:
10             return None
11         if not head.next:
12             return head
13         fast_point, slow_point = head, head
14         length = self.lengthList(head)
15         
16         #k大于等于链表长度        
17         if k >= length:
18             for _ in range(k%length):
19                 front_point, back_point = head, head.next
20                 while back_point.next:
21                     back_point = back_point.next
22                     front_point = front_point.next
23                 back_point.next = head
24                 front_point.next = None
25                 head = back_point
26             return head
27 
28         #k小于链表长度 
29         for _ in range(k):
30             if fast_point:
31                 fast_point = fast_point.next
32             else:
33                 break  
34 
35         while fast_point.next:
36             slow_point = slow_point.next
37             fast_point = fast_point.next
38         fast_point.next = head
39         head = slow_point.next
40         slow_point.next = None
41 
42         return head
43 
44     def lengthList(self, head: ListNode) -> int:
45         temp = head
46         length = 0
47         while temp:
48             length += 1
49             temp = temp.next
50 
51         return length
View Code

 

80. 删除排序数组中的重复项 II

难度中等

 

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例 1:

给定 nums = [1,1,1,2,2,3],

函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。

你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,0,1,1,1,1,2,3,3],

函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。

你不需要考虑数组中超出新长度后面的元素。
 1 class Solution:
 2     def removeDuplicates(self, nums: List[int]) -> int:
 3         if not nums:
 4             return 0
 5 
 6         nums_size = len(nums)
 7         if nums_size == 1:
 8             return 1
 9             
10         slow_point, fast_point = 0, 0
11         
12         for fast_point in range(0, nums_size):
13             if fast_point == 0 or (fast_point > 0 and nums[fast_point] != nums[fast_point - 1]):
14                 temp_num_time = 1
15                 nums[slow_point] = nums[fast_point]
16                 slow_point += 1
17             elif temp_num_time == 1:
18                 temp_num_time += 1
19                 nums[slow_point] = nums[fast_point]
20                 slow_point += 1
21             else:
22                 continue
23 
24         return slow_point
View Code

86. 分隔链表

难度中等

给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。

你应当保留两个分区中每个节点的初始相对位置。

示例:

输入: head = 1->4->3->2->5->2, x = 3
输出: 1->2->2->4->3->5
 1 # Definition for singly-linked list.
 2 # class ListNode:
 3 #     def __init__(self, x):
 4 #         self.val = x
 5 #         self.next = None
 6 
 7 class Solution:
 8     def partition(self, head: ListNode, x: int) -> ListNode:
 9         if not head:
10             return None
11         smallerNode = ListNode(0)
12         biggerNode = ListNode(x)
13         
14         smaller_pointer, bigger_pointer = smallerNode, biggerNode
15         pointer = head
16         while pointer:
17             if pointer.val < x:
18                 smaller_pointer.next = pointer
19                 smaller_pointer = smaller_pointer.next
20                 pointer = pointer.next
21                 smaller_pointer.next = None
22             else:
23                 bigger_pointer.next = pointer
24                 bigger_pointer = bigger_pointer.next
25                 pointer = pointer.next
26                 bigger_pointer.next = None
27             
28         smaller_pointer.next = biggerNode.next
29 
30         return smallerNode.next
View Code

88. 合并两个有序数组

难度简单

给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 使 num1 成为一个有序数组。

说明:

  • 初始化 nums1 和 nums2 的元素数量分别为 m 和 
  • 你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。

示例:

输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6],       n = 3

输出: [1,2,2,3,5,6]
 1 class Solution:
 2     def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
 3         """
 4         Do not return anything, modify nums1 in-place instead.
 5         """
 6         if m + n == 0:
 7             return 
 8         
 9         slow_pointer = m + n - 1
10         nums1_pointer = m - 1
11         nums2_pointer = n - 1
12         
13         while nums1_pointer >= 0 and nums2_pointer >= 0:
14             if nums1[nums1_pointer] >= nums2[nums2_pointer]:
15                 nums1[slow_pointer] = nums1[nums1_pointer]
16                 nums1_pointer = nums1_pointer - 1
17                 slow_pointer = slow_pointer - 1
18             else:
19                 nums1[slow_pointer] = nums2[nums2_pointer]
20                 nums2_pointer = nums2_pointer - 1
21                 slow_pointer = slow_pointer - 1
22                 
23         while nums1_pointer >= 0:
24             nums1[slow_pointer] = nums1[nums1_pointer]
25             nums1_pointer = nums1_pointer - 1
26             slow_pointer = slow_pointer - 1  
27             
28         while nums2_pointer >= 0:
29             nums1[slow_pointer] = nums2[nums2_pointer]
30             nums2_pointer = nums2_pointer - 1
31             slow_pointer = slow_pointer - 1                
32                 
33         return 
View Code

125. 验证回文串

难度简单

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明:本题中,我们将空字符串定义为有效的回文串。

示例 1:

输入: "A man, a plan, a canal: Panama"
输出: true

示例 2:

输入: "race a car"
输出: false
 1 class Solution:
 2     def isPalindrome(self, s: str) -> bool:
 3         if not s:
 4             return True
 5         front_pointer, back_pointer = 0, len(s) - 1
 6         
 7         while front_pointer < back_pointer:
 8             if s[front_pointer].isalnum() and s[back_pointer].isalnum():
 9                 if s[front_pointer].lower() != s[back_pointer].lower():
10                     return False
11                 else:
12                     front_pointer += 1
13                     back_pointer -= 1
14             elif (not s[front_pointer].isalnum()) and (not s[back_pointer].isalnum()):
15                 front_pointer += 1
16                 back_pointer -= 1     
17             elif s[front_pointer].isalnum() and (not s[back_pointer].isalnum()):
18                 back_pointer -= 1
19             else:
20                 front_pointer += 1
21         
22         return True
View Code

141. 环形链表

难度简单

给定一个链表,判断链表中是否有环。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
 1 # Definition for singly-linked list.
 2 # class ListNode:
 3 #     def __init__(self, x):
 4 #         self.val = x
 5 #         self.next = None
 6 
 7 class Solution:
 8     def hasCycle(self, head: ListNode) -> bool:
 9         if not head:
10             return False
11         
12         slow_pointer, fast_pointer = head, head
13         
14         while fast_pointer.next:
15             slow_pointer = slow_pointer.next
16             fast_pointer = fast_pointer.next.next
17             if fast_pointer == slow_pointer:
18                 return True
19             elif not fast_pointer:
20                 break
21             
22         return False
View Code

142. 环形链表 II

难度中等

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

说明:不允许修改给定的链表。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部连接到第二个节点。


示例 2:

输入:head = [1], pos = -1
输出:no cycle
解释:链表中没有环。

 1 # Definition for singly-linked list.
 2 # class ListNode:
 3 #     def __init__(self, x):
 4 #         self.val = x
 5 #         self.next = None
 6 
 7 class Solution:
 8     def detectCycle(self, head: ListNode) -> ListNode:
 9         if not head:
10             return None
11         
12         slow_pointer, fast_pointer = head, head
13         
14         while fast_pointer.next:
15             slow_pointer = slow_pointer.next
16             fast_pointer = fast_pointer.next.next
17             if fast_pointer == slow_pointer:
18                 fast_pointer = head
19                 while fast_pointer != slow_pointer:
20                     fast_pointer = fast_pointer.next
21                     slow_pointer = slow_pointer.next
22                 return slow_pointer
23             elif not fast_pointer:   
24                 break    
25                 
26         return None     
View Code

 NC128 容器盛水问题

链接:https://www.nowcoder.com/questionTerminal/f92929ec6e5642a690e7c197b0c40e38?orderByHotValue=1&mutiTagIds=1579&page=1&onlyReference=false
来源:牛客网
给定一个整形数组arr,已知其中所有的值都是非负的,将这个数组看作一个容器,请返回容器能装多少水。 

具体请参考样例解释 

输入描述:

第一行一个整数N,表示数组长度。

接下来一行N个数表示数组内的数。

输出描述:

输出一个整数表示能装多少水。

示例1
输入
6
3 1 2 5 2 4

输出

5

说明

示例2

输入

5
4 5 1 3 2

输出

2

 1 class Solution:
 2     def maxWater(self , arr ):
 3         # write code here
 4         if not arr:
 5             return 0
 6         left, right = 0, len(arr)-1
 7         left_val, right_val = arr[left], arr[right]
 8         max_water = 0
 9         while left < right:
10             if left_val < right_val:
11                 left += 1
12                 if arr[left] >= left_val:
13                     left_val = arr[left]
14                     continue
15                 else:
16                     max_water += (left_val - arr[left])
17             else: 
18                 right -= 1
19                 if arr[right] >= right_val:
20                     right_val = arr[right]
21                     continue 
22                 else:
23                     max_water += (right_val - arr[right])
24                     
25         return max_water
26                         
27                     
28 S = Solution()
29 while True:
30     try:
31         arr = list(map(int, input()[1:-1].split(',')))
32         print(S.maxWater(arr))
33     except:
34         break
View Code

原文地址:https://www.cnblogs.com/dede-0119/p/12509736.html