题意:给一个链表,删除从尾数起的第n个结点,返回头节点。
指针到最后,数出来有多少个,之从前向后数,再删掉节点
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode * p=head;int sz=0;
while(p!=NULL){
cout<val<next; sz++;
}
p=head; int ta=sz-n;
if(ta==0){
head=p->next;delete p;p=NULL; return head;
}
for(int i=1;inext;
ListNode * q=p->next;
p->next=q->next;
delete q;
p=q=NULL;
return head;
}
};
双指针,类似追及问题的那种
第一个指针和第二个指针指向head,让第一个指针先跑n个结点,之后第一个指针和第二个指针一起跑,直到第一个指针跑到尾,这时第二个指针就是倒数第n个结点了,删除第二个指针指向的结点就可以了
注意第一个指针为空的情况单独讨论
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode * fr=head;ListNode * se=head;
for(int i=1;i<=n;i++) fr=fr->next;
if(fr==NULL){
head=head->next;
delete se; se=NULL;
return head;
}
while(fr->next!=NULL){
fr=fr->next;se=se->next;
}
fr=se->next; se->next=fr->next;
delete fr;fr=NULL;
return head;
}
};
题意:括号合法问题
用栈看看合不合法
好像空间复杂度没办法在当前的时间复杂度下优化了
class Solution {
public:
bool isValid(string s) {
stack st;
for(int i=0;i
题意:把两个有序链表合成一个有序链表
就直接合成
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l, ListNode* r) {
ListNode* ans=NULL;ListNode* m=ans;
if(l!=NULL&&r==NULL){return l;}
else if(l==NULL&&r!=NULL){return r;}
else if(l==NULL&&r==NULL){return ans;}
while(l!=NULL&&r!=NULL){
if((l->val)<=(r->val)){
if (m==NULL){ans=m=l;l=l->next;}
else {m->next=l;m=m->next;l=l->next;}
}
else{
if (m==NULL){ans=m=r;r=r->next;}
else {m->next=r;m=m->next;r=r->next;}
}
}
if(l!=NULL){m->next=l;}
else if(r!=NULL){m->next=r;}
return ans;
}
};
题意:给出括号数,生成所有可能性
递归,当右括号数用完的时候跳出递归,同时时刻注意左括号数一定要 大于等于 右括号数
class Solution {
public:
void solve(int n,int l,int r,vector &ans,string &output){
if(r==n){ans.push_back(output);return;}
if(l>=r&&lr){
output.push_back(')');
solve(n,l,r+1,ans,output);
output.pop_back();
}
}
vector generateParenthesis(int n) {
if(n==0) return {};
int l=0,r=0;vector ans;string output;
solve(n,l,r,ans,output);
return ans;
}
};
看了看答案 除了递归 还有动态规划的做法,有点像矩阵连乘的动态规划
将问题看成重叠子问题,假设dp[i]包含所有长度为2*i的可能性,例如dp[2]为{ (()) , ()() },那么dp[3]可以被写成:
(
+ dp[0] +)
+ dp[2] =()(()),
()()()
(
+ dp[1] +)
+ dp[1] =(())()
(
+ dp[2] +)
+ dp[0] =((())),
(()())
从上面可以看出,这是个重叠子问题结构(其个数为卡特兰数)
状态转移函数为dp[i] = "(" + dp[j] + ")" + dp[i-j-1]
接下来从数据结构的角度来说,答案在dp[n]中,dp[n]是vector
之后就可以写代码了 注意初始化怎么写!!!
class Solution {
public:
vector generateParenthesis(int n) {
vector< vector > dp(n+1);//开辟空间
dp[0]={""};//初始化
for(int i=1;i<=n;i++){//动态规划中的n
for(int j=0;j
题意:你有一个链表组,排序成一个链表
递归,两个两个合并,有种归并排序的意思,但是代码能不能写出来就不知道了呜呜呜;
还有注意链表为空的情况!想了想之前有两个链表排序的例子,不知道能不能用上
但是递归完后,合成的链表放在哪里呢?那就新开一个vector ans,把之前的list clear一下(?)
每个拿到手的list,如果到手的就一个内容return;到手是1个以上,分成【l, r/2】【r/2+1,r】每个函数返回的应该是一个链表,ans把上面两个返回量收集一下,之后合并函数,最后返回一个链表
不会写!!感觉就差一点,但已知runtime error 没办法了;只好写个顺序版的了呜呜呜
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l, ListNode* r) {
ListNode* ans=NULL;ListNode* m=ans;
if(l!=NULL&&r==NULL){return l;}
else if(l==NULL&&r!=NULL){return r;}
else if(l==NULL&&r==NULL){return ans;}
while(l!=NULL&&r!=NULL){
if((l->val)<=(r->val)){
if (m==NULL){ans=m=l;l=l->next;}
else {m->next=l;m=m->next;l=l->next;}
}
else{
if (m==NULL){ans=m=r;r=r->next;}
else {m->next=r;m=m->next;r=r->next;}
}
}
if(l!=NULL){m->next=l;}
else if(r!=NULL){m->next=r;}
return ans;
}
ListNode* mergeKLists(vector& lists) {
if (lists.size()==0){return NULL;}
else if (lists.size()==1){return lists[0];}
for(int i = 1; i < lists.size(); i++){
lists[0] = mergeTwoLists(lists[0],lists[i]);
}
return lists[0];
}
};
首先先把[0, n-1],[1, n-2],[2, n-3],[3, n-4]…[n/2-1,n-n/2] 配对合并,把链表放在前者里面,之后合法长度变为(n+1)/2;
以上流程循环,直到n<=1;
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l, ListNode* r) {
ListNode* ans=NULL;ListNode* m=ans;
if(l!=NULL&&r==NULL){return l;}
else if(l==NULL&&r!=NULL){return r;}
else if(l==NULL&&r==NULL){return ans;}
while(l!=NULL&&r!=NULL){
if((l->val)<=(r->val)){
if (m==NULL){ans=m=l;l=l->next;}
else {m->next=l;m=m->next;l=l->next;}
}
else{
if (m==NULL){ans=m=r;r=r->next;}
else {m->next=r;m=m->next;r=r->next;}
}
}
if(l!=NULL){m->next=l;}
else if(r!=NULL){m->next=r;}
return ans;
}
ListNode* mergeKLists(vector& lists)
{
int n=lists.size();
if(lists.size()==0) return NULL;
while(n>1){
for(int i=0;i
mergeTwoLists函数和mergeKLists函数都差不多,重点在于sol是怎么实现的?
哦哦对照了一下,好像是在递归的时候传参传错了
正确的应该是:
int mid=l+(r-l)/2;
ListNode* a=sol(l,mid,lists);
ListNode* b=sol(mid+1,r,lists);我写的错误版本是:
ListNode* a=sol(l,r/2,lists);
ListNode* b=sol(r/2+1,r,lists);为什么我写的是错误的呢?
假设lists的内容是0 1 2 3
0 1 2 3
00 11 21 23
会出现以上错误,也就是说,当l=2,r=3的时候会出现错误!!所以要用mid来解决
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l, ListNode* r) {
ListNode* ans=NULL;ListNode* m=ans;
if(l!=NULL&&r==NULL){return l;}
else if(l==NULL&&r!=NULL){return r;}
else if(l==NULL&&r==NULL){return ans;}
while(l!=NULL&&r!=NULL){
if((l->val)<=(r->val)){
if (m==NULL){ans=m=l;l=l->next;}
else {m->next=l;m=m->next;l=l->next;}
}
else{
if (m==NULL){ans=m=r;r=r->next;}
else {m->next=r;m=m->next;r=r->next;}
}
}
if(l!=NULL){m->next=l;}
else if(r!=NULL){m->next=r;}
return ans;
}
ListNode* sol(int l,int r,vector& lists){
if(l>=r)return lists[l];
int mid=l+(r-l)/2;
ListNode* a=sol(l,mid,lists);
ListNode* b=sol(mid+1,r,lists);
return mergeTwoLists(a,b);
}
ListNode* mergeKLists(vector& lists) {
if (lists.size()==0){return NULL;}
return sol(0,lists.size()-1,lists);
}
};
首先创建一个链表指针的优先队列q,接着把list的头指针都放进去,如果q是空的,那么就返回空;创建答案链表的头指针,头指针指向当前堆顶的最小元素,把堆顶元素弹出,如果答案指针之后还有元素,那么就把答案指针的next放回堆中;
创建一个用于答案链表插入的尾指针,尾指针指向堆顶元素,堆顶元素弹出,尾指针指向next元素;如果尾指针next不为空,并放回堆中,直到优先队列q空了,循环停止,这时答案链表也形成了。
class Solution {
public:
struct compare {
bool operator()(const ListNode* l, const ListNode* r) {
return l->val > r->val;
}
};
ListNode *mergeKLists(vector &lists) { //priority_queue
priority_queue, compare> q;
for(auto l : lists) {
if(l) q.push(l);
}
if(q.empty()) return NULL;
ListNode* result = q.top();
q.pop();
if(result->next) q.push(result->next);
ListNode* tail = result;
while(!q.empty()) {
tail->next = q.top();
q.pop();
tail = tail->next;
if(tail->next) q.push(tail->next);
}
return result;
}
};
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
ofstream out("user.out");
vector buf;
constexpr size_t buf_size = 1e4;
buf.resize(buf_size);
out.rdbuf()->pubsetbuf(buf.data(), buf_size);
vector result;
result.reserve(1e4);
string in;
while (getline(cin, in)){
result.clear();
for (size_t i = 0, s = size(in); i < s; ++i){
const char c = in[i];
const bool is_num = (c >= '0') && (c <= '9') || (c == '-');
if (!is_num){
continue;
}
else{
char* off;
result.push_back(strtol(&in[i], &off, 10));
i += (off - &in[i]);
}
}
sort(begin(result), end(result));
out << '[';
for (size_t i = 0, s = size(result); i < s; ++i) {
if (0 != i)
out << ',';
out << result[i];
}
out << "]\n";
}
}
#define main _
class Solution{
public:
ListNode *mergeKLists(vector &lists) { return nullptr; }
};