剑指Offer(三)——数组

 

1、(JZ28)数组中出现次数超过一半的数字(数组,哈希)

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

# -*- coding:utf-8 -*-
from collections import defaultdict
class Solution:
    def MoreThanHalfNum_Solution(self, numbers):
        # write code here
        dic = defaultdict(int)
        for n in numbers:
            dic[n] += 1
        for k,v in dic.items():
            if v > len(numbers)/2:
                return k
        return 0
# -*- coding:utf-8 -*-
class Solution:
    def MoreThanHalfNum_Solution(self, numbers):
        # write code here
        num = map(str, numbers)
        s = list(set(num))
        for i in s:
            if num.count(i)>len(numbers)/2:
                return int(i)
        return 0
        

2、(JZ51)构建乘积数组

给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。(注意:规定B[0] = A[1] * A[2] * ... * A[n-1],B[n-1] = A[0] * A[1] * ... * A[n-2];)

对于A长度为1的情况,B无意义,故而无法构建,因此该情况不会存在。

class Solution:
    def multiply(self, A):
        # write code here
        B = []
        for i in range(len(A)):
            ans = 1
            for j in range(len(A)):
                if j != i:
                    ans = ans * A[j]
            B.append(ans)
        return B

上面时憨憨做法,极大占用内存。果然只有在c++中才能看到漂亮的做法。

class Solution {
public:
    vector<int> multiply(const vector<int>& A) {
        int len=A.size();
        vector<int> B(len);
        int temp=1;
        for (int i=0; i<len; i++){
            B[i] = temp;
            temp *= A[i];
        }
        temp =1;
        for (int i =len-1; i>=0; i--){
            B[i] *= temp;
            temp *= A[i];
        }
        return B;
    }
};

换成python也没少???

扫描二维码关注公众号,回复: 12721771 查看本文章
# -*- coding:utf-8 -*-
class Solution:
    def multiply(self, A):
        # write code here
        B = [1]*len(A)
        temp = 1
        for i in range(len(A)):
            B[i] = temp
            temp *= A[i]
        temp = 1
        for i in range(len(A)):
            B[len(A)-i-1] *= temp
            temp *= A[len(A)-i-1]
        return B

【其他问题】关于python的内存问题(未仔细看):

如何优化python占用的内存:https://blog.csdn.net/ajian6/article/details/97167695

python内存管理及释放:https://blog.csdn.net/jiangjiang_jian/article/details/79140742

3、(JZ50)数组中重复的数字

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中第一个重复的数字。 例如,如果输入长度为7的数组[2,3,1,0,2,5,3],那么对应的输出是第一个重复的数字2。没有重复的数字返回-1。

class Solution:
    def duplicate(self , numbers ):
        # write code here
        if len(set(numbers))==len(numbers):
            return -1
        ans=[0]*len(numbers)
        for n in numbers:
            ans[n] += 1
            if ans[n] > 1:
                return n
        return -1
class Solution:
    def duplicate(self , numbers ):
        # write code here
        L = []
        for n in numbers:
            if n in L:
                return n
            else:
                L.append(n)
        return -1
class Solution:
    def duplicate(self , numbers ):
        # write code here
        record = set()
        for n in numbers:
            if n in record:
                return n
            record.add(n)
        return -1

4、(JZ42)和为S的两个数字

输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

瞎胡解

# -*- coding:utf-8 -*-
import sys
class Solution:
    def FindNumbersWithSum(self, array, tsum):
        # write code here
        ans = []
        if not array:
            return ans
        dif = 0
        p = 0
        q = len(array)-1
        while array[q]>=tsum:
            q -= 1
        while p<q:
            
            ts = array[p]+array[q]
            if ts==tsum and array[q]-array[p]> dif:
                ans = [array[p],array[q]]
                dif = array[q]-array[p]
            elif ts < tsum:
                p += 1
            else:
                p = 0
                q -= 1
        return ans

上面的解法else之后从0开始有点浪费 

# -*- coding:utf-8 -*-
import sys
class Solution:
    def FindNumbersWithSum(self, array, tsum):
        # write code here
        ans = []
        if not array:
            return ans
        cha = 0
        p = 0
        q = len(array)-1
        while array[q]>=tsum:
            q -= 1
        while p<q:
            
            ts = array[p]+array[q]
            if ts==tsum and array[q]-array[p]> cha:
                ans = [array[p],array[q]]
                cha = array[q]-array[p]
            elif ts < tsum:
                p += 1
            else:
                p = 0
                q -= 1
        return ans

5、(JZ37)数字在排序数组中出现的次数

统计一个数字在升序数组中出现的次数。

# -*- coding:utf-8 -*-
class Solution:
    def GetNumberOfK(self, data, k):
        # write code here
        if k not in data:
            return 0
        index = data.index(k)
        num = 0
        for i in range(index, len(data)):
            if data[i] == k:
                num += 1
        return num
