刷题周记-7.29

题目网站:面经总结

1. 二维数组中的查找

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

  • 思路
    矩阵是有序的,从左下角来看,向上数字递减,向右数字递增,
    因此从左下角开始查找,当要查找数字比左下角数字大时。右移
    要查找数字比左下角数字小时,上移
def Find(target, array):
    row = len(array)-1
    cols = len(array[0])#turn lengh to index
    col = 0#row=rows and col=0 located at  lower left
    while(col < cols and row>=0):
        if (target < array[row][col]):
            row = row - 1
        elif(target > array[row][col]):
            col = col + 1
        else:
            return True #equal means find the item
    return False

problem1: 将行数或者列数作为index查询列表时,应-1
problem2: 先行后列(二维数组行列数确定),rows = len(array) cols = len(array[0])
problem3: 边界情况(查询终止条件),包不包含0, 这道题中col不包含,因为col是lenth没有-1,而row-1 本身就是index最小情况是0
sum: 思路上,如果是有序2维列表,可以观察规律,从一角开始查询

2. 旋转数组的最小数字

Q:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

  • 思路

解法一:按照旋转规则,查询到后面的元素均小于前面元素,且递增,因此返回第一个小于list[0]的元素即可

def minNumberInRotateArray_1(rotateArray):
    if len(rotateArray) == 0:
        return 0#when the size of array is 0 return 0
    for item in rotateArray:
        if item < rotateArray[0]:#find the first item which smaller than array[0]
            return item
    return rotateArray[0]#Maybe the first item is minimum

解法2: 二分查找,一个left指针指向第一个元素,一个right指针指向最后一个元素,若中间元素大于array[0],则属于前增序列
left指向mid,若mid小于array[0],right指向mid,二分下去,直到两个指针相邻,返回最小者。
目的是找到最中间的元素,根据题目设置,可以判断最中间元素是最小的。

def minNumberInRotateArray_2(rotateArray):
    left = 0#initialize the point
    right = int(len(rotateArray)-1)
    if len(rotateArray) == 0:
        return 0#when the size of array is 0 return 0
    while (rotateArray[left] >= rotateArray[right]):#end condition:when left < right 
        mid = int(left + (right - left) / 2)
        if right - left == 1:
            break
        elif(rotateArray[mid] > rotateArray[left]):#situation 1
            left = mid
        elif(rotateArray[mid] < rotateArray[left]):#situation 2
            right = mid
    return rotateArray[right]

sum: 二分查找中间值

3. 调整数组顺序奇数位于前面

题目1:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,
所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

思路:遇到偶数记录当前指针,当遇到下一个奇数时,将其与之前偶数交换

def reOrderArray_1(array):
    for i in range(0,len(array)):
        if (array[i] % 2 == 0):
            j=i#记录当前偶数指针
            for k in range(i+1,len(array)):
                if (array[k] % 2 != 0):#当再次遇到奇数时
                    array.insert(j,array.pop(k))#奇数删除,并插入到偶数的位置
                    break
    return array

解法二,开辟新数组

def reOrderArray_2(array):
    """思路:开辟新的数组"""
    even =[]
    odd=[]
    for item in array:
        if (item % 2==0):
            even.append(item)
        else:
            odd.append(item)
    return odd + even#合并

problem 1: 奇偶判断 %2 == 0
problem 2: 列表插入list.insert(index, object) array.insert(j,array.pop(k))
奇数删除,并插入到偶数的位置
problem 3: 合并两个list 用“+ ”号

