力扣每日一题

一.简单题

1.两数之和

1. 两数之和 - 力扣(LeetCode)

(1)暴力求解

int* twoSum(int* nums, int numsSize, int target, int* returnSize)
{
    int i=0,j=0;
    for(i=0;i<numsSize-1;i++)
    {
        for(j=i+1;j<numsSize;j++)
        {
            if(nums[i]+nums[j]==target)
            {
                int* ret=malloc(sizeof(int)*2);  
                //题目要求返回类型为int*,考虑返回指向数组的指针
                ret[0]=i;
                ret[1]=j;
                *returnSize=2;
                return ret;
            }
        }
    }
    *returnSize=0;
    return NULL;
}

(2)哈希表

2.回文数

9. 回文数 - 力扣(LeetCode)

bool isPalindrome(int x)
{
	if(x<0)
	return false;
    char arr[20],brr[20];
	itoa(x, arr);
	char i = 0,tmp=0;
	int m = strlen(arr);
    strcpy( brr, arr );
	
	for (i = 0; i <=(m - 1)/2; i++)
	{
		tmp = arr[i];
		arr[i] = arr[m - 1 - i];
		arr[strlen(arr) - 1 - i] = tmp;
	}
    int f=strcmp( arr, brr );
    if(f==0)
    return true;
    else
    return false;

}

3.罗马数字转整数

13. 罗马数字转整数 - 力扣(LeetCode)

int romanToInt(char* s)
{
    int n=strlen(s);
    int i=0;
    int sum=0;
    for(i=0;i<n;i++)
    {
        switch(s[i])
        {
            case 'M':
                sum=sum+1000;
                break;
            case 'D':
                sum=sum+500;
                break;
            case 'C':
                if(s[i+1]=='D')
                {
                    sum=sum+400;
                    i++;
                }
                else if(s[i+1]=='M')
                {
                    sum=sum+900;
                    i++;
                }
                else
                {
                    sum=sum+100;
                }
                break;
            case 'L':
                sum=sum+50;
                break;
            case 'X':
                if(s[i+1]=='L')
                {
                    sum=sum+40;
                    i++;
                }
                else if(s[i+1]=='C')
                {
                    sum=sum+90;
                    i++;
                }
                else
                {
                    sum=sum+10;
                }
                break;
            case 'V':
                sum=sum+5;
                break;
            case 'I':
                if(s[i+1]=='V')
                {
                    sum=sum+4;
                    i++;
                }
                else if(s[i+1]=='X')
                {
                    sum=sum+9;
                    i++;
                }
                else
                {
                    sum=sum+1;
                }
                break;
            default:
                break;
        }
    }
    return sum;
}

4.

5. 有效括号

20. 有效的括号 - 力扣(LeetCode)

bool isValid(char * s)
{
    ST st;
    StackInit(&st);
    while(*s)
    {
        if(*s=='('||*s=='['||*s=='{')
        {
            StackPush(&st,*s);//入栈,栈里不存右括号
            s++;
        }
        else
        {
            //遇到右括号了,但是栈里面没有数据,说明前面没有左括号,也要返回flase
            if(StackEmpty(&st))
            {
                StackDestroy(&st);
                return false;
            }
            STDataType top=StackTop(&st);
            StackPop(&st);
            if((*s==')'&&top!='(')||(*s==']'&&top!='[')||(*s=='}'&&top!='{'))
            {
                StackDestroy(&st); //不销毁会导致内存泄漏
                return false;
            }
            else
            {
                s++;
            }
        }
    }
    
    //只要栈不是空,就说明里面还有还有左括号没有被匹配
    bool ret=StackEmpty(&st);
    StackDestroy(&st); //不销毁会导致内存泄漏
    return ret;
}

.相同的树

100. 相同的树 - 力扣(LeetCode)

bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{
    if(p==NULL && q==NULL)
    return true;
    
    if(p==NULL || q==NULL) //这里不能用异或,因为异或是个值运算
    return false;

    if(p->val != q->val)
    return false;

    return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}

经典的前序:先判断根,再是左子树,右子树

.杨辉三角

118. 杨辉三角 - 力扣(LeetCode)

