牛客刷题day9(排序,寻找峰值,求平方根,合并K个已经排序的链表,字符串的排列,输出二叉树右视图,单链表的排序,出现次数topk的问题)

牛客刷题day9

1.排序

题目

给定一个数组,请你编写一个函数,返回该数组排序后的形式。

解题思路

关于排序,请看专题排序专栏

核心代码

关于排序代码,请看专题排序专栏

2.寻找峰值

题目

山峰元素是指其值大于或等于左右相邻值的元素。给定一个输入数组nums,任意两个相邻元素值不相等,数组可能包含多个山峰。找到索引最大的那个山峰元素并返回其索引。
假设 nums[-1] = nums[n] = -∞。
输入:[2,4,1,2,7,8,4]
返回值:5

解题思路

因为要求索引值最大的峰值,所以从末尾遍历数组,找到的第一个符合条件的值即索引最大。

核心代码
class Solution:
    def solve(self , a ):
        # write code here
        len_a = len(a)
        for i in range(len_a-1,-1,-1):
            if a[i]>a[i-1]:
                return i

3.求平方根

题目

实现函数 int sqrt(int x).
计算并返回x的平方根(向下取整)

解题思路

二分法

核心代码
class Solution:
    def sqrt(self, x):
        if x <= 1: return x

        left = 1
        right = x

        while left <= right:
            mid = left + (right - left) // 2
            if mid * mid > x:
                right = mid - 1
            elif mid * mid < x:
                left = mid + 1
            else:
                return mid

        return right

4.合并K个已排序的链表

题目

合并 k 个已排序的链表并将其作为一个已排序的链表返回。分析并描述其复杂度。
输入:[{1,2,3},{4,5,6,7}]
返回值:{1,2,3,4,5,6,7}

解题思路

1.递归解决
这道题目最容易想到的做法是,使用合并两个有序链表中的方法,合并两个有链表,融合前两个链表,将下一个链表与当前结果融合,遍历列表中的每个链表,不断循环下去。但是这种方法时间复杂度很高,我们考虑用二分法把列表进行中间拆分,将列表都拆成长度相等的两个列表,然后融合每个小列表中的链表即可。这样就可以将K级别的融合计算量转换为log(K)级别。
2.最小堆
主要是利用最小堆方法,用一个大小为K的最小堆(用优先队列+自定义降序实现)(优先队列就是大顶堆,队头元素最大,自定义为降序后,就变成小顶堆,队头元素最小),先把K个链表的头结点放入堆中,每次取堆顶元素,然后将堆顶元素所在链表的下一个结点加入堆中

核心代码
1.递归解决
class Solution:
	# 将链表拆分成两个长的链表,递归拆分
    def mergeKLists(self, lists):
        lenLists = len(lists)
        if lenLists == 0:
            return None
        if lenLists == 1:
            return lists[0]
        if lenLists == 2:
            return self.mergeTwoLists(lists[0], lists[1])
        mid = lenLists // 2
        left = self.mergeKLists(lists[:mid])
        right = self.mergeKLists(lists[mid:])
        return self.mergeTwoLists(left, right)
	# 将两个链表合成一个链表
    def mergeTwoLists(self, list1, list2):
        if not list1:
            return list2
        if not list2:
            return list1
        mergeTwoList = ListNode(0)
        res = mergeTwoList
        while list1 and list2:
            if list1.val <list2.val:
                mergeTwoList.next =list1
                mergeTwoList = mergeTwoList.next
                list1 = list1.next
            else:
                mergeTwoList.next = list2
                mergeTwoList = mergeTwoList.next
                list2 = list2.next
        if list1:
            mergeTwoList.next = list1
        if list2:
            mergeTwoList.next =list2
            
        return res.next

2.最小堆
class Solution:
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        import heapq
        dump= ListNode(0)
        p = dump
        head = []
        #首先将每个链表表头放入最小堆中
        for i in range(len(lists)):
            if lists[i] :
                heapq.heappush(head, (lists[i].val, i))
                lists[i] = lists[i].next
        while head:
            val, idx = heapq.heappop(head)
            #取出最小堆的值,放在链表第一位
            p.next = ListNode(val)
            p = p.next
            # 将取出链首元素新链表链首放入堆中,直到堆为空
            if lists[idx]:
                heapq.heappush(head, (lists[idx].val, idx))
                lists[idx] = lists[idx].next
        return dump.next

5.字符串的排列

题目

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则按字典序打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
示例1
输入 “ab” 返回值 [“ab”,“ba”]

解题思路

1.递归解决

2.python 自带库itertools.permutations