4. 顺时针打印矩阵(

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,
例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

思路1: 左上点和右下点 每次走完剥圈函数之后 左上角坐标++,右下角-- 往圈内移

def printMa(matrix, matrix_res, tR, tC, dR, dC):
"""taverse the matrix by the appointed rule"""
    cur_C = tC
    cur_R = tR
    if (tR == dR):
        for i in range(cur_C,dC+1):
            matrix_res.append(matrix[tR][i])# 只剩一行,把列输完
    elif (tC == dC):
        for i in range(cur_R, dR+1):
            matrix_res.append(matrix[i][tC])# 只剩一列,把行输完
    else:
        while (cur_C < dC):#当前列向右遍历完
            matrix_res.append(matrix[cur_R][cur_C])
            cur_C += 1
        while (cur_R < dR):#当前行向下遍历完
            matrix_res.append(matrix[cur_R][cur_C])
            cur_R += 1
        while (cur_C > tC):#当前列向左遍历完
            matrix_res.append(matrix[cur_R][cur_C])
            cur_C -= 1
        while (cur_R > tR):#当前列向上遍历完
            matrix_res.append(matrix[cur_R][cur_C])
            cur_R -= 1
def printMartrix_2(matrix):
"""print and "remove" the printed items"""
    tR = 0
    tC = 0
    dR = len(matrix)-1
    dC = len(matrix[0])-1
    matrix_res = []
    while(tR <= dR and tC <= dC):
        printMa(matrix,matrix_res,tR,tC,dR,dC)
        tR += 1#每循环一次,剥去一层,tR已输出行数/2(单侧)dC-tC即当前列数
        tC += 1#已输出列数/2(单侧)
        dC -= 1#剩余为输出列*2
        dR -= 1#剩余未输出行*2
    return matrix_res

pro1: range用法,最后一个要+1
sum: 有指针思维这道题中,6个参数都是指针,用于记录当前输出过程,和决定接下来的转向

“”“思路2:可以模拟魔方逆时针旋转的方法,一直做取出第一行的操作
例如
1 2 3
4 5 6
7 8 9
输出并删除第一行后,再进行一次逆时针旋转,就变成:
6 9
5 8
4 7
继续重复上述操作即可。”""

class Solution:
    # matrix类型为二维列表,需要返回列表
    def printMatrix(self, matrix):
        # write code here
        result = []
        while(matrix):
            result+=matrix.pop(0)#将matrix 首元素加入result 中
            if not matrix or not matrix[0]:#如果行或者列为空停止
                break
            matrix = self.turn(matrix)#调用旋转函数
        return result
    def turn(self,matrix):
        num_r = len(matrix)
        num_c = len(matrix[0])
        newmat = []
        for i in range(num_c):
            newmat2 = []#选装后的行
            for j in range(num_r):
                newmat2.append(matrix[j][i])#加入第1列元素,实现方法是先遍历列,再遍历行
            newmat.append(newmat2)#最终是第一列,第二列顺序放置
        newmat.reverse()#逆序符合要求
        return newmat

pro1:result = [ ] ; result+=matrix.pop(0)#将matrix 首元素(嵌套列表多个)加入result 中,由于多个不能用append
pro 2: 内部函数调用 matrix = self.turn(matrix)#调用旋转函数
pro3: 按列输出 for i in range(num_c):
newmat2 = []#选装后的行
for j in range(num_r):
newmat2.append(matrix[j][i])#加入第1列元素,实现方法是先遍历列,再遍历行
newmat.append(newmat2)#最终是第一列,第二列顺序放置
pro4:逆序输出 newmat.reverse()#逆序符合要求

5. 数组中出现次数超过一半的数字

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。
由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

    def MoreThanHalfNum_Solution(self,numbers):
        """返回大于一半数组的数字"""
        if len(numbers)==0:
            return 0
        count = 0
        numbers.sort()#排序,重复多次且超过数组数一半的数字一定在数组中间
        mid_num = numbers[len(numbers)//2]
        for number in numbers:
            if number==mid_num:
                count += 1
        if count >= len(numbers)//2:
            return mid_num
        else:
            return 0

pro1:排序方法 list.sort(cmp=None, key=None, reverse=False)
cmp – 可选参数, 如果指定了该参数会使用该参数的方法进行排序。
key – 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
reverse – 排序规则,reverse = True 降序, reverse = False 升序(默认)。

6. 连续子数组最大和

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,
常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。
但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?
例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。
给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

实际上就是给定有序数组,计算连续子向量的最大和

  • 思路

动态规划:
F(i):以array[i]为末尾元素的子数组的和的最大值,子数组的元素的相对位置不变
F(i)=max(F(i-1)+array[i] , array[i])
res:所有子数组的和的最大值
res=max(res,F(i))

个人理解是分为两步:1、加数字后和数字本身大小对比,如果后者大,只能说明前面有负数,应该舍弃。
2、加数字前和加数字后大小对比,之前的res实际上是作为连续最大值的记忆,体现动态规划原理

如数组[6, -3, -2, 7, -15, 1, 2, 2]
初始状态:
F(0)=6
res=6
i=1:
F(1)=max(F(0)-3,-3)=max(6-3,3)=3
res=max(F(1),res)=max(3,6)=6
i=2:
F(2)=max(F(1)-2,-2)=max(3-2,-2)=1
res=max(F(2),res)=max(1,6)=6
i=3:
F(3)=max(F(2)+7,7)=max(1+7,7)=8
res=max(F(2),res)=max(8,6)=8
i=4:
F(4)=max(F(3)-15,-15)=max(8-15,-15)=-7
res=max(F(4),res)=max(-7,8)=8
以此类推
最终res的值为8

    def FindGreatestSumOfSubArray(self, array):
        if len(array) == 0:
            return 0
        cur = array[0]#起始为第一个值,之后要比大小
        res = array[0]
        for i in range(1,len(array)):#分成两个步骤,1、加上array[i],不加array[i]
            cur = max(cur + array[i],array[i])#加上array[i]的最大值,分为加上更大和不加更大两种情况,
            res = max(cur, res)#比较,加上或者不加array[i]两种情况
        return res

pro1: 和初始值比大小,设为array【0】,迭代从array[1]开始,即i=1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值