class Solution 
{
public:
    vector<vector<int>> generate(int numRows) 
    {
        vector<vector<int>> vv;
        vv.resize(numRows,vector<int>());  //vector<int>()是用匿名对象来初始化
        for(size_t i=0;i<vv.size();i++)
        {
            vv[i].resize(i+1,0);  //都初始化为0
            vv[i][0]=vv[i][vv[i].size()-1]=1; //每一行的第一个和最后一个都初始化为1
        }
        for(size_t i=0;i<vv.size();i++)
        {
            for(size_t j=0;j<vv[i].size();j++)
            {
                if(vv[i][j]==0)
                {
                    vv[i][j]=vv[i-1][j-1]+vv[i-1][j];
                }
            }
        }
        return vv;
    }
};

vector的嵌套

 

.反转链表

206. 反转链表 - 力扣(LeetCode)

struct ListNode* reverseList(struct ListNode* head)
{
  if(head==NULL)
  {
    return head;
  }
  struct ListNode *n1,*n2,*n3;
  n1=NULL;
  n2=head;
  n3=head->next;
  while(n2)
  {
    n2->next=n1;  //翻转指针

    n1=n2;  //让n1==n2
    n2=n3;   //让n2==n3
    if(n3)
    {
      n3=n3->next;
    }
  }
  return n1;
}

运用三指针的方法,关键是画图

.链表的中间结点

876. 链表的中间结点 - 力扣(LeetCode)

struct ListNode* middleNode(struct ListNode* head)
{
    struct ListNode *fast,*slow;
    fast=head;
    slow=head;
     while(fast!=NULL&&fast->next!=NULL)
     {
         slow=slow->next;
         fast=fast->next->next;
     }
     return slow;
}

运用快慢指针,快指针比慢指针多走一步,最终slow会在head和fast的中间位置

 拓展:找倒数第k个结点


struct ListNode* FindNode(struct ListNode* head,int k)
{
    struct ListNode *fast,*slow;
    fast=head;
    slow=head;
    int i=0;
    for(i=0;i<k;i++)
    {
        if(fast==NULL)  //K大于链表长度,提前结束
        {
            return NULL;
        }
        fast=fast->next;
    }
     while(fast)
     {
         slow=slow->next;
         fast=fast->next->next;
     }
     return slow;
}

也是用快慢指针,不过是fast先走k步;
之后slow与fast一起走,当fast==NULL时,slow指向的是倒数第k个

.合并两个有序链表

21. 合并两个有序链表 - 力扣(LeetCode)

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2)
{
    if(l1==NULL)
    {
        return l2;
    }
    if(l2==NULL)
    {
        return l1;
    }
    //如果其中一个链表为空,返回另一个链表
    struct ListNode *head,*tail;
    head=NULL;
    tail=NULL;
    while(l1&&l2)
    {
        if(l1->val<l2->val)
        {
            if(head==NULL)  //第一次的判断
            {
                head=l1;
                tail=l1;
            }
            else
            {
                tail->next=l1;
                tail=l1;
            }
            l1=l1->next;
        }
        else
        {
            if(head==NULL)  //第一次的判断
            {
                head=l2;
                tail=l2;
            }
            else
            {
                tail->next=l2;
                tail=l2;
            }
            l2=l2->next;
        }
    }
    //连接剩下的
    if(l1)
    {
        tail->next=l1;
    }
    if(l2)
    {
        tail->next=l2;
    }
    return head;
}
依次比较链表结点,每次取小的结点,尾插到新的链表即可

. 回文链表

LCR 027. 回文链表 - 力扣(LeetCode)

bool isPalindrome(struct ListNode* head)
{
    struct ListNode* mid=middleNode(head);
    struct ListNode* rhead=reverseList(mid);

    struct ListNode* cur1=head;  //尽量不要乱动头指针
    struct ListNode* cur2=rhead;

    while(cur1&&cur2)
    {
        if(cur1->val!=cur2->val)
        {
            return false;
        }
        else
        {
            cur1=cur1->next;
            cur2=cur2->next;
        }
    }
    return true;
}

先找到中间结点,然后逆置后面的链表,之后再和前面的链表比较。

.相交链表

