likes
comments
collection
share

专项学习算法之排序

作者站长头像
站长
· 阅读数 8

(注意:以下题目来源牛客)

单链表的排序(简单)

给定一个节点数为n的无序单链表,对其按升序排序。 数据范围:

0<n≤1000000 < n \le 100000 0<n100000

要求:空间复杂度 O(n),时间复杂度 O(nlogn)

class Solution:
    def sortInList(self , head: ListNode) -> ListNode:
        # write code here
        pass 
str1 = list(map(int, input()[1 : -1].split(',')))
str1 = sorted(str1) 
print('{' + ','.join(list(map(str, str1))) + '}')

最小的K个数(中等)

给定一个长度为 n 的可能有重复值的数组,找出其中不去重的最小的 k 个数。例如数组元素是4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4(任意顺序皆可)。 数据范围:

0≤k,n≤100000\le k,n \le 10000 0k,n10000

数组中每个数的大小

0≤val≤10000 \le val \le 1000 0val1000

要求:空间复杂度 O(n) ,时间复杂度 O(nlogn)

# -*- coding:utf-8 -*-
class Solution:
    def GetLeastNumbers_Solution(self, tinput, k):
        # write code here
        list=[]
        if len(tinput)<k:
            return list
        else:
            tinput.sort()
            return tinput[:k]

合并区间(中等)

给出一组区间,请合并所有重叠的区间。 请保证合并后的区间按区间起点升序排列。

数据范围:区间组数

0≤n≤2×1050 \le n \le 2 \times 10^50n2×105

,区间内 的值都满足

0≤val≤2×105 0 \le val \le 2 \times 10^50val2×105

要求:空间复杂度 O(n),时间复杂度 O(nlogn) 进阶:空间复杂度 O(val),时间复杂度O(val)

class Solution:
    def merge(self , intervals: List[Interval]) -> List[Interval]:
        # write code here
        if not intervals:
            return []
        intervals.sort(key=lambda x:x.start)
        res = []
        res.append(intervals[0])
        for i in range(1,len(intervals)):
            last = res[-1]
            cur = intervals[i]
            if last.end<cur.start:
                res.append(cur)
            else:
                last.end = max(last.end, cur.end)
        return res

最大数(中等)

给定一个长度为n的数组nums,数组由一些非负整数组成,现需要将他们进行排列并拼接,每个数不可拆分,使得最后的结果最大,返回值需要是string类型,否则可能会溢出。

数据范围:

1≤n≤100,0≤nums[i]≤100001 \le n \le 100,0 \le nums[i] \le 10000 1n1000nums[i]10000

进阶:时间复杂度O(nlogn) ,空间复杂度:O(n)

基本思路: 1、每次将相邻的两个字符串拼接,然后比大小,从而确定相邻的两个字符串是否交换位置。 2、如果排序好的数组第一个元素就是“0”,那么结果直接返回字符串“0”。 3、如果第一个元素不是“0”,直接从头到尾拼接返回就好了。


class cmp(str):
    def __lt__(x, y):
        # 子字符串正反拼接的结果判断(注意是字符串)
        return x+y > y+x
class Solution:
    
    def solve(self , nums: List[int]) -> str:
        # write code here
        # 1. 转换为字符串
        nums = [str(n) for n in nums]
        # 2. 排序
        # 相邻两个字符串正反拼接,将大数放在最前面
        nums = sorted(nums, key=cmp)
        if nums[0] == '0':
            return '0'
        else:
            return ''.join(nums)

栈和排序(中等)

给你一个 1 到 n 的排列和一个栈,并按照排列顺序入栈

你要在不打乱入栈顺序的情况下,仅利用入栈和出栈两种操作,输出字典序最大的出栈序列

排列:指 1 到 n 每个数字出现且仅出现一次

数据范围:

1≤n≤5×1041 \le n \le 5 \times 10^41n5×104

排列中的值都满足

1≤val≤n1 \le val \le n1valn

进阶:空间复杂度 O(n) ,时间复杂度 O(n)