# -*- coding:utf-8 -*-
class Solution:
    def GetNumberOfK(self, data, k):
        # write code here
        count = 0
        for i in range(len(data)):
            if k == data[i]:
                count += 1
        return count

6、(JZ4)重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

思路:充分利用前序遍历和中序遍历的特点。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回构造的TreeNode根节点
    def reConstructBinaryTree(self, pre, tin):
        # write code here
        if not pre or not tin:
            return None
        root = TreeNode(pre.pop(0))
        index = tin.index(root.val)
        root.left = self.reConstructBinaryTree(pre,tin[:index])
        root.right = self.reConstructBinaryTree(pre,tin[index+1:])
        return root

7、(JZ1)二维数组中的查找

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

# 最简单粗暴的方法
# -*- coding:utf-8 -*-
class Solution:
    # array 二维列表
    def Find(self, target, array):
        # write code here
        if not array:
            return False
        rows = len(array)
        cols = len(array[0])
        for r in range(rows):
            for c in range(cols):
                if array[r][c] == target:
                    return True
        return False
        

思路:首先我们选择从左下角开始搜寻,(为什么不从左上角开始搜寻,左上角向右和向下都是递增,那么对于一个点,对于向右和向下会产生一个岔路;如果我们选择从左下脚开始搜寻的话,如果大于就向右,如果小于就向下)。从左下角元素往上找,右边元素大,上面元素小。若出了边界,则表示不存在target元素。

# -*- coding:utf-8 -*-
class Solution:
    # array 二维列表
    def Find(self, target, array):
        # write code here
        rows = len(array)-1
        cols = len(array[0])-1
        i = rows
        j = 0
        while j<=cols and i>=0:
            if target<array[i][j]:
                i -= 1
            elif target>array[i][j]:
                j += 1
            else:
                return True
        return False

8、调整数组顺序使奇数位于偶数前面

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

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param array int整型一维数组 
# @return int整型一维数组
#
class Solution:
    def reOrderArray(self , array ):
        # write code here
        index = 0
        ans = []
        if not array:
            return ans
        for n in array:
            if n % 2 == 1:
                ans.insert(index, n)
                index += 1
            else:
                ans.append(n)
        return ans
       

9、斐波那契数列

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。

n\leq 39n≤39

# -*- coding:utf-8 -*-
class Solution:
    def Fibonacci(self, n):
        # write code here
        if n <= 1:
            return n
        a = 0
        b = 1
        for i in range(n-1):
            temp = a + b
            a = b 
            b = temp
        return temp

10、顺时针打印矩阵

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下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.

关键在于——边界条件选定

if matrix and matrix[0]

# -*- coding:utf-8 -*-
class Solution:
    # matrix类型为二维列表,需要返回列表
    def printMatrix(self, matrix):
        # write code here
        ans = []
        if len(matrix)==1:
            return matrix[0]
        while matrix:
            ans.extend(matrix.pop(0))
            if matrix and matrix[0]:
                for i in range(len(matrix)):
                    ans.append(matrix[i].pop())
            if matrix and matrix[0]:
                ans += matrix.pop()[::-1]
            if matrix and matrix[0]:
                for j in reversed((range(len(matrix)))):
                    ans.append(matrix[j].pop(0))
        return ans

[::-1]    -1表示步进

extend   a = [1,2]  b=[3,3]  a.extend(b) # a = [1,2,3,4] 列表合并

reversed 函数返回一个反转的迭代器。

11、(JZ32)把数组排成最小的数

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。(遗留问题)

# -*- coding:utf-8 -*-
class Solution:
    def PrintMinNumber(self, numbers):
        # write code here
        n = len(numbers)
        if n==0:
            return ''
        if n==1:
            return numbers[0]
        compare = lambda n1, n2: int(str(n1)+str(n2))-int(str(n2)+str(n1))
        array = sorted(numbers, cmp=compare)
        return ''.join([str(i) for i in array])
            

 sorted(numbers, cmp=compare)

# -*- coding:utf-8 -*-
import itertools
class Solution:
    def PrintMinNumber(self, numbers):
        # write code here
        ret = []
        numbers = list(map(str,numbers))
        mm = itertools.permutations(numbers)
        for i in mm:
            ret.append(''.join(i))
        ret.sort()
        return ret[0]
            

itertools.permutations(iterable, r=None) 全排列


连续返回由 iterable 元素生成长度为 r 的排列。

如:

import itertools
nums = ['a','b','c']
for num in itertools.permutations(nums, 3):
    a = num[0] + num[1] + num[2]
    print(a)
'''
abc
acb
bac
bca
cab
cba
'''

12、(JZ35) 数组中的逆序对

13、(JZ66)机器人的运动范围

猜你喜欢

转载自blog.csdn.net/caicai0001000/article/details/114273004