听说剑指offer很有名,凑巧leetcode上又有可以白嫖的,就顺便刷一刷。
不过leetcode上的剑指offer都是简单题,不知道原书上面是不是都是这个难度?还是等到真正找工作的时候再去买一本叭。
废话不多说,下面对第三到第六题做个总结:
第三题:数组中重复的数字
这道题目讲真并不难,可能刚学编程一两天的人都会有思路。
这里大概有两种思路:
1、 用字典(哈希),遍历每个元素,如果没有出现在字典中,就在字典中新建一个key。如果出现在字典中(说明之前出现过这个元素),那么直接返回。(这种方法因为没什么可讨论的就省略)
2、注意看题目中的“所有数字都在0~n-1的范围内”,我们可以这么想:把每个元素放到它应该在的位置上
以上图中示例1为栗子:
- 指针指向第一个数字2,将它与数组上位置为2的元素1对调(此时位置2上的元素不是2):[1, 3, 2, 0, 2, 5, 3]
- 指针指向第二个数字3,将它与数组上位置为3的元素0对调(此时位置3上的元素不是3):[1, 0, 2, 3, 2, 5, 3]
- 指针指向第三个数字2,此时2被放在了它该放的位置。
- 指针指向第四个数字3,此时3被放在了它该放的位置
- 指针指向第五个数字2,但是:此时位置2上已经有元素2了,因此可以判断2元素 重复了,返回元素2.
代码如下:
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
for i in range(len(nums)):
while nums[i] != i:
if nums[i] == nums[nums[i]]:
return nums[i]
nums[nums[i]] , nums[i] = nums[i] , nums[nums[i]]
return None
这里有一个要注意的点,就是倒数第二行的交叉赋值
之前我没注意,写成了:
nums[i], nums[nums[i]] = nums[nums[i]], nums[i]
最后报错,这是why呢?
经过查找,我发现对于交叉赋值:a, b = b, a
处理过程为:先将a指向b代表的对象, 再将b指向a代表的对象(这里的a代表的对象指得是原来a代表的对象)
因此,在上式中,在对等式左边的nums[nums[i]](处理过程中的b)进行计算时,nums[i](处理过程中的a)已经被修改了。
.
第四题:二维数组中的查找
这个题还是属于那种谁都会做,但是还是需要一点窍门的题。
这题最重要的就是条件:“列上递增,行上递增”
因此,除了暴力的两个for循环查找,还有一种简单的方法。
- 观察数组左下角的元素,将其与target比较
- 如果target大于该元素,则说明该元素所在的列上不可能有target(因为该列上均小于该元素)。因此,我们下一步只用在该列的右边n*(m-1)数组中找
- 如果target小于该元素,则说明该元素所在的行上不可能有target(因为该行上均大于该元素)。因此,我们下一步只用在该列的上边n-1*m数组中找
- 如果target等于该元素,返回True
这样进行下去,如果一直找不到,则返回False。
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
i, j = len(matrix)-1, 0
while i >= 0 and j <= len(matrix[0])-1:
if target > matrix[i][j]:
j += 1
elif target < matrix[i][j]:
i -= 1
else:
return True
return False
.
第五题:替换空格
这题…也没什么好说的。
值得注意的事,python中字符串是不可修改的!
之前,我想的是遍历每个元素,如果碰到空格,就修改该元素为“%20".
当然,不可避免地失败了,就是忽略了字符串是不可修改的
之后,我的想法是:如果遍历到空格,则重新构造一个字符串为:
s = s[:i] + "%20" + s[i+1:]
这样确实可行,但是每次空格都需要重新构造一个字符串。开销太大了。
因此,最后还是采用了用列表存储,最后用join方法返回的方式:
class Solution:
def replaceSpace(self, s: str) -> str:
res = []
for c in s:
if c == ' ': res.append("%20")
else: res.append(c)
return "".join(res)
.
第六题:从尾到头打印链表
这题唯一注意的是reversed方法返回的是一个迭代器,需要用list()把它实例化。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reversePrint(self, head: ListNode) -> List[int]:
s = []
while head:
s.append(head.val)
head = head.next
return list(reversed(s))