LCR 027. 回文链表 - 力扣(LeetCode)

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    struct ListNode* tail1=headA;
    struct ListNode* tail2=headB;
    int len1=1,len2=1; //因为没有把尾算进去,所以初始为一比较好
    while(tail1->next!=NULL)
    {
        len1++;
        tail1=tail1->next;
    }
       while(tail2->next!=NULL)
    {
        len2++;
        tail2=tail2->next;
    }
    if(tail1!=tail2) //最好用地址去比较,用值可能会误判
    {
        return NULL;  //不相交
    }

    int gap=abs(len1-len2);
    struct ListNode* longlist=headA; 
    struct ListNode* shortlist=headB;
    if(len1<len2)  //先假设a长,要是a短的话再交换过来
    {
        longlist=headB;
        shortlist=headA;
    }

    while(gap--)  //长的先走,和短的齐平
    {
        longlist=longlist->next; 
    }
    while(longlist!=shortlist)
    {
        longlist=longlist->next;
        shortlist=shortlist->next;
    }
    return longlist;
}

.环形链表

LCR 027. 回文链表 - 力扣(LeetCode)

bool hasCycle(struct ListNode *head) 
{
    struct ListNode* fast=head;
    struct ListNode* slow=head;
    struct ListNode* A=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)  //当相遇时
        {
            struct ListNode* meet=slow;
            while(A!=meet)
            {
                A=A->next;
                meet=meet->next;
            }
            return meet;
        }
    }
    return NULL;
}

使用快慢指针,快比慢多一步
根据图和公式分析,结论是L==从meet到环入口的距离


法2:

还可以成链表相交求交点

list1:从head到meet (让meet做两个链表的尾巴)
list2:从meet前一个到meet

 

 .用队列实现栈

225. 用队列实现栈 - 力扣(LeetCode)

typedef struct
{
    Queue q1;
    Queue q2;
} MyStack;


MyStack* myStackCreate() 
{
    MyStack* st =(MyStack*)malloc(sizeof(MyStack));
    QueueInit(&st->q1);
    QueueInit(&st->q2);
    return st;
}

void myStackPush(MyStack* obj, int x) 
{
    if(!QueueEmpty(&obj->q1)) //->已经解引用过一次了,所以还是要加&
    {
        QueuePush(&obj->q1,x);
    }
    else
    {
        QueuePush(&obj->q2,x);
    }
}

int myStackPop(MyStack* obj) {
 assert(obj);
 //我们需要判断那个队列是空,则将另一个队列的前n-1个数据进行出队到空队列
 Queue* emptyQ = &obj->q1;
 Queue* noemptyQ = &obj->q2;
 if(!QueueEmpty(&obj->q1))
 {
     emptyQ = &obj->q2; 
     noemptyQ = &obj->q1;
 }


 // 把非空队列的前N个数据,导入空队列,剩下一个删掉
 // 就实现了后进先出
    while(QueueSize(noemptyQ)>1)
    {
        int front =QueueFront(noemptyQ);
        QueuePush(emptyQ,front);
        QueuePop(noemptyQ);
    }
    int top=QueueFront(noemptyQ);  //先保存一下,不然被pop掉找不到数据了
    QueuePop(noemptyQ);
    return top;
}

int myStackTop(MyStack* obj) 
{
	if(!QueueEmpty(&obj->q1))
	{
		return QueueBack(&obj->q1);
	}
	else
	{
		return QueueBack(&obj->q2);
	}
}

bool myStackEmpty(MyStack* obj) 
{
	return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2); //都不为空才行
}

void myStackFree(MyStack* obj) 
{
	QueueDestroy(&obj->q1);
	QueueDestroy(&obj->q2);
	free(obj);
	obj==NULL;
}


核心思路:
1.入数据,往不为空的队列里入数据,保持另外一个队列为空
2.出数据,把前n-1个数据转移到另外一个队列里存起来,把最后一个数据出出去

.用栈实现队列 

typedef struct 
{
    ST pushST;
    ST popST;
} MyQueue;


MyQueue* myQueueCreate() 
{
    MyQueue* q=(MyQueue*)malloc(sizeof(MyQueue));
    StackInit(&q->pushST);
    StackInit(&q->popST);
    return q;
}

void myQueuePush(MyQueue* obj, int x) 
{
    StackPush(&obj->pushST,x);
}

int myQueuePop(MyQueue* obj) 
{
    if(StackEmpty(&obj->popST))
    {
        while(!StackEmpty(&obj->pushST))
        {
            StackPush(&obj->popST,StackTop(&obj->pushST));
            StackPop(&obj->pushST);
        }
    }
    int front=StackTop(&obj->popST);
    StackPop(&obj->popST);
    return front;
}