核心代码
1.基于回溯思想
class Solution:
    def Permutation(self, ss):
        # write code here
        res = []
        if len(ss) == 0:
            return []
        if len(ss) == 1:
            return [ss]
        self.helper(ss, res, '')
        return sorted(list(set(res)))

    def helper(self, ss, res, path):
        if len(ss) == 1:
            res.append(path + ss[0])
        else:
            for i in range(len(ss)):
                self.helper(ss[:i] + ss[i + 1:], res, path + ss[i])
2.python自带库
import itertools
class Solution:
    def Permutation(self, ss):
        # write code here
        if not ss:
            return []
        arr = sorted(set(list(map(''.join,itertools.permutations(ss)))))
        return arr

6.输出二叉树右视图

题目

请根据二叉树的前序遍历,中序遍历恢复二叉树,并打印出二叉树的右视图
输入
[1,2,4,5,3],[4,2,5,1,3]
返回值
[1,3,5]

解题思路

本题总体可拆分为两部分:
根据先序、中序遍历重构二叉树
层序遍历二叉树输出每层最右侧元素

核心代码
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


class Solution:
    def solve(self, xianxu, zhongxu):
        root = self.buildTree(xianxu, zhongxu)
        return self.printRightTree(root)

    def buildTree(self, xianxu, zhongxu):
        if len(xianxu) < 1 and len(zhongxu) < 1:
            return None
        root = TreeNode(xianxu[0])
        root_index = zhongxu.index(root.val)
        root.left = self.buildTree(xianxu[1:root_index + 1], zhongxu[:root_index])
        root.right = self.buildTree(xianxu[root_index + 1:], zhongxu[root_index + 1:])
        return  root

    def printRightTree(self,root):
        res =[]
        queue =[root]
        while queue:
            curLevel=[]
            nextLevel =[]
            for node in queue:
                curLevel.append(node.val)
                if node.left:
                    nextLevel.append(node.left)
                if node.right:
                    nextLevel.append(node.right)
            queue=nextLevel
            res.append(curLevel[-1])
        return res
    

7.单链表的排序

题目

给定一个无序单链表,实现单链表的排序(按升序排序)。
输入:[1,3,2,4,5]
返回值:{1,2,3,4,5}

解题思路

1.常规思路
先将链表转为数组,对数组进行排序,最后再将已经排序的数组转成链表
2.利用归并排序
首先使用快慢指针,把链表切割成两部分。然后在递归调用将单链表切分成单个单个的结点
最后好戏上场,逐个的去拼接left 和 right 递归回来的链表,按照从小到大从左到右的 顺序把 链表拼接上去

核心代码
1.常规思路
class Solution:
    def sortInList(self , head ):
        # write code here
        if not head:
            return head
        cur =head
        valList =[]
        while cur:
            valList.append(cur.val)
            cur = cur.next
        valList.sort()
        List = ListNode(0)
        p=List
        for i in valList:
            node =ListNode(i)
            p.next = node
            p = p.next
        return List.next
2.归并排序
class Solution:
    def sortInList(self , head ):
        if head is None&nbs***bsp;head.next is None:
            return head
        # cut is used to cut down list
        cut = head
        # use 
        slow = head
        fast = head
        # find mid node
        while fast and fast.next:
            cut = slow
            slow = slow.next
            fast = fast.next.next
        left = head
        right = cut.next
        cut.next = None
        left = self.sortInList(left)
        right = self.sortInList(right)
        return self.merge(left, right)
         
    def merge(self, left, right):
        guard = ListNode(0)
        p = guard
        while left and right:
            if left.val < right.val:
                guard.next = left
                left = left.next
            else:
                guard.next = right
                right = right.next
            guard = guard.next
        # append remain list
        if left:
            guard.next = left
        if right:
            guard.next = right
        return p.next

8.出现次数top K的问题

题目

给定String类型的数组strArr,再给定整数k,请严格按照排名顺序打印 出次数前k名的字符串。
如果strArr长度为N,时间复杂度请达到O(N \log K)O(NlogK)

输出K行,每行有一个字符串和一个整数(字符串表示)。
你需要按照出现出现次数由大到小输出,若出现次数相同时字符串字典序较小的优先输出

在这里插入图片描述

解题思路

创建字典,用字典存储数组元素出现的次数
然后对字典根据出现的次数进行排序,最后根据条件将k个元素输出

核心代码
class Solution:
    def topKstrings(self , strings , k ):
        # write code here
        hashTable = dict()
        for s in strings:
            if s in hashTable:
                hashTable[s] += 1
            else:
                hashTable[s] = 1
        res = []
        for key, value in sorted(hashTable.items(), key = lambda kv:(-kv[1], kv[0]))[:k]:
            res.append([key, value])
        return res

写在后面

博主创作不易,无论是找资料还是写代码都是需要花费时间和精力的,茫茫人海,如果你看到了我的博客,觉得写的还行的话,希望能点赞支持一下,让我更有创作的动力。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值