Schwertlilien
As a recoder: notes and ideas.

刷题日记-3

Q1-合并k个排序列表⚠️⚠️⚠️

暴力解法:直接把所有的列表全部合并,然后用sort(),其时间复杂度是$O(n\log n)$

Q2-反转链表

link

话说我写这个题的时候,非常靠直觉?一开始写的是return curr;然后报错,然后就先改成了prev,提交通过。然后通过了之后开始想,为什么return prev是对的:应该是走到最后的时候curr=nullptr了,反倒是prev才存的是最后一个节点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* prev=head;
ListNode* curr=head;
while(curr!=nullptr){
ListNode* tmp=nullptr;
if(curr->next!=nullptr)tmp=curr->next;
if(prev==curr)curr->next=nullptr;
else curr->next=prev;
prev=curr;
curr=tmp;
}
return prev;
}
};

Q3-使数组和能被p整除

link

思路:我得到前缀和数组 s,遍历 curr,找一个最靠近 curr 的 prev,使得 (s[curr] - s[prev]) % p == x, 也就是 s[prev] % p == (s[curr] - x + p) % p,用 curr - prev 更新最小长度。

TLE版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

复杂度分析
class Solution {
public:
int minSubarray(vector<int>& nums, int p) {
bool flag=false;
int min_cnt=nums.size();
int x=0;
for(int i=0;i<nums.size();i++){
x=(x+nums[i]%p)%p;
}
if(x==0)return 0;

for(int i=0;i<nums.size();i++){
int y=0;
int cnt=0;
for(int j=i;j<nums.size();j++){
y+=nums[j];cnt++;
cout<<"y: "<<y<<" p:"<<p<<" x:"<<x<<" cnt:"<<cnt<<" min cnt:"<<min_cnt<<endl;
if(y%p==x&&cnt!=nums.size()){
flag=true;
if(cnt<min_cnt)min_cnt=cnt;
}
}
}
if(!flag)return -1;
else return min_cnt;
}
};

AC版本:卡在了为什么要加hash表last很长时间,最后大概理解了随循环的话,每一步添加或者是修改了对应的前缀和的值,使得得到的是prev_sum[prev],然后现在遍历prev_sum[curr]是否存在。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public:
int minSubarray(vector<int>& nums, int p) {
vector<int> prev_sum(nums.size()+1);
prev_sum[0]=0;
int x=0;
for(int i=0;i<nums.size();i++){
x=(x+nums[i]%p)%p;
prev_sum[i+1]=x;
}
if(x==0)return 0;
int ans=nums.size();
unordered_map<int,int> last;
for(int i=0;i<nums.size()+1;i++){
auto it=last.find((prev_sum[i]-x+p)%p);
if(it!=last.end()){
ans=min(ans,i-it->second);
}
last[prev_sum[i]]=i;
}
return ans<nums.size()?ans:-1;
}
};

33.搜索旋转排序数组

link

思路:重点在于mid的一侧一定是有序的。而且有nums[l]>num[r]必然成立。需要注意的是在有序的判定后,target可能等于nums[r]/nums[l],千万不要遗漏这种情况。这个题还是我上次面试做的。。上次就没搞清楚边界条件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
int search(vector<int>& nums, int target) {
int l=0;
int r=nums.size()-1;
while(l<=r){
int m=(l+r)/2;
if(target==nums[m])return m;
if(nums[m]>=nums[l]){
//mid左边有序
if(target>=nums[l]&&target<nums[m])r=m-1;
else l=m+1;
}
else {
//mid右边有序
if(target>nums[m]&&target<=nums[r])l=m+1;
else r=m-1;
}
}
return -1;
}
};
搜索
匹配结果数:
未搜索到匹配的文章。