int myQueuePeek(MyQueue* obj) 
{
    if(StackEmpty(&obj->popST))
    {
        while(!StackEmpty(&obj->pushST))
        {
            StackPush(&obj->popST,StackTop(&obj->pushST));
            StackPop(&obj->pushST);
        }
    }
    return StackTop(&obj->popST);
}

bool myQueueEmpty(MyQueue* obj) 
{
    return StackEmpty(&obj->pushST) && StackEmpty(&obj->popST);
}

void myQueueFree(MyQueue* obj) 
{
    StackDestroy(&obj->pushST);
    StackDestroy(&obj->popST);
    free(obj);  //不要忘了把MyQueue释放掉
    obj==NULL;
}

.单值二叉树

965. 单值二叉树 - 力扣(LeetCode)


bool isUnivalTree(struct TreeNode* root)
{
    if(root==NULL)
    {
        return true;
    }

    if(root->left && root->left->val!=root->val) //跟左子树比较
    {
        return false;
    }
     if(root->right && root->right->val!=root->val) //跟右子树比较
    {
        return false;
    }

    return isUnivalTree(root->left) && isUnivalTree(root->right);

    //不能是
    return isUnivalTree(root->left);
    return isUnivalTree(root->right);
}

每次递归都是比较孩子(子树)与父亲,只要不是单值二叉树,肯定在某个地方孩子与父亲不相等

.对称二叉树 

101. 对称二叉树 - 力扣(LeetCode)

bool _isSymmetric(struct TreeNode* leftRoot,struct TreeNode* rightRoot)
{
    if(leftRoot==NULL && rightRoot==NULL)
    {
        return true;
    }
    if(leftRoot==NULL || rightRoot==NULL)
    {
        return false;
    }

    if(leftRoot->val != rightRoot->val)
    {
        return false;  //最好写题意不满足的条件
    }

    return  _isSymmetric(leftRoot->left,rightRoot->right) 
            && _isSymmetric(leftRoot->right,rightRoot->left);
}

bool isSymmetric(struct TreeNode* root)
{
    return _isSymmetric(root->left,root->right); //当给的函数不合适的时候,可以自己再编一个
}

 .二叉树的前序遍历

144. 二叉树的前序遍历 - 力扣(LeetCode)

int TreeSize(struct TreeNode* root)
{
    return (root==NULL) ? 0 : TreeSize(root->left)+TreeSize(root->right)+1;
}

void _preorder(struct TreeNode* root,int* a,int *i) //递归中传数值,基本都是传址
{
    if(root==NULL)
        return ;
    
    a[(*i)++]=root->val;
    _preorder(root->left,a,i);
    _preorder(root->right,a,i);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize)
{
    *returnSize=TreeSize(root);
    int *a=(int*)malloc((*returnSize)*sizeof(int));

    int i=0;
    _preorder(root,a,&i);  //要保证每个栈帧都只有一个i
    return a;
}

.两个数组的交集

349. 两个数组的交集 - 力扣(LeetCode)

class Solution 
{
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) 
    {
        //排序+去重
        set<int> s1(nums1.begin(),nums1.end());
        set<int> s2(nums2.begin(),nums2.end());

        auto it1=s1.begin();
        auto it2=s2.begin();

        vector<int> v;
        while(it1!=s1.end()&& it2!=s2.end())
        {
            if(*it1<*it2)
            {
                ++it1;
            }
            else if(*it1>*it2)
            {
                ++it2;
            }
            else
            {
                v.push_back(*it1);
                ++it1;
                ++it2;
            }
        }
        return v;
    }
};

 

.字符串中的第一个唯一字符

387. 字符串中的第一个唯一字符 - 力扣(LeetCode)

class Solution 
{
public:
    int firstUniqChar(string s) 
    {
        //用计数来统计次数
        int count[26]={0};
        for(auto ch:s)
        {
            count[ch-'a']++;
        }
        for(int i=0;i<s.size();++i)
        {
            if(count[s[i]-'a']==1)
            {
                return i;
            }
        }
        return -1;
    }  
};

.字符串相加

415. 字符串相加 - 力扣(LeetCode)

