[剑指Offer]01~04

[剑指Offer]01~04

学习使用工具

剑指Offer http://itmyhome.com/sword-means-offer/sword-means-offer.pdf

LeetCode的剑指Offer题库 https://leetcode.cn/problemset/all/

鲁棒性

题目本身思路也许不难,对于一般用例,也很快就能写出能够通过的代码。但实际的得分点集中在特殊用例上,能通过90%用例的代码和能完全AC的代码差距是很大的。

  1. 边界条件

  2. 特殊输入:空字符串、空指针、负值、错误输入等

复杂度优化

剑指Offer 01:赋值运算函数(C++)(LeetCode未收录)

这题不使用C++的可以不用看。

如下为类型CMyString的声明,请为该类型添加赋值运算符函数

class CMyString
{
public:
    CMyString(char* pData = NULL);
    CMyString(const CMyString& str);
    ~CMyString(void);
    
private:
    char* m_pData;
}

很简单的题,但是需要考虑多方面的问题。

  1. 是否把返回值的类型声明为该类型的引用,并在函数结束前返回实例自身的引用(*this);

  2. 是否把传入的参数的类型声明为常量引用;

  3. 是否释放实例自身已有的内存;

  4. 是否判断传入的参数和当前的实例(*this)是不是同一个实例。

解法:

CMyString& CMyString: :operator = (const CMyString &str)
{
    if (this == &str)
    	return *this;
    
    delete []m_ pData;
    m_ pData = NULL;
	
    m_ pData = new char[strlen(str.m_ pData) + 1];
	strcpy (m_ pData, str.m_ pData) ;
	
    return *this;
}

书中还提出了考虑到当前内存可能不足的解法(异常安全性原则),吸收这里的设计思路即可。

CMyString& CMyString: :operator = (const CMyString &str)
{
    if(this != &str)
    {
        CMyString strTemp(str) ;
        
        char* pTemp = strTemp. m pData;
        strTemp.m pData = m pData;
        m_ pData = pTemp;
    }

    return *this;
}

剑指Offer 02:实现Singleton模式(C#)(LeetCode未收录)

未拓展C#技能点,跳过。

做题部分

剑指Offer 03. 数组中重复的数字

找出数组中重复的数字。

在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

示例 1:

输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3 

限制:

2 <= n <= 100000

解法:

很简单的一题。

最开始想的解法是排序后遍历,遇到相邻元素相同返回即可。不过,时间复杂度O(nlogn),还有待优化。

def findRepeatNumber(self, nums: List[int]) -> int:
        nums.sort()
        for i in range(len(nums)):
            if nums[i] == nums[i+1]:
                return nums[i]

改用类哈希表的思想可以将时间复杂度降到O(n),空间复杂度提升为O(n)

def findRepeatNumber(self, nums: List[int]) -> int:
        h = [0] * len(nums)
        for i in nums:
            if h[i] == 0:
                h[i] += 1
            else:
                return i

剑指Offer 04. 二维数组中的查找

在一个 n * m 的二维数组中,每一行都按照从左到右 **非递减 **的顺序排序,每一列都按照从上到下 **非递减 **的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

示例:

现有矩阵 matrix 如下:

[
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
]

给定 target = 5,返回 true

给定 target = 20,返回 false

限制:

0 <= n <= 1000

0 <= m <= 1000

解法:

一开始用递归做,超时了。

def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
        if not matrix:
            return False
        if not matrix[0]:
            return False

        n = len(matrix)
        m = len(matrix[0])

        def func(target: int, matrix: List[List[int]], i: int, j:int):              
            if matrix[i][j] == target :
                return True
            elif matrix[i][j] < target:
                a = False
                b = False
                if i < n - 1:
                    a = func(target, matrix, i+1, j)
                if j < m - 1:
                    b = func(target, matrix, i, j+1)
                return (a or b)
            return False

        return func(target, matrix, 0, 0)

然后死磕半天,翻了下答案才发现正确解法是从右上角开始走。这样问题就简化为二叉搜索树了,世界再见!

def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
        if not matrix:
            return False
        if not matrix[0]:
            return False

        n = len(matrix)
        m = len(matrix[0])
        i = 0
        j = m - 1
        
        while(True):
            if matrix[i][j] == target:
                return True
            elif matrix[i][j] < target:
                i += 1
            else:
                j -= 1

            if i == n or j == -1:
                return False
posted @ 2023-03-06 13:45  无机呱子  阅读(12)  评论(0编辑  收藏  举报