算法练习
来源:互联网 发布:程序员工作心得体会 编辑:程序博客网 时间:2024/05/16 05:16
算法练习 - 排序
练习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