剑指offer:面试题NO.3-NO.6

听说剑指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))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值