class Solution 
{
public:
    string addStrings(string num1, string num2) 
    {
        int end1=num1.size()-1,end2=num2.size()-1;
        int next=0;
        string str;
        
        while(end1>=0||end2>=0)
        {
            int val1=0;
            if(end1>=0)
            {
                val1=num1[end1]-'0';
            }
            int val2=0;
            if(end2>=0)
            {
                val2=num2[end2]-'0';
            }

            int ret=val1+val2+next;
            if(ret>9)
            {
                ret -= 10;
                next=1;
            }
            else
            {
                next=0;
            }
            str.insert(0,1,'0'+ret);
            --end1;
            --end2;
        }
        if(next==1)
        {
            str.insert(0,1,'0'+1);
        }
        return str;
    }
};

//可以用来处理大数相加

 .另一颗树的子树

572. 另一棵树的子树 - 力扣(LeetCode)

bool isSameTree(struct TreeNode* p, struct TreeNode* q) //第100题的函数
{
    if(p==NULL && q==NULL)
    return true;
    
    if(p==NULL || q==NULL) 
    return false;

    if(p->val != q->val)
    return false;

    return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}

bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{
    if(root==NULL)
    {
        return false;
    }

    if(isSameTree(root,subRoot))
    {
        return true;
    }

    return isSubtree(root->left,subRoot) || isSubtree(root->right,subRoot);
    //return isSameTree(root->left,subRoot) || isSameTree(root->right,subRoot) 是错的
}

.根据二叉树创建字符串

606. 根据二叉树创建字符串 - 力扣(LeetCode)

class Solution 
{ 
public:
    string tree2str(TreeNode* root) 
    {
        if(root==nullptr)
            return "";

        string str = to_string(root->val);   //转成字符串类型
        
        if(root->left!=nullptr||root->right!=nullptr)  
        {
            str += '(';
            str += tree2str(root->left);
            str += ')';
        }

        if(root->right!=nullptr)   //判断右边省不省略
        {
        str += '(';
        str += tree2str(root->right);
        str += ')';
        }
        return str;
    }
};

.仅仅反转字母

917. 仅仅反转字母 - 力扣(LeetCode)

bool isletter(char a)
{
    if((a>='a'&&a<='z')||(a>='A'&&a<='Z'))
    {
        return true;
    }
    return false;
}

class Solution 
{
public:

    string reverseOnlyLetters(string s) 
    {
        size_t begin=0;
        size_t end=s.size()-1;

        while(begin<end)
        {
            while(begin<end&&!isletter(s[begin]))
            begin++;

            while(begin<end&&!isletter(s[end]))
            end--;

            swap(s[begin],s[end]);
            begin++;
            end--;
        }
        return s;
    }
};

二.中等题

1.整数反转

7. 整数反转 - 力扣(LeetCode)

int reverse(int x)
{
    int m=0;
    long int sum=0;
    int flag=0;
    if(x<0)
    {
        if(x==-2147483648)
        {
            return 0;
        }
        else
        {
            x=-x;
            flag=1;
        }
    }
    while(x)
    {
        m=x%10;
        sum=sum*10+m;
        x=x/10;
    }
    if(sum>=2147483648||sum<=-2147483648)
    {
        return 0;
    }
    if(flag==1)
    {
        sum=-sum;
    }
    
    return sum;
}

2.链表分割(牛客网)

typedef struct ListNode
{
	int val;
	struct ListNode* next;
}ListNode;

ListNode* partition(ListNode* pHead, int x)
{
	struct ListNode* A_head, * A_tail, * B_head, * B_tail;
	//开一个哨兵卫的头结点,方便之后的分别尾插
	A_head = A_tail = (struct ListNode*)malloc(sizeof(struct ListNode));
	A_tail = NULL;
	B_head = B_tail = (struct ListNode*)malloc(sizeof(struct ListNode));
	B_tail = NULL;

	ListNode* cur = pHead;
	while (cur)
	{
		if (cur->val < x)
		{
			A_tail->next = cur;  //A_tail的下一个指向cur
			A_tail = cur;
		}
		else
		{
			B_tail->next = cur;  //A_tail的下一个指向cur
			B_tail = cur;
		}
		cur = cur->next;  //因为cur没有被改变,所以依然可以继续往下走
	}
	A_tail->next = B_head->next;
	B_tail = NULL;   // 要把b_tail指向空,不然有可能B的最后一个还连着A的下一个呢

	ListNode* head=A_head->next;
	//不要忘了释放内存
	free(A_head);   
	free(B_head);
	return A_head->next;
}

