算法练习 - 排序
练习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