设计思想: 1、因为要满足字典序最大,所以第一个出栈的一定是n,所以我们需要定义一个n来控制元素的出栈顺序; 2、为了满足字典序最大我们还得知道哪些元素已经入了栈,因为n-1有可能在n之前就入了栈了, 所以我们需要编辑数组来知道哪些较大的数据入栈(因为这些数据可以提前出栈), 那么我们就遍历数据通过n和标记数组来空竹出战的顺序; 3、如果数据遍历完,栈还没有空,我们只能将栈中元素全部弹出。

专项学习算法之排序

class Solution:
    def solve(self , a: List[int]) -> List[int]:
        # write code here
        s = [] #定义一个栈用来存储数据(我们用数组来模拟)
        n  = len(a)
        res = []#用来返回结果
        vis = [0] *(n+1)#用来标记哪个数字出现过
        for i in a:
            s.append(i)#压入栈
            vis[i] = 1#压入一个数就把对应的数字标记为1
            while n and vis[n]: n-=1#检测现有栈中有多少个数出现了就是较大的哪些数出现了(从大到小)
            while s and n <= s[-1]:
                #然后将栈中>=n的元素出栈
                res.append(s[-1])
                s.pop()
        #如果栈没为空就按照栈中原样直接出栈
        while s:
            res.append(s[-1])
            s.pop()
        return res

数据流中的中位数(中等)

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

数据范围:数据流中数个数满足

1≤n≤10001 \le n \le 1000 1n1000

大小满足

1≤val≤10001 \le val \le 1000 1val1000

进阶: 空间复杂度 O(n) , 时间复杂度 O(nlogn)

堆排序思想: 中位数为一个数列的中间两个或一个,也即中位数将数列分成了较小的部分和较大的部分。我们可以维护两个堆,分别是大顶堆min,用于存储较小的值,其中顶部最大;小顶堆max,用于存储较小的值,其中顶部最小,则中位数只会在两个堆的堆顶出现。我们可以约定奇数时取大顶堆的顶部值,偶数时取两堆顶的平均值,则可以发现两个堆的数据长度要么是相等的,要么奇数时大顶堆会多一个。 每次输入的数据流先进入大顶堆排序,然后将小顶堆的最大值弹入大顶堆中,完成整个的排序。但是因为大顶堆的数据不可能会比小顶堆少一个,因此需要再比较二者的长度,若是小顶堆长度小于大顶堆,需要从大顶堆中弹出最小值到大顶堆中进行平衡。

import heapq
class Solution:
    def __init__(self):
        self.maxheapq=[]  # 大堆:存放小于中位数的元素(奇数时包含中位数)
        self.minheapq=[]  # 小堆:存放大于中位数的元素
    def Insert(self, num):
        # write code here
        if len(self.maxheapq)==len(self.minheapq):
            heapq.heappush(self.minheapq,-heapq.heappushpop(self.maxheapq,-num))
        else:
            heapq.heappush(self.maxheapq,-heapq.heappushpop(self.minheapq,num))
    def GetMedian(self):
        # write code here
        if len(self.maxheapq)==len(self.minheapq):
            return (self.minheapq[0]-self.maxheapq[0])/2
        return self.minheapq[0]

链表的奇偶重排

给定一个单链表,请设定一个函数,将链表的奇数位节点和偶数位节点分别放在一起,重排后输出。 注意是节点的编号而非节点的数值。

数据范围:节点数量满足

0≤n≤1050 \le n \le 10^50n105

节点中的值都满足

0≤val≤1000 0 \le val \le 10000val1000

要求:空间复杂度 O(n),时间复杂度 O(n)

专项学习算法之排序

class Solution:
    def oddEvenList(self, head: ListNode) -> ListNode:
        if not head:
            return head
        
        evenHead = head.next
        odd, even = head, evenHead
        while even and even.next:
            odd.next = even.next
            odd = odd.next
            even.next = odd.next
            even = even.next
        odd.next = evenHead
        return head

转载自:https://juejin.cn/post/7072541724110749726
评论
请登录