​(这是死循环了)

.电话号码的字母组合

17. 电话号码的字母组合 - 力扣(LeetCode)

class Solution 
{
    string _numToStr[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
public:
    void Combinations(const string& digits,size_t di,string conbineStr,vector<string>& strV)   
//这里用传值是为了往下调用的时候不影响上面的数字
    { 
        if(di==digits.size())
        {
            strV.push_back(conbineStr);
            return;
        }
        int num=digits[di]-'0';
        string str=_numToStr[num];
        for(auto ch:str)
        {
            Combinations(digits,di+1,conbineStr+ch,strV);  
//这里不能是 di++和conbineStr += ch 因为会改变di和conbineStr 
        }

    }
    vector<string> letterCombinations(string digits) 
    {
        vector<string> strV;
        if(digits.size()==0)
        {
            return strV;
        }

        Combinations(digits,0,"",strV);
        return strV;
    }
};

 

.二叉树的层序遍历

102. 二叉树的层序遍历 - 力扣(LeetCode)

class Solution 
{
public:
    vector<vector<int>> levelOrder(TreeNode* root) 
    {
        queue<TreeNode*> q;
        int levelsize=0;
        if(root)  //初始化队列
        {
            q.push(root);
            levelsize=1;
        }

        vector<vector<int>> vv;
        while(!q.empty())
        {
            //通过levelsize控制一层一层的出
            vector<int> v;
            while(levelsize--)
            {
                TreeNode* front=q.front();   //先把要出的保存起来
                q.pop();
                v.push_back(front->val);

                //上一层出完,带出下一层
                if(front->left)
                q.push(front->left);

                if(front->right)
                q.push(front->right);
            }

            vv.push_back(v);
            levelsize=q.size();   //更新下一层数据
        }
        return vv;
    }
};

.从前序与中序遍历构造二叉树

105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)

class Solution 
{
public:
    TreeNode* _buildTree(vector<int>& preorder, vector<int>& inorder,int& peri,int inbegin,int inend)
    {
        if(inbegin>inend)
        {
            return nullptr;
        }

        TreeNode* root=new TreeNode(preorder[peri]);  //用前序找根

        //分割出左右子区间
        //[inbegin,rooti-1],rooti,[rooti+1,inend] 分割成三段区间
        int rooti=inbegin;  //rooti是根在中序序列中的下标
        while(rooti<=inend)
        {
            if(inorder[rooti]==preorder[peri])
            {
                break;   //找到了rooti
            }
            else
            {
                rooti++;
            }
        }
        ++peri;

        root->left=_buildTree(preorder,inorder,peri,inbegin,rooti-1);  //(用左子树区间)递归创建左子树
        root->right=_buildTree(preorder,inorder,peri,rooti+1,inend);
        return root;
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) 
    {
        int i=0;
        return _buildTree(preorder,inorder,i,0,inorder.size()-1);
    }
};

.二叉树的层序遍历Ⅱ

107. 二叉树的层序遍历 II - 力扣(LeetCode)

class Solution 
{
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) 
    {
        queue<TreeNode*> q;
        int levelsize=0;
        if(root)  //初始化队列
        {
            q.push(root);
            levelsize=1;
        }

        vector<vector<int>> vv;
        while(!q.empty())
        {
            //通过levelsize控制一层一层的出
            vector<int> v;
            while(levelsize--)
            {
                TreeNode* front=q.front();   //先把要出的保存起来
                q.pop();
                v.push_back(front->val);

                //上一层出完,带出下一层
                if(front->left)
                q.push(front->left);

                if(front->right)
                q.push(front->right);
            }

            vv.push_back(v);
            levelsize=q.size();   //更新下一层数据
        }

        reverse(vv.begin(),vv.end());   //比102多一句代码

        return vv;
    }
};


关键就是这一句 reverse(vv.begin(),vv.end()),注意reverse值逆置了一维的数组,所以可以这样用

3.复制带随机指针的链表

138. 复制带随机指针的链表 - 力扣(LeetCode)

