剑指offer整理(附python代码)——数组

Content

1.二维数组中的查找

问题描述

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

考察点:数组查找
思路1

从右上角开始扫描,情况及方案如下:
- 该数大于要找的数:删除该数所在的列
- 该数小于要找的数:删除该数所在的行
- 该数等于要找的数:直接返回该数

class Solution1:
    def Find(self, target, array):
        rows = len(array)
        cols = len(array[0])
        row = 0
        col = cols-1
        icon = False
        while (row<rows)&(col>=0):
            if (array[row][col]==target):
                icon = True
                break
            elif array[row][col]>target:
                col = col-1
            else:
                row = row+1
        return icon
if __name__ == '__main__':
    s = Solution1()
    array = [[1,3,6],[2,4,7],[3,5,9]]
    print s.Find(7,array)
True

2.旋转数组的最小数字

问题描述

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

关键:二分查找(折半查找)

要求:线性表必须采用顺序存储结构;元素按关键字有序排列;
1. 将表的中间位置的记录与关键字进行比较,若同,则查找成功;否则将表按关键字分为左右两部分
2. 若小于关键字,则从右半部分继续查找
3. 若大于关键字,则从左半部分继续查找

思路:
  1. 设置两个指针pl,pr,分别指向数组的首尾。
  2. 找到数组的中间元素,与两个指针进行比较,若大于等于pl,则将pl指向中间元素;若小于等于pr,则将pr指向中间元素。
  3. 重复步骤2,直到两个指针最后左右相邻,此时pr即为最小值。
    [bug]1.没考虑数组未经过旋转的情况2.当中间元素和首尾元素相同时,无法判断pl,pr的指向。(如:0 1 1 1 1;旋转后:1 0 1 1 1;或 1 1 1 0 1;)
# -*- coding:utf-8 -*-
class Solution:
    def minNumberInRotateArray(self, rotateArray):
        # write code here
        left = 0
        right = len(rotateArray)-1
        mid = 0
        while(rotateArray[left]>=rotateArray[right]):
            # 递归终止条件,两个指针最后左右相邻,此时pr即为最小值。
            if ((right-left)==1):
                mid = right
                break
            mid = (left+right)/2
            #bug2:当数组中的 首=尾=中间元素 时,用search()方法遍历数组,找最小。
            if ((rotateArray[left]==rotateArray[right]) and (rotateArray[mid]==rotateArray[left])):
                return search(rotateArray)
            if(rotateArray[mid]>=rotateArray[left]):
                left = mid
            else:
                right = mid
        return rotateArray[mid]
    def search(self,rotateArray):
        # 遍历数组,查找最小元素
        mid = rotateArray[0]
        for i in range(1,len(rotateArray)):
            if rotateArray[i]<mid:
                mid = rotateArray[i]
        return mid
s = Solution()
print s.minNumberInRotateArray([3,4,5,1,2])
1

3.数值的整数次方

问题描述

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

考察点:代码完整性

要考虑exponent的取值:负整数、0、正整数,分三种情况

思路

n次方变为n次的积,首先将exponent取绝对值进行计算,然后根据exponent的取值:负整数、0、正整数,分情况输出。

class Solution:
    def Power(self, base, exponent):
        # write code here
        base1 = base
        # 首先将exponent取绝对值,计算
        for i in range(abs(exponent)-1):
            base = base1*base
        #根据exponent的取值:负整数、0、正整数,分情况输出
        if exponent < 0:
            return 1.0 / base
        elif exponent == 0:
            return 1
        else:
            return base
if __name__ == '__main__':
    s = Solution()
    print s.Power(2,-3)
0.125

4.调整数组顺序使奇数位于偶数前面

问题描述

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

考察点:代码完整性

数组全奇数、全偶数、为空、

思路1
  • 1st遍历,判断数组是否全奇数、全偶数、为空?返回:2nd遍历;
  • 2nd遍历,新建等长数组,奇数从前开始插入,偶数从(数组长-偶数个数)位置开始插入
  • 额外空间:等长数组、数组总长、偶数个数、已存储的奇数/偶数个数
class Solution4:
    # 1st遍历,判断数组是否全奇数、全偶数、为空?返回:2nd遍历;
    # 2nd遍历,新建等长数组,奇数从前开始插入,偶数从(数组长-偶数个数)位置开始插入
    # 额外空间:等长数组、数组总长、偶数个数、已存储的奇数/偶数个数
    def reOrderArray(self, array):
        # write code here
        a_len = len(array)
        new_array = [0]*a_len
        or_numb = 0
        for i in array:
            if i%2 == 0:
                or_numb += 1
        #数组全奇数、全偶数、为空,直接返回原数组
        if or_numb == a_len or or_numb==0:
            return array
        else:
            oddicon = 0
            oricon = 0
            for i in array:
                if i%2 == 0:
                    print "oricon",oricon,i
                    new_array[a_len-or_numb+oricon] = i
                    oricon += 1
                else:
                    print "oddicon",oddicon,i
                    new_array[oddicon] = i
                    oddicon += 1
            return new_array
if __name__ == '__main__':
    s = Solution4()
    print s.reOrderArray([1,4,6,8,9])
oddicon 0 1
oricon 0 4
oricon 1 6
oricon 2 8
oddicon 1 9
[1, 9, 4, 6, 8]

5.把字符串转成整数

问题描述

将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。
输入一个字符串,包括数字字母符号,可以为空。若非合法的数值表达,则返回0。

思路
  1. 用正则表达式判断字符串中是非法(含字母),字符串比较判断符号(+、-),负数则用整数-1【指数函数10^x,可以用pow(10,x),或*10**x,两个表示指数】
  2. 直接用int(),将字符串转整数
import re
print re.search(r'[a-zA-Z]','232Z43')
None
# -*- coding:utf-8 -*-
import re
import math
import time
class Solution:
    def StrToInt(self, s):
        # write code here
        numb = len(s)-1
        sums = 0
        if s=='0'or re.search(r'[a-zA-Z]',s) or s=='':
            return 0
        elif s[0]=='-':
            for i in range(1,numb+1):
                sums=sums+int(s[i])*math.pow(10,numb-i)
            return (-1)*sums
        elif s[0]=='+':
            for i in range(1,numb+1):
                sums=sums+int(s[i])*math.pow(10,numb-i)
            return sums
        else:
            for i in range(numb+1):
                print i,s[i]
                sums+=int(s[i])*math.pow(10,numb-i)
            return sums

if __name__ == '__main__':
    start = time.time()
    s = Solution()
    print s.StrToInt('-123')       
    end = time.time()
    print 'time:',end-start
-123.0
time: 0.0
# 时间更短
# -*- coding:utf-8 -*-
class Solution:
    def StrToInt(self, s):
        # write code here
        try:
            return int(s)
        except Exception as e:
            return 0
if __name__ == '__main__':
    start = time.time()
    s = Solution()
    print s.StrToInt('-123')       
    end = time.time()
    print 'time:',end-start
-123
time: 0.0

6.顺时针打印矩阵

问题描述

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 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(较快)
  1. 每次打印第一行,打印完后对数组进行逆时针旋转。(魔方的逆时针旋转)
  2. 循环上述过程
思路2
<
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值