剑指OFFER-二维数组中的查找

Question

在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

关键词:数组 有序 二分查找

Solution

1、暴力破解

时间复杂度:O(N^N)
空间复杂度:O(1)

  • Python
# array 二维列表
# target 目标值
def Find(self, target, array):
    if len(array)==0 or len(array[0])==0:
        return False
    for i in range(len(array)):
        for j in range(len(array[0])):
            if array[i][j] == target:
                return True
    return False
  • C++
// array 二维列表
// target 目标值
bool Find(int target, vector<vector<int> > array) {
    int row = array.size();
    int col = array[0].size();
    if(row==0||col==0) 
    	return false;
    int i, j;
    for(i=0; i<row; i++){
    	for(j=0; j<col; j++){
            if (target==array[i][j])
                return true;
            };
		};
    return false;
    };

2、二分查找

a、逐行二分查找

时间复杂度:O(NlogN)
空间复杂度:O(1)

  • Python
# array 二维列表
# target 目标值
def Find(self, target, array):
    if len(array)==0 or len(array[0])==0:
        return False
    for i in range(len(array)):
        left = 0
        right = len(array[0]) - 1
        while(left <= right):
            j = (left + right) // 2
            if target == array[i][j]:
                return True
            if target > array[i][j]:
                left = j + 1
            else :
                right = j - 1
    return False
  • C++
// array 二维列表
// target 目标值
bool Find(int target, vector<vector<int> > array) {
    int row = array.size();
    int col = array[0].size();
    if(row==0||col==0) 
    	return false;
    int i, j;
    int left, right;
    for(i=0; i<row; i++){
    	for(left = 0, right = col-1; left <= right;){
            j = (left + right) / 2;
            if (target==array[i][j])
                return true;
            if (target > array[i][j]){
                left = j+1;
                continue;
                };
            if (target < array[i][j]){
                right = j-1;
                continue;
                };
            };
		};
    return false;
	};

b、二维折半查找

时间复杂度:O(NlogN)
空间复杂度:O(1)

  • Python
# array 二维列表
# target 目标值
def Find(self, target, array):
    if len(array)==0 or len(array[0])==0:
        return False
    top = left = 0
    bottom = len(array) - 1
    right = len(array[0]) - 1
    while(top<bottom or left<right):
        # 第一行缩小右边界
        rleft, rright = left, right
        while (rleft<=rright):
            j = (rleft + rright) // 2
            if array[top][j] == target:
                return True
            elif array[top][j] > target:
                rright = j - 1
            else:
                rleft = j + 1
        right = min(j, right)
        top += 1
        #最后一行缩小左边界
        rleft, rright = left, right
        while (rleft<=rright):
            j = (rleft + rright) // 2
            if array[bottom][j] == target:
                return True
            elif array[bottom][j] > target:
                rright = j - 1
            else:
                rleft = j + 1
        left = max(j, left)
        bottom -= 1
        #最左列缩小下边界
        ctop, cbottom = top, bottom
        while (ctop<=cbottom):
            i = (ctop + cbottom) // 2
            if array[i][left] == target:
                return True
            elif array[i][left] > target:
                cbottom = i - 1
            else:
                ctop = i + 1
        bottom = min(i, bottom)
        left += 1
        #最右列缩小上边界
        ctop, cbottom = top, bottom
        while (ctop<=cbottom):
            i = (ctop + cbottom) // 2
            if array[i][right] == target:
                return True
            elif array[i][right] > target:
                cbottom = i - 1
            else:
                ctop = i + 1
        top = max(i, top)
        right -= 1
    top = min(len(array)-1, top)
    left = min(len(array[0])-1, left)
    return array[top][left] == target
  • C++
// array 二维列表
// target 目标值
bool Find(int target, vector<vector<int> > array) {
    int row = array.size();
    int col = array[0].size();
    if(row==0||col==0) 
        return false;
    int top = 0;
    int left = 0;
    int bottom = row - 1;
    int right = col - 1;
        
    int rleft, rright, ctop, cbottom;
    int i, j;
    for(;top<bottom || left<right;){
        // 第一行缩小右边界
        rleft = left;
        rright = right;
        while (rleft<=rright){
            j = (rleft + rright) / 2;
            if (array[top][j] == target)
                return true;
            else if (array[top][j] > target)
                rright = j - 1;
            else
                rleft = j + 1;
        };
        if (j < right)
            right = j;
        top++;
        // 最后一行缩小左边界
        rleft = left;
        rright = right;
        while (rleft<=rright){
            j = (rleft + rright) / 2;
            if (array[bottom][j] == target)
                return true;
            else if (array[bottom][j] > target)
                rright = j - 1;
            else
                rleft = j + 1;
        };
        if (j > left)
            left = j;
        bottom--;
        // 最左列缩小下边界
        ctop = top;
        cbottom = bottom;
        while (ctop<=cbottom){
            i = (ctop + cbottom) / 2;
            if (array[i][left] == target)
                return true;
            else if (array[i][left] > target)
                cbottom = i - 1;
            else
                ctop = i + 1;
        };
        if (i < bottom)
            bottom = i;
        left++;
        // 最右列缩小上边界
        ctop = top;
        cbottom = bottom;
        while (ctop<=cbottom){
            i = (ctop + cbottom) / 2;
            if (array[i][right] == target)
                return true;
            else if (array[i][right] > target)
                cbottom = i - 1;
            else
                ctop = i + 1;
        };
        if (i > top)
            top = i;
        right--;
    };
        
    if (top> row - 1)
        top = row - 1;
    if (left > col - 1)
        left = col - 1;  
    return array[top][left] == target;
};