struct Node* copyRandomList(struct Node* head) 
{
//1.拷贝结点,插入原节点的后面
	struct Node* cur=head;  
    while(cur)
    {
        struct Node* copy=(struct Node*)malloc(sizeof(struct Node));
        copy->val=cur->val;
        //插入copy节点
        copy->next=cur->next;
        cur->next=copy;

        cur=copy->next; //cur移动到下一个原节点
    }

//2.根据原节点,处理copy节点的random
    cur=head;
    while(cur)
    {
        struct Node* copy=cur->next;
        if(cur->random==NULL)
        {
            copy->random=NULL;
        }
        else
        {
            copy->random=cur->random->next;
        }
        cur=copy->next;
    }
//3.取出复制的链表出来
    cur=head;
    struct Node* copyhead=NULL;
    struct Node* copytail=NULL;
    while(cur)
    {
        struct Node* copy=cur->next;
        struct Node* next=copy->next;
        if(copytail==NULL)
        {
            copyhead=copytail=copy;
        }
        else
        {
            copytail->next=copy;
            copytail=copy;
        }
        cur->next=next;  //恢复原链表
        cur=next;
    }
    return copyhead; //别忘了返回
}

最重要的还是画图

.逆波兰表达式求值

150. 逆波兰表达式求值 - 力扣(LeetCode)

class Solution 
{
public:
    int evalRPN(vector<string>& tokens) 
    {
        stack<int> st;
        for(auto& str:tokens)  //一个一个取字符串时,数据量一般比较大,所以加&,不加也不会报错
        {
            if(str=="+"||str=="-"||str=="*"||str=="/")
            {
                int right=st.top();
                st.pop();
                int letf=st.top();
                st.pop();
                switch(str[0])
                {   
                    case '+':
                        st.push(left+right);
                        break;
                    case '-':
                        st.push(left-right);
                        break;
                    case '*':
                        st.push(left*right);
                        break;
                    case '/':
                        st.push(left/right);
                        break;
                }
            }
            else
            {
                st.push(stoi(str));  //先把字符串转整型,在入栈
            }
        }
    }
};

中缀表达式转后缀表达式:

 

  对于括号:   可以定义一个flag,当遇到 “(” 时,把flag=1,这时候括号里的运算符全是最高级,当遇到“)” 时,把flag变回。

.最小栈

155. 最小栈 - 力扣(LeetCode)

class MinStack 
{
public:
    MinStack() 
    {
        
    }


    void push(int val) 
    {
        _st.push(val);
        if(_minst.empty()||val<=_minst.top())
        {
            _minst.push(val);
        }
    }

    
    void pop() 
    {
        if(_minst.top()==_st.top())
        {
            _minst.pop();
        }
        _st.pop();
    }
    
    int top() 
    {
        return _st.top();
    }
    
    int getMin() 
    {
        return _minst.top();
    }

private:
    stack<int> _st;
    stack<int> _minst;
};

.215数组中的第K个最大元素

215. 数组中的第K个最大元素 - 力扣(LeetCode)

class Solution 
{
public:
    int findKthLargest(vector<int>& nums, int k) 
    {
        priority_queue<int> pq(nums.begin(),nums.end());   //用迭代器区间构造
        while(--k)
        {
            pq.pop();
        }
        return pq.top();
    }
};

O(K*logN+N)


法2:
class Solution 
{
public:
    int findKthLargest(vector<int>& nums, int k) 
    {
        priority_queue<int,vector<int>,greater<int>> pq(nums.begin(),nums.begin()+k);  //用堆排的思想,找大数建小堆
        for(size_t i=k;i<nums.size();++i)
        {
            if(nums[i]>pq.top())
            {
                pq.pop();
                pq.push(nums[i]);
            }
        }
        //假设有n个排列好的数据,用前k个建小堆,那么后面n-k个能全部进入堆,那么最小的大数就是第n-k个,也就是堆顶,从n开始倒数第k个。
        return pq.top();
    }
};

O((N-K)*logK)

.二叉树的最近公共祖先

236. 二叉树的最近公共祖先 - 力扣(LeetCode)

class Solution 
{
public:
    bool IsInTree(TreeNode* root, TreeNode* x)
    {
        if(root==nullptr)
            return false;
    
        if(root==x)
            return true;

        return IsInTree(root->left,x)||IsInTree(root->right,x);
        
    }
    
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 
    {
        if(root==nullptr)
        {
            return nullptr;
        }

        if(p==root||q==root)  //如果自己是根的话,那么另一个一定是孩子,自己就是公共祖先
        {
            return root;
        }

        bool pInleft=IsInTree(root->left,p);
        bool pInRight=!pInleft;

        bool qInleft=IsInTree(root->left,q);
        bool qInRight=!qInleft;

        if( pInleft&&qInRight || pInRight&&qInleft)
        {
            return root;
        }
        else if(pInleft&&qInleft)
        {
            return lowestCommonAncestor(root->left,p,q);
        }
        else
        {
            return lowestCommonAncestor(root->right,p,q);
        }

    }    
};

