【leetcode练习题】4. 寻找两个有序数组的中位数

感悟收获

  1. 思路对于编程序来说是特别重要的,先要思考清楚所处理的问题,相处一个算法结构再去实现问题!
  2. 快速实现问题的能力是需要具有的;;
  3. 对于这些题目而言,算法往往比实现这些问题更加重要;
  4. 非常震撼的算法思想,令人有些惊叹!!!
  5. python 除法要除以2.0,不然是整除

题目

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

算法解析

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

官方实现代码

from typing import List
class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        if len(nums1) > len(nums2):
            nums1, nums2 = nums2, nums1
        m = len(nums1)
        n = len(nums2)
        size_left_total = (m + n + 1) >> 1
        # 数组是奇数时,中位数就是中位数,size左 = size右 + 1(包括进去中位数) size右最小索引 为i
        # 数组为偶数时,中位数分左右中位数,size左 = size右 size 右最小索引为i
        left = 0
        right = m    

        # find i and j
        while left < right:
            i = (left + right) >> 1 # 得到的是中位数的索引,或者是右中位数的索引
            j = size_left_total - i
            #print('i,j:', i, j)
            if nums2[j - 1] > nums1[i]:       
               # nums2 的左边最大的数比 num1 右边最小的数要大,说明边界线i需要右移
               # left 需要变大,i在[left ,right ]里面选择
                left = i + 1    # i+1 如果进入死循环,则选i+1 否则 i
            else:
                right= i   #i 或者 i -1

        # i and j have been found
        i = right
        j = size_left_total - i

        nums1_left_max = float('-inf') if i == 0 else nums1[i - 1]
        nums1_right_min = float('inf') if i == m else nums1[i]
        
        nums2_left_max = float('-inf') if j == 0 else nums2[j - 1]
        nums2_right_min = float('inf') if j == n else nums2[j]

        if (m + n) & 1:  # 数组总和数量为奇数
            return max(nums1_left_max, nums2_left_max)
        else:
            return float((max(nums1_left_max, nums2_left_max) + min(nums1_right_min, nums2_right_min)) / 2)

这里上面应该除以2.0,不然会有错误

自己实现的代码1:

nums1=[4,5,6,9,10]
nums2=[1,2]
temp=0;
i=0;
j=0;
length=(len(nums1)+len(nums2))/2
while (i+j < length):
    if (len(nums1)==0):
        if (len(nums2)% 2==0):
            print(nums2[len(nums2)//2-1])
            temp=(nums2[len(nums2)//2-1]+nums2[len(nums2)//2])/2
        else:temp=nums2[len(nums2)//2]
        i=length
    elif (len(nums2)==0):
        if (len(nums1)%2==0):temp=(nums1[len(nums1)//2-1]+nums1[len(nums1)//2])/2
        else:temp=nums1[len(nums1)//2]
        i=length
    else:
        while (nums1[i]<=nums2[j]) &( i+j+1<length) :  i=i+1
        while (len(num2)==j)&(nums1[i]>=nums2[j]) &( i+j+1<length) :  i=i+1
        while (nums1[i]>=nums2[j]) & ( i+j+1<length) : j=j+1
        while (len(num1)==i)&(nums1[i]>=nums2[j]) &( i+j+1<length) :  i=i+1
        if i+j+1>length:
            temp=min(nums1[i],nums2[j])
            break
        if i+j+1==length:
            temp=(nums1[i]+nums2[j])/2
            break
print(temp)      
               

小技巧:正负无穷表示的方法:

  float('inf')  
  float('-inf') 

Python类中的self到底是干啥的

Python编写类的时候,每个函数参数第一个参数都是self,一开始我不管它到底是干嘛的,只知道必须要写上。后来对Python渐渐熟悉了一点,再回头看self的概念,似乎有点弄明白了。

首先明确的是self只有在类的方法中才会有,独立的函数或方法是不必带有self的。self在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。

self名称不是必须的,在python中self不是关键词,你可以定义成a或b或其它名字都可以,但是约定成俗(为了和其他编程语言统一,减少理解难度),不要搞另类,大家会不明白的。

下例中将self改为myname一样没有错误:

class Person:
    def _init_(myname,name):
        myname.name=name
    def sayhello(myname):
        print 'My name is:',myname.name
p=Person('Bill')
print p

self指的是类实例对象本身(注意:不是类本身)。

class Person:
    def _init_(self,name):
        self.name=name
    def sayhello(self):
        print 'My name is:',self.name
p=Person('Bill')
print p

在上述例子中,self指向Person的实例p。 为什么不是指向类本身呢,如下例子:

class Person:
    def _init_(self,name):
        self.name=name
    def sayhello(self):
        print 'My name is:',self.name
p1=Person('Bill')
p2 = Person('Apple')
print p1

如果self指向类本身,那么当有多个实例对象时,self指向哪一个呢?

总结

self在定义时需要定义,但是在调用时会自动传入。

self的名字并不是规定死的,但是最好还是按照约定是用self

self总是指调用时的类的实例。

越努力越幸运。

下面说说typing模块常用的方式:

from typing import List, Tuple, Dict
def add(a:int, string:str, f:float, b:bool) -> Tuple[List, Tuple, Dict, bool]:
    list1 = list(range(a))
    tup = (string, string, string)
    d = {"a":f}
    bl = b
    return list1, tup, d,bl
print(add(5,"hhhh", 2.3, False))

结果:([0, 1, 2, 3, 4], (‘hhhh’, ‘hhhh’, ‘hhhh’), {‘a’: 2.3}, False)
说明:

在传入参数时通过“参数名:类型”的形式声明参数的类型;
返回结果通过"-> 结果类型"的形式声明结果的类型。
在调用的时候如果参数的类型不正确pycharm会有提醒,但不会影响程序的运行。
对于如list列表等,还可以规定得更加具体一些,如:“-> List[str]”,规定返回的是列表,并且元素是字符串。
由于python天生支持多态,迭代器中的元素可能多种,如下:

from typing import List
def func(a:int, string:str) -> List[int or str]:
    list1 = []
    list1.append(a)
    list1.append(string)
    return list1

使用or关键字表示多种类型
typing常用的类型:

int,long,float: 整型,长整形,浮点型;
bool,str: 布尔型,字符串类型;
List, Tuple, Dict, Set:列表,元组,字典, 集合;
Iterable,Iterator:可迭代类型,迭代器类型;
Generator:生成器类型;

Python列表解析配合if else

2017-05-30 11:36:54 KeeJee 阅读数 15788更多
分类专栏: Python Python
用习惯列表解析之后会觉得超级酷,所以在尝试使用列表解析,把循环什么的写在一行里面。使用if的时候什么时候必须要有else,什么时候可以没有else一直没搞明白,直到今天!待我缓缓道来:

列表解析总共有两种形式:

  1. [i for i in range(k) if condition]:此时if起条件判断作用,满足条件的,将被返回成为最终生成的列表的一员。

  2. [i if condition else exp for exp]:此时if…else被用来赋值,满足条件的i以及else被用来生成最终的列表。

以上情况对多个for仍然成立。

print([i for i in range(10) if i%2 == 0])
print([i if i == 0 else 100 for i in range(10)])
 
[0, 2, 4, 6, 8]
[0, 100, 100, 100, 100, 100, 100, 100, 100, 100]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

和你在一起^_^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值