8、    point

8.1    两数之和等于指定值
class Solution:
    def twoSum(self , numbers , target ):
        # write code here

        n = len(numbers)
        if n<2:
            return []
        L = sorted(numbers)
        i = 0
        j = n-1
        while i<j:
            if L[i]+L[j]==target:
                a = numbers.index(L[i])
                numbers.pop(a)
                b = numbers.index(L[j])
                if b>=a:
                    b += 1
                if a>b:
                    a,b = b,a
                return a+1,b+1
            elif L[i]+L[j]>target:
                j -= 1
            elif L[i]+L[j]<target:
                i += 1    
        return []      

8.2    数组中相加和为0的三元组
class Solution:
    def threeSum(self , num ):
        # write code here
        n = len(num)
        num = sorted(num)
        print('num=',num)
        res = []
        for i in range(n-2):
            if num[i]>0:
                break
            j = i+1
            k = n-1            
            while j<k:
                if num[i]+num[j]+num[k]==0:
                    t = [num[i],num[j],num[k]]
                    if t not in res:
                        res.append(t)
                    j += 1
                    k -= 1
                elif num[i]+num[j]+num[k]<0:
                    j += 1
                elif num[i]+num[j]+num[k]>0:
                    k -= 1  
        print('res=',res)
        return

8.3    数组中未出现的最小正整数
先排序,负值略过,重复略过,按1至N对比,如没有则返回
class Solution:
    def minNumberdisappered(self , arr ):
        # write code here
        L = sorted(arr)
        L.append(L[-1]+1)
        #print(L)
        k = 1
        for i in range(len(L)-1):
            #print('i=',i,'k=',k)
            if L[i]<0:
                continue
            if L[i]==L[i+1]:
                continue
            if L[i] != k:
                break
            else:
                k += 1
        #print('k=',k)
        return k

9、    other (array / string / sort)

9.1    字符串的排列
对于已有的每一种排列的每个位置k,插入第i个新数字ss[i],得到一组新排列
class Solution:
    def Permutation(self, ss):
        # write code here        
        n = len(ss)
        if n<=0:
            return
        if n==1:
            return ss

        ss = list(ss)                           # 输入转成list(list才有insert方法)
        out = []
        out.append([ss[0]])                     # i-1时已有的排列(二维数组)
        for i in range(1,n):
            tmp = []
            for string in out:                  # 对于已有的每一种排列
                for k in range(len(string)+1):  # 当前排列的每个位置k
                    s = string.copy()            # 复制当前排列
                    s.insert(k,ss[i])            # 在复制排列的第k个位置,插入第i个数ss[i]
                    tmp.append(s)                # 得到一组新排列加入临时二维数组
            out = tmp                           # 更新i-1时已有的排列

        for i in range(len(out)):
            out[i] = ''.join(out[i])            # 数组合成一个对象用于set()去重,再排序
        out = sorted(set(out))                  # set的元素只能是单个变量,不能是数组等多变量对象
        #print(out)
        return out

9.2    找出连续最长的数字串
原字符串前后加##,数字改1,其它改0,利用规则找01突变点,存储最长数字串
        L = input()
        L = '#'+L+'#'
        #print('L=',L)
        S=''
        for s in L:
            if s.isdigit():
                S += '1'
            else:
                S += '0'
        #print('S=',S)
        i_start = 0
        i_len = 0
        Out = []
        for i in range(1,len(S)):
            if S[i]=='1' and S[i-1]=='0':
                i_start = i
                #print('i_start=',i_start)
            elif S[i]=='0' and S[i-1]=='1':
                i_end = i
                #print('i_end=',i_end)
                if i_end-i_start==i_len:
                    Out.append(L[i_start:i_end])
                elif i_end-i_start>i_len:
                    i_len = i_end-i_start
                    Out = []
                    Out.append(L[i_start:i_end])
        #print(i_len)
        print(''.join(Out)+','+str(i_len))

9.3    学英语
1、关键是1~3位数的表达,首先考虑1~19,20、30、……90建立字典
2、然后将1~3位填充成3位,再分别考虑每一位是否为0的情况
3、and的位置:百位数个数基数词形式加“hundred”,表示几百,在几十几与百位间加上and
例如:2,648 two thousand six hundred and forty eight

D = {'1':'one','2':'two','3':'three','4':'four','5':'five','6':'six','7':'seven','8':'eight','9':'nine','10':'ten',
      '11':'eleven','12':'twelve','13':'thirteen','14':'fourteen','15':'fifteen','16':'sixteen','17':'seventeen','18':'eighteen','19':'nineteen','20':'twenty',
      '30':'thirty','40':'forty','50':'fifty','60':'sixty','70':'seventy','80':'eighty','90':'ninety'}
