一、翻转二叉树
题目描述
翻转一棵二叉树。
示例
示例:
输入:
4
/
2 7
/ /
1 3 6 9
输出:
4
/
7 2
/ /
9 6 3 1
解题
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
if not root:
return None
temp = root.left
root.left = root.right
root.right = temp
self.invertTree(root.left)
self.invertTree(root.right)
return root
典型二叉树反转,使用递归。
利用一个临时结点,使左右结点进行交换。
交换动作完成后,开始递归,左右两边的子树。
二、三个数的最大乘积
题目描述
给你一个整型数组 nums ,在数组中找出由三个数组成的最大乘积,并输出这个乘积。
示例
示例 1:
输入:nums = [1,2,3]
输出:6
示例 2:
输入:nums = [1,2,3,4]
输出:24
示例 3:
输入:nums = [-1,-2,-3]
输出:-6
解题
class Solution:
def maximumProduct(self, nums: List[int]) -> int:
nums.sort()
max1 = nums[-1]* nums[-2]* nums[-3]
max2 = nums[0]* nums[1]* nums[-1]
return max(max1, max2)
如果是一个无序的数组,处理起来没那么快。可以先将数组排序,从小到大。这样一来,3个数的最大乘积
要考虑这几种情况:
- 数组里都是正数,那么3个数最大乘积就是后3位相乘。
- 数组里都是负数,那么3个数最大乘积就是后3位相乘。
- 数组里有正有负,那么3个数最大乘积可能:1.只有1个负数时,仍然为最后3个相乘。2. 大于等于2个负数时,就是最小的2个负数与最大的正数相乘。
所以,总结下来就是2种情况,把两种都计算一遍,然后比较哪个大返回谁。
三、删除有序数组中的重复项
题目描述
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
示例
示例 1:
输入:nums = [1,1,2]
输出:2, nums = [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]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。
不需要考虑数组中超出新长度后面的元素。
解题
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
fast = 1
slow = 1
for fast in range(1, len(nums)):
if nums[fast] != nums[fast-1]:
nums[slow] = nums[fast]
slow += 1
fast += 1
return slow
题目重点是要原地删除,用双指针解决,分别是fast
和slow
,初始都指在下标为1的元素。
- fast为遍历的指针,每遍历一个元素,比较
fast
与前一个 即fast-1
是否相等。 - 如果不相等,就可以把
fast
所在的元素,与slow
交换,放到前面去。然后slow+=1
,指向下一个元素插入
的位置。 - 如果相等,说明
fast
与前一个重复,fast+=1
,继续往右遍历,直到下一个不一样的元素,继续放到slow
位置。
四、删除排序链表中的重复元素
题目描述
存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除所有重复的元素,使每个元素 只出现一次 。
返回同样按升序排列的结果链表。
示例
示例 1:
输入:head = [1,1,2]
输出:[1,2]
示例 2:
输入:head = [1,1,2,3,3]
输出:[1,2,3]
解题
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
if not head:
return head
cur = head
while cur.next:
if cur.val == cur.next.val:
cur.next = cur.next.next
else:
cur = cur.next
return head
这里是一个升序链表,所以重复的数据是连续排列的。这样,可以一次遍历解决。
- cur指针指向head结点,开始往下遍历。这里先判断下
if not head
的情况。 - 如果
cur
的值cur.val
,与下一个结点的值cur.next.val
相等,说明重复,要删除cur.next
。
不过这里的删除操作是改变指针指向,cur.next
指向cur.next.next
即可。被绕开的结点没有引用,会
被自动回收。 - 如果不等于,说明不重复,
cur = cur.next
让cur
指针继续往右移动。
五、链表的中间结点
题目描述
给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
示例
示例 1:
输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
示例 2:
输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。
解题
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def middleNode(self, head: ListNode) -> ListNode:
n = 0
cur = head
while cur:
n += 1
cur = cur.next
m = 0
cur = head
while m < n // 2:
m += 1
cur = cur.next
return cur
两次遍历。
- 第一次遍历,知道了链表的长度
n
。 - 第二次遍历,只遍历到
n
的一半while m < n // 2
,返回指针cur
。