数据结构与算法Python版 MOOC 第七周 作业

1 快速排序主元(10分)

题目内容:

著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元(中值),通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。 给定划分后的N个互不相同的非负整数的排列,请问有多少个元素可能是划分前选取的主元?

例如给定的排列是[1, 3, 2, 4, 5]。则:

  • 1 的左边没有元素,右边的元素都比它大,所以它可能是主元;

  • 尽管 3 的左边元素都比它小,但其右边的 2 比它小,所以它不能是主元;

  • 尽管 2 的右边元素都比它大,但其左边的 3 比它大,所以它不能是主元;

类似原因,4 和 5 都可能是主元。

因此,有 3 个元素可能是主元。

输入格式:

一行数个整数的排列,由空格分隔

输出格式:

在第 1 行中输出有可能是主元的元素个数;在第 2 行中按递增顺序输出这些元素,其间以 1 个空格分隔,行首尾不得有多余空格(若元素个数为0则第二行为一行空行)。

输入样例:

1 3 2 4 5

输出样例:

3

1 4 5

def compare(lst): #遍历第i个数n,左边都小于n,右边都大于n
    def comp(lst): 
        res=[]
        lstMax=lst[0]
        for i in range(len(lst)):
            if lst[i]>=lstMax:
                res.append(i)
                lstMax=lst[i]
        return res
    temp1=comp(lst)  #向右侧遍历、再向左侧遍历,时间复杂度为O(n)
    temp2=[len(lst)-i-1 for i in comp([-x for x in lst][::-1])][::-1]
    return  list(set(temp1) & set(temp2))

lst=[int(x) for x in input().split()]
ans=sorted(compare(lst))
print(len(ans))
print(' '.join([str(lst[i]) for i in ans]))

2 第一个坏版本(10分)

题目内容:

现在有同一个产品的N个版本,编号为从1至N的整数;其中从某个版本之后所有版本均已损坏。现给定一个函数isBadVersion,输入数字N可判断该版本是否损坏(若损坏将输出True);请找出第一个损坏的版本。

注:有时isBadVersion函数运行速度很慢,请注意优化查找方式

输入格式:

两行

第一行为整数,为产品号总数N

第二行为给定的判断函数,使用有效的Python表达式给出,可使用eval读取

输出格式:

一行数字,表示第一个损坏的版本

输入样例:

50

lambda n:n>=30

输出样例:

30

def firstBadVersion(n):
    low,high=0,n
    while low<high:
        mid=(low+high)//2
        if isBadVersion(mid):
            high=mid
        else:
            low=mid
        if low+1==high:
            return high
    return mid
    
N = int(input())
isBadVersion = eval(input())
print(firstBadVersion(N))

3 插入与归并(10分)

题目内容:

给出如下定义:

插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。

归并排序进行如下迭代操作:首先将原始序列看成 N 个只包含 1 个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下 1 个有序的序列。

现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?

输入格式:

两行由空格分隔的数字,其对应长度相等的列表

其中第一行代表未排序的列表,第二行是排序算法过程中某一步的中间列表

输出格式:

首先在第 1 行中输出Insertion Sort表示插入排序、或Merge Sort表示归并排序;然后在第 2 行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行首尾不得有多余空格

输入样例:

3 1 2 8 7 5 9 4 0 6

1 3 2 8 5 7 4 9 0 6

输出样例:

Merge Sort

1 2 3 8 4 5 7 9 0 6

输入样例2:

3 1 2 8 7 5 9 4 6 0

1 2 3 7 8 5 9 4 6 0

输出样例2:

Insertion Sort

1 2 3 5 7 8 9 4 6 0

def mergeSort(lst):
    step=1
    answers=[]
    while step<len(lst):
        low=0
        ans=[]
        while low<=len(lst):
            high=low+step*2
            mid=low+step
            res=[]
            lstlow=lst[low:mid]
            lsthigh=lst[mid:high]
            while lstlow and lsthigh:  
                if lstlow[0]<lsthigh[0]:
                    res.append(lstlow.pop(0))
                else:
                    res.append(lsthigh.pop(0))
            res.extend(lstlow if lstlow else lsthigh)
            low+=step*2
            ans+=res
        lst=ans
        answers.append(ans) 
        step*=2
    return res,answers

def judge(lst,raw):
    i=1
    while raw[i]>raw[i-1]:
        i+=1
    if raw[i:]==lst[i:]:
        return 'Insertion Sort',i
    else:
        return 'Merge Sort',i

lst=input().split()
raw=input().split()
kind , pos=judge(lst,raw)

if kind=='Insertion Sort':#插入排序
    j=pos
    while raw[j]<raw[j-1] and j>0:
        raw[j],raw[j-1]=raw[j-1],raw[j]
        j-=1
    output=raw
else:  #归并排序
    res,answers=mergeSort(raw)
    output=answers[answers.index(raw)+1]
print(kind)
print(' '.join(output))

这道题有一个样例提示结果错误,之后再研究。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值