c、中心二分查找

时间复杂度:O(logN^2)
空间复杂度:O(1)

  • Python
# array 二维列表
# target 目标值
def Find(self, target, array):
    if len(array)==0 or len(array[0])==0:
        return False
        
    def search(top, bottom, left,right):
        if top>bottom or left>right:
            return False
        if top==bottom and left==right:
            return (array[top][left]==target)
        i = (top + bottom) // 2
        j = (left + right) // 2
        flag = False
        if array[i][j] == target or array[top][left] == target:
            return True
        # target小于中心点
        if array[i][j] > target:
            # 上方区域
            if target == array[top][left] or target == array[i-1][right]:
                return True
            elif array[top][left]<target and array[i-1][right]>target:
                flag = search(top, i-1, left, right)
            #左下区域
            if not flag:
                if target == array[i][left] or target == array[bottom][j-1]:
                    return True
                elif array[i][left]<target and array[bottom][j-1]>target:
                    flag = search(i, bottom, left, j-1)
            return flag

        # target大于中心点
        else:
            # 右上区域
            if target == array[top][j+1] or target == array[i][right]:
                return True
            elif array[top][j+1]<target and array[i][right]>target:
                flag = search(top, i, j+1, right)
            #下方区域
            if not flag:
                if target == array[i+1][left] or target == array[bottom][right]:
                    return True
                elif array[i+1][left]<target and array[bottom][right]>target:
                    flag = search(i+1, bottom, left, right)
            return flag
   
    return search(0, len(array)-1, 0, len(array[0])-1)
  • C++
// array 二维列表
// target 目标值
bool Find(int target, vector<vector<int> > array) {
    int row = array.size();
    int col = array[0].size();
    if(row==0||col==0) 
        return false;
    return search( array, target, 0, 0, col-1, row-1);
};
    
bool search(vector<vector<int> > &datas, int target, int left, int top, int right, int bottom){
    if (top == bottom && left == right)
        return datas[top][left] == target;
    else if (datas[top][left]>target || datas[bottom][right]<target)
        return false;
    else {
        int cHoriz = (left + right) / 2;
        int cVertic = (top + bottom) / 2;
 
        if (datas[cVertic][cHoriz] == target)
            return true;
        else {
                // 目标大于分割点则排除左上区域,对右下进行递归
            if (datas[cVertic][cHoriz] < target) {
                if (cHoriz<right && cVertic<bottom &&
                    search(datas, target, cHoriz+1, cVertic+1, right, bottom))
                    return true;
            }
            // 否则排除右下区域,对左上进行递归
            else if ((left<cHoriz || top<cVertic) &&
                     search(datas, target, left, top, cHoriz, cVertic))
                return true;
            // 对右上区域进行递归
            if (cHoriz < right &&
                search(datas, target, cHoriz+1, top, right, cVertic))
                return true;
            // 对左下区域进行递归
            if (cVertic < bottom &&
                search(datas, target, left, cVertic+1, cHoriz, bottom))
                return true;
            return false;
        }
    }
};

3、左下/右上移动元素

从左下角开始,若目标大于当前值,目标区域为当前值右边区域;若小于当前值,目标区域为上方区域。

时间复杂度:O(N)
空间复杂度:O(1)

  • Python
## 左下开始移动
# array 二维列表
# target 目标值
def Find(target, array):
    if len(array)==0 or len(array[0])==0:
        return False
    i = len(array)-1
    j = 0
    while i>=0 and j<len(array[0]):
        if target == array[i][j]:
            return True
        elif target > array[i][j]:
            j += 1
        else:
            i -= 1
    return False
  • C++
// 左下开始移动
// array 二维列表
// target 目标值
bool Find(int target, vector<vector<int> > array) {
    int row = array.size();
    int col = array[0].size();
    if (row == 0 || col == 0) 
    	return false;
    int i, j;
    for(i = row-1, j = 0; i>=0 && j < col;){
    	if(target == array[i][j])
    		return true;
    	if(target > array[i][j]){
    		j++;
    		continue;
    		}
    	if(target < array[i][j]){
    		i--;
    		continue;
    		}
		};
    return false;
    };
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值