LeetCode刷题记录(持续更新中...)

有效的括号

利用栈解决问题:

class Solution {
public:
    bool isValid(string s) {
        stack<char> stack;
        int len=s.length();
        if(len==0){
            return false;
        }
        stack.push('#');
        for(int i=0;i<len;i++){
            if((stack.top()=='('&&s[i]==')')||(stack.top()='['&&s[i]==']')||(stack.top()=='{'&&s[i]=='}')){
                stack.pop();
            }else{
                stack.push(s[i]);
            }
        }
        if(stack.top()=='#'){
            return true;
        }
        else{
            return false;
        }
    }
};

两数之和

这是比较简单的暴力遍历

//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int length=nums.length;
        for(int i=0;i<length;i++){
            for(int j=i+1;j<length;j++){
                if(nums[i]+nums[j]==target){
                     int[] result= {i,j};
                     return result;
                }
            }
        }
        return null;
    }
}
//leetcode submit region end(Prohibit modification and deletion)

评论中有大佬给出了用hash表的做法,属实想不到,学到了学到了...

反转链表

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* pre=NULL;
        ListNode* cur=head;
        while(cur!=NULL){
            ListNode* next=cur->next;
            cur->next=pre;
            pre=cur;
            cur=next;
        }
        return pre;
    }
};

总结:这题是使用双指针很好的一个例子,虽然是easy题但是还是很有价值的。

合并两个有序链表

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* dummy =new ListNode(0);
        ListNode* newList = dummy;
        while(l1!=NULL&&l2!=NULL){
            if(l1->val<l2->val){
                newList->next=l1;
                l1=l1->next;
            }
            else if(l1->val>=l2->val){
                newList->next=l2;
                l2=l2->next;
            }
            newList=newList->next;
        }
         if(l1!=NULL){
             newList->next=l1;
         }else if(l2!=NULL){
             newList->next=l2;
         }
        return dummy->next;
    }
};

总结,这题跟上一题让我对什么时候创建新节点以及什么时候直接使用节点有了更深刻的认识

删除排序链表中的重复节点

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if(head==NULL){
            return NULL;
        }
        ListNode* newHead=new ListNode(0);
        ListNode* p=newHead;
        ListNode* newVal1=new ListNode(head->val);
        p->next=newVal1;
        p=newVal1;
        while(head!=NULL){
            //p->next=head;
            if(head->val==p->val){
                head=head->next;

            }else{
                ListNode* newVal=new ListNode(head->val);
                p->next=newVal;
                p=newVal;
                head=head->next;
            }


            //head=head->next;
        }
        return newHead->next;
    }
};

我每次都开辟了一个新的节点,空间复杂度跟时间复杂度应该都是o(n)...其实是有点浪费空间的

环形链表

这题用的快慢指针,很好很强大,又get到一个

class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode* low=head;
        ListNode* high=head;
        int num=0;
        while(high!=NULL&&high->next!=NULL){
            high=high->next->next;
            low=low->next;
            num++;
            if(low==high){
                return true;
            }
        }
        //return 
        return false;
    }
};

其实这题用集合存储应该更简单一点,但是奈何c++集合实现啥的还没学到....

这题还有一个第二版,就是返回环的入口点在哪,其实感觉更像是数学了...

移除链表元素

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {

        while (NULL  != head && head->val == val)
         head = head->next;
        if(head==NULL) return NULL;
        ListNode* newHead=head;
        ListNode* pre=head;
        while(head->next!=NULL){
            head=head->next;
            if(head->val==val){
                pre->next=head->next;
                head=pre;
            }else{
                pre=head;
            }
        }
        return newHead;
    }
};

这题我一开始没想到怎么处理边界问题,想了半天感觉太复杂,后来看了一眼答案,让我把while (NULL != head && head->val == val) head = head->next;抄了过来,直接把一开始的问题给特殊处理掉就行。

相交链表

说来惭愧,这题其实复习考研的时候遇到过...但是现在还是看了别人的答案😂俺是真的菜

这题原理就是a+b+c=c+b+a

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(headA==NULL||headB==NULL)return NULL;
        ListNode* l1=headA;
        ListNode* l2=headB;
        while(l1!=l2){
            l1=l1?l1->next:headB;
            l2=l2?l2->next:headA;
        }

        return l1;
}

回文链表

这题主要采用用数组存值,然后比较即可,不过这样空间复杂度很高

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        vector<int> vec;
        ListNode* cur=head;
        while(cur){
            vec.push_back(cur->val);
            cur=cur->next;
        }
         for (int i = 0, j = vec.size() - 1; i < j; i++, j--) {
            if (vec[i] != vec[j]) return false;
        }
        return true;
    }
};

到现在为止,lc上的链表简单题基本上刷完了,收获最大的就是双指针的使用!

相同的树

class Solution {
public:
    bool isSameTree(TreeNode* p, 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);
    }
};

这题用递归很简单,也稍微打消了一点对树的恐惧哈

对称二叉树

递归实现:

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(root==NULL)return true;
        return cmp(root->left,root->right);
    }

    bool cmp(TreeNode* left,TreeNode* right){
        if(left==NULL&&right==NULL)return true;
        if(left==NULL||right==NULL||left->val!=right->val)return false;
        return cmp(left->left,right->right)&&cmp(left->right,right->left);
    }
};

借用这题整理一下递归实现的思路。递归问题主要出现在何时找到递归点。
对于本题:1. 怎么样才能算是true呢?两种情况,第一种当根节点为空那么必定对称,第二种左树的左值与右树的右值相同且左树的右值与右树的左值相同,递归点:在尝试判断左树与右树对称的条件时,发现其跟两树的孩子的对称情况有关系。

二叉树的最大深度

class Solution {
public:
    int maxDepth(TreeNode* node) {
        if (node == NULL) return 0;
        int leftDepth = maxDepth(node->left);       // 左
        int rightDepth = maxDepth(node->right);     // 右
        int depth = 1 + max(leftDepth, rightDepth); // 中
        return depth;
    }
};

路径之和

class Solution {
    public boolean hasPathSum(TreeNode root, int sum) {
        if (root == null) {
            return false;
        }
        // 到达叶子节点时,递归终止,判断 sum 是否符合条件。
        if (root.left == null && root.right == null) {
            return root.val == sum;
        }
        // 递归地判断root节点的左孩子和右孩子。
        return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
    }
}

我摊牌了,这题是抄来的... 欸好久没看书,忘得就差不多了

posted @ 2021-01-04 19:14  four1er  阅读(104)  评论(0)    收藏  举报