算法练习 - 排序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28057541/article/details/72511657

算法练习 - 排序


练习1 LeetCode - 524. Longest Word in Dictionary through Deleting

class Solution(object):

    # 对链表排序
    # 时间复杂度要求:O(nlogn)
    # 空间:常量空间

    # 数据结构:链表
    # 排序算法:归并

    def sortList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """

    # 子程序 ifcanbeformed:判断 str_o 是否可以通过删除一些字符来得到 str_n

    # 输入:str_o,str_n
    # 返回:true,false
    def ifcanbeformed(self,str_o,str_n):
    # 设 str_n_index = 0
        str_n_index = 0
    # 遍历 str_o,标识i:
        for i in range(len(str_o)):
    #     如果 str_o[i] == str_n[str_n_index]:
            if str_o[i] == str_n[str_n_index]:
    #         str_n_index++
                str_n_index+=1
    #     如果str_n_index == str_n.length:
            if str_n_index == len(str_n):
    #         返回 true
                return True
    # 返回false
        return False

    # 子程序 lexOrderMaxString(s1,s2):

    # 输入:两个相等长度的字符串
    # 返回: 其中字典序排列较大的那个

    def lexOrderMaxString(self,s1,s2):
        # 遍历 i to s1.length:
        for i in range(len(s1)):
        #     如果s1[i] > s2[i]:
            if s1[i] < s2[i]:
        #         那么返回s1
                return s1
        #     如果s1[i] < s2[i]:
            if s1[i] > s2[i]:
        #         那么返回s2
                return s2
        # 遍历完都一样,返回 s1    
        return s1




    # 子程序 findLongestWord: 
    # 输入:字符串s 字符集合d
    # 返回:d中最长的,可以通过s删除一些字符串得到的那个字符串

    def findLongestWord(self,s,d):
        # max_length = MIN
        max_length = -sys.maxsize - 1
        # max_str = 空字符串
        max_str = ''
        # 遍历d,string:
        for string in d:
        #     如果 判断当前的可以formed:
            if self.ifcanbeformed(s,string):
        #         如果 max_length < str.length:
                if max_length < len(string):
        #             max_length = str.length
                    max_length = len(string)
        #             max_str = str
                    max_str = string
        #       如果 长度相当,则要根据字典序来判断
                if max_length == len(string):
                    max_str = self.lexOrderMaxString(max_str,string)
        # 返回str
        return max_str

练习2 LeetCode - 75. Sort Colors

    # 输入:一个数组,只包含0,1,2三个数
    # 返回:排好序的数组

    # 要求,计数排序,本地

    def sortColors(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        count = [0,0,0]
        for i in nums:
            if i == 0:
                count[0]+=1
            elif i == 1:
                count[1]+=1
            elif i == 2:
                count[2]+=1
        index = 0
        for c in range(len(count)):
            if c == 0:
                for j in range(count[c]):
                    nums[index] = 0
                    index+=1
            elif c == 1:
                for j in range(count[c]):
                    nums[index] = 1
                    index+=1
            elif c == 2:
                for j in range(count[c]):
                    nums[index] = 2
                    index+=1

练习3 LeetCode - 274. H-Index

class Solution(object):
    # 一个科学家发布了一组论文,论文的文献引用数为[3,0,6,1,5]
    # h-index的定义是有h篇论文至少有h个引用,其余的论文的引用数都小于h篇

    # 输入:citations 表示这组论文的引用数
    # 输出:h-index(如果有多个index,那么输出最大的那个)

    def hIndex(self, citations):
        # 使用快排对数组进行原地降序排序 O(nlgn)
        citations = sorted(citations,reverse=True)
        # sums 表示对应论文比它大的论文数有多少个,长度和citations相同
        sums = [0]*len(citations)
        # h_index为 0
        h_index = 0
        # 遍历 citations,指标为i:
        for i in range(len(citations)):
        #     如果 i 为 0:
            if i == 0:
        #         sums[i] = i
                sums[i] = 1
        #     否则:
            else:
        #         sums[i] = sums[i-1]+1
                sums[i] = sums[i-1]+1
        #     如果 sums[i] >= citations[i]:
            if sums[i] <= citations[i]:
        #         如果 h_jndex < citations[i]:
                if h_index < sums[i]:
        #             h_jndex = citations[i]
                    h_index = sums[i]
        # 返回 h_index
        return h_index

练习4 LeetCode - 147. Insertion Sort List

以下是通过操作节点来实现插入排序的,但是对应最大的测试用例超时了

class Solution(object):

    # 使用插入排序来岁链表进行排序
    # 输入:head 表头
    # 输入:排序后的表头
    def insertionSortList(self, head):
        # 如果head为空,或者为1,那么直接返回
        if head == None:
            return None
        if head.next == None:
            return head
        # node2 = head.next,head和之后分离
        node2 = head.next
        head.next = None
        # 当 node2 不为空,则循环:
        while node2 != None:
        #     tempnode2指向node2,node2向后移动
            tempnode2 = node2
            node2 = node2.next
        #     设 node1 为 head
            node1 = head
        #     当 node1 不为空,则循环:
            while node1 != None:
        #         tempnode1  = node1
                tempnode1 = node1
        #         node1 = node1.next
                node1 = node1.next
        #         判断tempnode1和tempnode2的值,一共有4种情况需要插入:
        #         头之前,中间,尾巴,或者不插
        #         插入的3种情况
        #         1. 如果 tempnode1 == head,且 tempnode1 大于 tempnode2,tempnode2要插在tempnode1之前:
                if (tempnode1.val==head.val)and(tempnode1.val>tempnode2.val):
                    tempnode2.next = tempnode1
                    head = tempnode2
                    break
        #         2. 如果tempnode1 小于 tempnode2,且tempnode1已经是链表的最后一个,tempnode2直接插入tempnode1之后
                elif (tempnode1.val <= tempnode2.val)and(tempnode1.next == None):
                    tempnode1.next = tempnode2
                    tempnode2.next = None
                    break
        #         3. 如果tempnode1 小于 tempnode2,且tempnode1.next大于tempnode2,tempnode2插在tempnode1和tempnode1.next之间
                elif (tempnode1.val <= tempnode2.val)and(tempnode1.next.val > tempnode2.val):
                    tempnode2.next = tempnode1.next
                    tempnode1.next = tempnode2
                    break
        # 返回head
        return head

其实也可以直接对node中值进行置换

class Solution(object):

    # 使用插入排序来岁链表进行排序
    # 输入:head 表头
    # 输入:排序后的表头
    def insertionSortList(self, head):
        # 如果head为空,或者为1,那么直接返回
        if head == None:
            return None
        if head.next == None:
            return head
        # 设node为head的下一个
        node = head.next
        # 如果node不为空,则循环
        while node != None:
        #     val 为 node的值
            val = node.val
        #     设node2为head
            node2 = head
        #     如果 node2 != node 循环:
            while node2 != node:
        #         如果node<node2,则:
                if val < node2.val:
        #            跳出
                    break
                else:
                    node2 = node2.next
        #     node后移
            node = node.next
        #     如果 node2 != node1 循环:
            while node2 != node:
        #         交换val和node2数值
                temp = val
                val = node2.val
                node2.val = temp
                node2 = node2.next
        # 返回head
        return head

不过同样会超时间,官网对这道题python时间要求的讨论LeetCode讨论

同样的算法使用java可以通过

public class Solution {
    public ListNode insertionSortList(ListNode head) {
        if(head == null){
            return null;
        }
        if(head.next == null){
            return head;
        }
        ListNode node = head.next;
        while(node!=null){
            int val = node.val;
            ListNode node2 = head;
            while(node2!=node){
                if(val<node2.val){
                    break;
                } else {
                    node2 = node2.next;
                }
            }
            node = node.next;
            while(node2!=node){
                int temp = val;
                val = node2.val;
                node2.val = temp;
                node2 = node2.next;
            }
        }
        return head;
    }
}

练习5 LeetCode - 56. Merge Intervals

class Solution(object):

    def merge(self, intervals):
        """
        :type intervals: List[Interval]
        :rtype: List[Interval]
        """
        # 一开始 排除错误输入
        if len(intervals) < 1:
            return intervals
        # 首先根据组合的开始位置,对所有组合进行排序 O(nlgn),在python3中,cmp参数被移除了
        intervals = sorted(intervals,key=lambda interval:interval.start)
        # 设 res 为返回的列表
        res=[]
        cur = Interval(0,0)
        cur.start = intervals[0].start
        cur.end = intervals[0].end
        # 遍历排好序的list:
        for i in range(1,len(intervals)):
        #     如果当前interval可以和下一个interval重合:
            if (cur.end+intervals[i].end-cur.start-intervals[i].start)>=(intervals[i].end-cur.start):
        #         当前interval = 前后的结合
                cur.end = max(intervals[i].end,cur.end)
        #     否则:
            else:
        #         res中添加当前的interval
                res.append(cur)
        #         新建一个interval等于下一个interval
                cur = Interval(intervals[i].start,intervals[i].end)
        # 将最后一个填入res,返回res
        res.append(cur)
        return res

练习6 LeetCode - 148. Sort List

class Solution(object):
    # 时间:O(nlgn)
    # 空间:O(1)
    # 那肯定是分治,这个好歹算是个快排了
    def sortList(self, head):
        # 如果head为空,返回空
        if head == None:
            return None
        # 如果当前head之后next为空,也就是只有一个节点,直接返回head
        if head.next == None:
            return head
        # 分解部分
        # 设val等于head的value
        val = head.val
        # 设 h1 为小于head的节点头,
        h1 = None
        h1_index = None
        # 设 h2 为大于head的节点头
        h2 = None
        h2_index = None
        # 设 hm 为等于head的节点头
        hm = head
        index = head.next
        hm.next = None
        # 遍历链表,将链表分为重新分为三个部分:h1,h2,hm
        while index!=None:
            temp = index
            index = index.next
            temp.next = None
            # 小于val的节点,插入h1
            if temp.val < val:
                # 如果h1为空,则h1指向当前节点,h1_index也指向当前节点
                if h1 == None:
                    h1 = temp
                    h1_index = temp
                # 否则将h1_index下一个指向temp节点,并且h1_index指向下一个
                else:
                    h1_index.next = temp
                    h1_index = h1_index.next
            # 大于等于val的节点,插入h2
            elif temp.val >= val:
                # 和上面的对应相同
                if h2 == None:
                    h2 = temp
                    h2_index = temp
                else:
                    h2_index.next = temp
                    h2_index = h2_index.next
        # 对h1,h2递归的进行排序
        h1 = self.sortList(h1)
        h2 = self.sortList(h2)
        # 将h1,hm,h2组合在一起,并返回总链的头部
        if h1 != None:
            h1_index =  h1
            while h1_index.next!=None:
                h1_index = h1_index.next
            h1_index.next = hm
            hm.next = h2
            return h1
        else:
            hm.next = h2
            return hm

算法还是超时了,使用归并

class Solution(object):
    # 时间:O(nlgn)
    # 空间:O(1)
    # 那肯定是分治,同样是分治,使用归并

    # 子程序 merge
    def merge(self,h1,h2):
        # 输入两个头结点 h1,h2
        h = None
        h_index = None
        # 循环两个节点,直到其中一个为空
        h1_index = h1
        h2_index = h2
        while h1_index!=None and h2_index!=None:
            small = None
            if h1_index.val < h2_index.val:
                small = h1_index
                h1_index = h1_index.next
                small.next = None
            else:
                small = h2_index
                h2_index = h2_index.next
                small.next = None
            if h == None:
                h = small
                h_index = small
            else:
                h_index.next = small
                h_index = h_index.next
        # 1空了就用2补,2空了就用1补
        if h1_index == None:
            h_index.next = h2_index
        else:
            h_index.next = h1_index
        return h
    # 返回并好的 h


    # 输入 head
    # 输出 head
    def sortList(self, head):
        # 基本情况:为空的时候,直接返回空;当head之后没有节点的时候,直接返回节点
        if head == None or head.next == None:
            return head
        # 如果有两个节点,则直接返回一个排列好的
        if head.next.next == None:
            if head.val > head.next.val:
                head.val,head.next.val = head.next.val,head.val
            return head
        # 分解
        # 找到链表的头和中间,使用快慢指针的方式
        # 令fast,slow都为head
        fast = head
        slow = head
        # 当fast自身不为空,或之后也不为空的时候循环:
        while fast!=None and fast.next!=None:
        #     show后移一位
            slow = slow.next
        #     fast后移两位
            fast = fast.next.next
        # 将链表从中间分为两个部分头部分别为h1,h2,也就是h1 = head,h2 = slow.next
        h1 = head
        h2 = slow.next
        # 同时断开链表 slow.next 设为空
        slow.next = None
        # 对h1,h2递归的进行排序
        h1 = self.sortList(h1)
        h2 = self.sortList(h2)
        # 合并h1,h2为head,# 返回head
        head = self.merge(h1,h2)
        return head

猜你喜欢

转载自blog.csdn.net/qq_28057541/article/details/72511657