这个的O(N)是n方

法2:用深度搜索找公共路线

class Solution 
{
public:
    bool GetPath(TreeNode* root,TreeNode* x,stack<TreeNode*>& path)
    {
        if(root==nullptr)
        return false;

        path.push(root);   //先入

        if(root==x)  //找到要找的结点了
        return true;

        if(GetPath(root->left,x,path))
        return true;
        
        if(GetPath(root->right,x,path))
        return true;

        path.pop();     //要先把那个错误的路径弹出去
        return false;

    }
    
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 
    {
        stack<TreeNode*> Ppath,Qpath;
        GetPath(root,p,Ppath);
        GetPath(root,q,Qpath);

        while(Ppath.size()!=Qpath.size())
        {
            if(Ppath.size() > Qpath.size())
                Ppath.pop();
            else
                Qpath.pop();
        }

        while(Ppath.top()!=Qpath.top())
        {
            Ppath.pop();
            Qpath.pop();
        }
        
        return Ppath.top();

    }    
};

.设计循环队列

622. 设计循环队列 - 力扣(LeetCode)

(1)链表判满

​ ​ 

(2)数组判满 (rear是下标,开辟空间数==k+1)

typedef struct 
{
    int *a;
    int front;
    int tail;
    int k;
} MyCircularQueue;

bool myCircularQueueIsEmpty(MyCircularQueue* obj) 
{
    return obj->tail==obj->front;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) 
{
    return (obj->tail+1)%(obj->k+1)==obj->front;
}

MyCircularQueue* myCircularQueueCreate(int k) 
{
    MyCircularQueue* obj =(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->a=(int*)malloc(sizeof(int)*(k+1));
    obj->front=obj->tail=0;
    obj->k=k;
    return obj;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) 
{
    if(myCircularQueueIsFull(obj))
    {
        return false;
    }
    obj->a[obj->tail]=value;
    obj->tail++;     //别忘了放完之后,tail才++
    obj->tail=(obj->tail)%(obj->k+1);
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) 
{
    if(myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    obj->front++;
    obj->front=(obj->front)%(obj->k+1);
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) 
{
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    return obj->a[obj->front];
}

int myCircularQueueRear(MyCircularQueue* obj) 
{
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    if(obj->tail==0)
    {
        return obj->a[obj->k];
    }
    else
    {
        return obj->a[obj->tail-1];  //别忘了tail-1,因为push完之后tail要+1;
    } 
        
//  return obj->a[(obj->tail+obj->k)%(obj->k+1)]; 也可以
}

void myCircularQueueFree(MyCircularQueue* obj) 
{
    free(obj->a); //从小往大释放
    free(obj);
}


1.也符合先进先出
2.空间大小固定
3.就结果而言,数组更好用

.前K个高频单词

692. 前K个高频单词 - 力扣(LeetCode)

class Solution 
{
public:
    struct Compare
    {
        bool operator()(const pair<string,int>& kv1,const pair<string,int>& kv2)const
        {
            return kv1.second > kv2.second;
        }
    };

    vector<string> topKFrequent(vector<string>& words, int k)
    {
        map<string,int> countMap;
        for(auto& str:words)
        {
            countMap[str]++;
        }

        vector<pair<string,int>> v(countMap.begin(),countMap.end());  //用迭代器构造
        stable_sort(v.begin(),v.end(),Compare());  //不要用sort,sort不具有稳定性
        
        vector<string> vv;
        for(size_t i=0;i<k;i++)
        {
            vv.push_back(v[i].first);
        }
        return vv;
    }
};


如果不用stable_sort,那么可以通过改变仿函数的比较方式,用sort也行
eg:
struct Compare
{
    bool operator()(const pair<string,int>& kv1,const pair<string,int>& kv2)const
    {
        return kv1.second > kv2.second ||(kv1.second==kv2.second && kv1.first<kv2.first);
    }
};


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

对玛导至昏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值