def fun(L):
    n = len(L)
    #print('LL=',L)
    #print('nn=',n)
    out = ''
    if n==1:
        out += D[L]
    elif n==2:
        if int(L)>=10 and int(L)<=20:            # 10-20特例
            out += D[L]
        else :            
            if L[0] != '0' and L[1] == '0':
                out += D[L]
            elif L[0] != '0' and L[1] != '0':
                t = L[0]+'0'
                out += D[t]+' '+ D[L[1]]
    else:
        if L[0] == '0' and L[1] == '0' and L[2] == '0':
            pass
        elif L[0] != '0' and L[1] == '0' and L[2] == '0': # 佰
            out += D[L[0]]+' hundred'
        elif L[0] == '0' and L[1] != '0' and L[2] == '0': # 十
            #out += 'and ' + D[L[1:3]]
            out += D[L[1:3]]
        elif L[0] == '0' and L[1] == '0' and L[2] != '0': # 个
            #out += 'and ' + D[L[2]]            
            out += D[L[2]]            
        elif L[0] != '0' and L[1] != '0' and L[2] == '0': # 佰十
            out += D[L[0]]+' hundred and '+ D[L[1:3]]
        elif L[0] != '0' and L[1] == '0' and L[2] != '0': # 佰个
            out += D[L[0]]+' hundred and '+ D[L[2]]
        elif L[0] == '0' and L[1] != '0' and L[2] != '0': # 十个
            if int(L[1:])>10 and int(L[1:])<20:           # 10-20特例
                #out += 'and ' + D[L[1:]]
                out += D[L[1:]]
            else:
                t = L[1]+'0'
                #out += 'and ' + D[t]+' '+D[L[2]]
                out += D[t]+' '+D[L[2]]
        elif L[0] != '0' and L[1] != '0' and L[2] != '0': # 百十个
            if int(L[1:])>10 and int(L[1:])<20:           # 10-20特例
                out += D[L[0]] + ' hundred and ' + D[L[1:]]
            else :
                t = L[1]+'0'
                out += D[L[0]] + ' hundred and ' + D[t]+' '+D[L[2]]
return out

9.4    人民币转换
D = {'0':'零','1':'壹','2':'贰','3':'叁','4':'肆','5':'伍','6':'陆','7':'柒','8':'捌','9':'玖'}
def f4(L):
    L = L.zfill(4)
    #--------------------------------------------------
    # 个十百千位分别给单位
    T = ['仟','佰','拾','']
    out = ''
    for i in range(4):
        if L[i] != '0':
            out += D[L[i]]+T[i]
        else:
            out += '零'
    #--------------------------------------------------
    # 最多3个0变为1个0
    out = out.replace('零零','零')
    out = out.replace('零零','零')
    out = out.replace('壹拾','拾')
    #--------------------------------------------------
    # 结尾1个零删除
    if out[-1]=='零':
        out = out[0:-1]
    return out

9.5    合法IP & Mask
# 识别有效的IP地址和掩码并进行分类统计
def value(S):
    return int(S[0])*256**3 + int(S[1])*256**2 + int(S[2])*256 + int(S[3])
def bin64(S):
    b = ''
    for i in S:
        b += bin(int(i))[2:].zfill(8)
    return b
def isIp(ip):
    if len(ip) != 4:
        return False
    for i in ip:
        if not i.isnumeric() or int(i)<0 or int(i)>255:
            return False
    return True
def isMask(mask):
    if len(mask) != 4:
        return False
    for i in mask:
        if not i.isnumeric() or int(i)<0 or int(i)>255:
            return False
    t = list(map(int,list(bin64(mask))))
    a = []
    for i in range(len(t)-1):
        a.append(t[i]-t[i+1])
    if a.count(1) == 1 and a.count(0) == 30:
        return True
    else:
        return False

9.6    螺旋矩阵
先做4个子函数fun1-4,再做一个主调fun,运行一次剥离一圈数据,直到矩阵为空
def fun1(matrix):
    if matrix:
        return matrix.pop(0),matrix   
    else: 
        return [],[]
def fun2(matrix):
    if matrix:
        t = []
        mat = []
        for row in matrix:
            if row:
                a = row.pop()
                t.append(a)
                mat.append(row)
        return t,mat
    else: 
        return [],[]
def fun3(matrix):
    if matrix:
        return matrix.pop()[::-1],matrix
    else: 
        return [],[]
def fun4(matrix):
    if matrix:
        t = []
        mat = []
        for row in matrix[::-1]:
            if row:
                a = row.pop(0)
                t.append(a)
                mat.append(row)
        return t,mat[::-1]
    else: 
        return [],[]
def fun(matrix):
    if matrix:
        out1,matrix = fun1(matrix)
        out2,matrix = fun2(matrix)
        out3,matrix = fun3(matrix)
        out4,matrix = fun4(matrix)
        return out1+out2+out3+out4,matrix
    else: 
        return [],[]

9.7    容器盛水问题
1、从左向右,从右向左各扫一遍,记住当前最大值,
2、如果当前值小于最大值,则计算水容量,如果当前值大于最大值,则更新最大值
3、对应位置左右扫描取小,即是实际容量,
4、第二次扫描时同时计算容量,少一次遍历
class Solution:
    def maxWater(self , arr ):
        # write code here

        L = arr
        n = len(arr)
        if n<3:
            return 0

        i_max = arr[0]
        w1 = []
        for i in range(1,n-1):
            if L[i]>i_max:
                i_max = L[i]
                w1.append(0)
            else:
                w1.append(i_max-L[i])

        i_max = arr[-1]
        w2 = []
        res = 0
        for i in range(n-2,0,-1):
            if L[i]>i_max:
                i_max = L[i]
            else:
                res += min(w1[i-1],i_max-L[i])
        #print(w1)
        #print(w2)
        return res

9.8    称砝码
砝码一个个地增加,原集合中每一个重量 + 新砝码重量 = 新增重量集合
        n = int(input())
        weight = list(map(int,input().strip().split()))
        num = list(map(int,input().strip().split()))

        set_old = {0}
        for i in range(n):
            for j in range(num[i]):           # 按砝码个数依次取
                w = weight[i]                 # 新取砝码的重量
                #print(w)
                set_new = set()
                for s in set_old:
                    set_new.add(s+w)          # 原集合中每一个重量 + 新砝码重量 = 新增重量集合
                set_old = set_old | set_new   # 新增重量集合与原集合的并集,构成下一次的原集合
        print(len(set_old))