剑指offer:20、数组中的逆序对;21、连续子数组的最大和;22、整数中1出现的次数

20、数组中的逆序对
题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%100000000
示例1
输入
1,2,3,4,5,6,7,0
输出
7
笔记:题目很简单,然而按照写出来的,不能通过会超时,找了博客,看到的思路
更加简洁(牛逼)的方法:
先将原序列排序,然后从排完序的数组中取出最小的,它在原数组中的位置表示有多少比它大的数在它前面,每取出一个在原数组中删除该元素,保证后面取出的元素在原数组中是最小的,这样其位置才能表示有多少比它大的数在它前面,即逆序对数。

class Solution:
    def InversePairs(self, data):
        # write code here
        if len(data) == 0 or len(data) == 1:
            return 0
        num = []
        for i in data:
            num.append(i)
        num.sort()
        c = 0
        for i in range(len(num)):
            p = data.index(num[i])
            c += p
            data.remove(num[i])  #deta.pop(p)
        return c%1000000007

附上冒泡排序和快速排序python实现

#冒泡排序-------------------------------------------------------
def BubbleSort(list):
    for i in reversed(range(len(a))):
        for j in range(0,len(a)-1):
            if(list[j] > list[j+1]):
                temp=list[j]
                list[j]=list[j+1]
                list[j+1]=temp
def qsort(list):
    if list==[]:
        return []
    else:
        smaller=[x for x in list[1:] if x<list[0]] #比list[0]小的部分
        bigger=[x for x in list[1:] if x>=list[0]] #比list[0]大(或相等)的部分
        return qsort(smaller)+[list[0]]+qsort(bigger)

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

解法1:自己的解法,总算可以做出一类题型了

# -*- coding:utf-8 -*-
class Solution:
    def FindGreatestSumOfSubArray(self, array):
        # write code here
        num = []
        for i in array:
            num.append(i)
        if len(num) == 1:
            return num[0]
        r = []
        for i in range(len(num) - 1):
            a = num[i]
            for j in range(i + 1, len(num)):
                a = a + num[j]
                r.append(a)
        r = r + num
        r.sort()
        return r[-1]

解法2:动态规划解法,得补一下知识,膜拜大神加油不要放弃你可以的
链接:https://www.nowcoder.com/questionTerminal/459bd355da1549fa8a49e350bf3df484
来源:牛客网

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

class Solution:
    def FindGreatestSumOfSubArray(self, array):
        # write code here
        res = max(array)
        temp = 0
        for i in array:
            temp = max(i, temp + i)
            res = max(res ,temp)
        return res

22、整数中1出现的次数
题目描述
求出113的整数中1出现的次数,并算出1001300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)

笔记:解法1,自己想的,改了一次竟然真的可以通过,还好测试用例比较简单~~算了一种奇怪的解法吧
解法1:自己的不简洁版本

# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1Between1AndN_Solution(self, n):
        # write code here
        num = []
        for i in range(1, n + 1):
            num.append(i)
        c = 0
        for j in range(n):
            a = str(num[j])
            c = c + a.count('1')
        return c

解法2:
1位数,1-9中,1一共出现了1次;

  2位数,10-99中,10-19的十位上一共出现了10*1=10次,对于每个十位开头的数字10-19、20-29,每个数个位上出现的是1-9中1出现的次数,共有9个区间9*1=9次;

  3位数,100-999,100-199百位上出现了10**2=100次,对于每个百位数开头,例如100-199,200-299,低位上其实就是0-99这个区间上1出现的次数,一共9个区间 9*19=171次;

  由此推测,对于1-9,10-99,100-999,每个n位数中包含1的个数公式为:

  f(1) = 1

  f(2) = 9 * f(1) + 10 ** 1

  f(3) = 9 * f(2) + 10 ** 2

  f(n) = 9 * f(n-1) + 10 ** (n-1)

  通过以上分析,我们可以确定对于任意一个给定的数,例如23456这个5位数,10000之前的数中包含的个数是确定的了,为f(1)+f(2)+f(3)+f(4),这是一个递归的过程
class Solution:
    def NumberOf1Between1AndN_Solution(self, n):
        # write code here
        res=0
        tmp=n
        base=1
        while tmp:
            last=tmp%10
            tmp=tmp/10
            res+=tmp*base
            if last==1:
                res+=n%base+1
            elif last>1:
                res+=base
            base*=10
        return res
class Solution:
    def NumberOf1Between1AndN_Solution(self, n):
        # write code here
        count=0
        i=1
        while i<=n:
            a=n/i
            b=n%i
            count+=(a+8)/10*i+(a%10==1)*(b+1)
            i*=10
        return count
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值