题目描述1
笔者解答1.1
class Solution {
public String findLongestWord(String s, List<String> d) {
PriorityQueue<String> queue=new PriorityQueue<>((o1,o2)->{
if(o1.length()==o2.length()){
return o1.compareTo(o2);
}else{
return o2.length()-o1.length();
}
});
if(s.length()==0)return "";
int n=d.size();
int i;
for(i=0;i<n;i++){
queue.offer(d.get(i));
}
String str="";
n=s.length();
while(!queue.isEmpty()){
String temp_str=queue.poll();
int k=0;
int j=0;
for(;j<temp_str.length();j++){
for(;k<n;k++){
if(temp_str.charAt(j)==s.charAt(k))break;
}
if(k==n&&j!=temp_str.length()-1)break;
}
if(j==temp_str.length())return temp_str;
}
return str;
}
}
笔者分析1.2
这次代码还有最后几个用例没有通过,不太明白为什么,而且感觉自己的算法虽然在每个字符串比较前排了序,可以较快的找到合适的字符串,但是在单一字符串每个字符验证的时候,算法过于笨拙,时间复杂度太高,哎,求助评论区。等下,下面这个AC的算法好像和我思路是一样的。。。。而且看最后执行数据的话,好像也还不错。!
class Solution {
public String findLongestWord(String s, List<String> d) {
Collections.sort(d);
String res = "";
for(String word:d){
if(check(s,word)&&word.length()>res.length()){
res = word;
}
}
return res;
}
/*利用双指针法判断子串*/
public boolean check(String s,String p){
char[] ss = s.toCharArray();
char[] pp = p.toCharArray();
int i=0,j=0;
while(i<ss.length&&j<pp.length){
if(pp[j]==ss[i])
j++;
i++;
}
return j==pp.length;
}
}
题目描述2
笔者分析2.1
可能开始看到这道题时,会觉得特别简单,我也是这么认为的,不就是用个优先遍历序列,再新建一个链表头结点,把堆中的结点弹出来就行么。但当我看到这道题,评论和题解数量都快破千的时候,才意识到这题里大有学问,有意思的 不是如何把这题写出来,而是如何更巧妙的写出来。
归并排序(递归法)
- 题目要求空间复杂度分别为O(nlogn)和O(1),根据事件复杂度我们自然想到二分法,从而联想到归并排序;
- 对数组做归并排序的空间复杂度为O(nlogn),分别由新开辟数组O(n)和递归递归函数调用O(logn)组成,而根据链表特性:数组额外空间:链表可以通过修改应用来更改节点顺序,无需像数组一样开辟额外空间;递归额外空间:递归函数将带来O(logn)的空间复杂度,因此若希望达到O(1)空间复杂度,则不能使用递归。
- 通过递归实现链表归并排序,有以下两个环节:
- 分割cut环节:当找到当前链表中点,并从中点将链表断开(以便在下次递归cut时,链表片段拥有正确边界);我们使用fast,slow快慢双指针法,奇数个结点找到中点,偶数个结点找到中心左边的结点;找到中点slow后,执行slow.next=None将链表切断;递归分割时,输入当前链表左端点head和中心结点slow的下一个结点tmp(因为链表是从slow切断的);cut递归终止条件:当head.next==None时,说明只有一个结点了,直接返回此结点。
- 合并merge环节:将两个排序链表合并,转化为一个排序链表。双指针法合并,建立辅助ListNode h作为头部;设置两指针left,right分别指向两链表头部,比较两指针处结点值大小,由小到大加入合并链表头部,指针交替前进,直至添加完两个链表;返回辅助ListNode h作为头部的下一个结点h.next;时间复杂度O(l+r),l,r分别代表两个链表长度。
- 当题目输入的head==None时,直接返回None.
public ListNode sortList(ListNode head){
//1.递归结束条件
if(head==null||head.next==null)
return head;
//2.找到链表中间结点并断开链表&递归下探
ListNode midNode=middleNode(head);
ListNode rightHead=midNode.next;
midNode.next=null;
ListNode left=sortList(head);
ListNode right=sortList(rightHead);
//3.当前层业务操作(合并有序链表)
return mergeTwoLists(left,right);
}
//找到链表中间结点
private ListNode middleNode(ListNode head){
if(head==null||head.next==null){
return head;
}
ListNode slow=head;
ListNode fast=head.next.next;
while(fast!=null&&fast.next!=null){
slow=slow.next;
fast=fast.next.next;
}
return slow;
}
//合并两个有序链表
private ListNode mergeTwoLists(ListNode l1,ListNode l2)
{
ListNode sentry=new ListNode(-1);
ListNode curr=sentry;
while(L1!=null&&l2!=null){
if(l1.val<l2.val){
curr.next=l1;
l1=l1.next;
}else{
curr.next=l2;
l2=l2.next;
}
curr=curr.next;
}
curr.next=l1!=null?l1:l2;
return sentry.next;
}
总结
感觉自己变懒了,虽然打卡不会停止,但热情没有刚开始的高了。可是,如果你想体会到真正的快乐,那就请给它多点时间,每日打卡第十一天,以下图为证