LeetCode刷题2

这篇博客详细介绍了在LeetCode上的刷题经历,包括链表问题如删除排序链表重复元素,字符串转换整数(atoi),以及多种算法题目如括号生成、二叉树构造、平衡二叉树等。文章还深入探讨了动态规划的解题框架,以求根节点到叶节点数字之和和零钱兑换为例,阐述动态规划的核心要素和状态转移方程的构建过程。
摘要由CSDN通过智能技术生成

0612

力扣刷题1

点这里

力扣刷题2

力扣83题:删除排序链表中的重复元素

版本1:(没用虚拟头结点)

class Solution {
   
public:
    ListNode* deleteDuplicates(ListNode* head) {
   
        //ListNode* preHead = new ListNode(0, head);
        ListNode* cur = head;
        while(cur && cur->next){
   //最少还剩两个节点
        	//两个结点值相等:就往后跳
            if(cur->val == cur->next->val){
   
                cur->next = cur->next->next;
            }
            else{
   //两个结点值不相等
                cur = cur->next;
            }          
        }
        return head;
    }
};

版本2:(用了虚拟头结点)

class Solution {
   
public:
    ListNode* deleteDuplicates(ListNode* head) {
   
        ListNode* preHead = new ListNode(0, head);
        ListNode* cur =  preHead;
        while(cur->next && cur->next->next){
   //链表最少还剩两个结点:
        	//两个结点值相等:从第二个开始删除
            if(cur->next->val == cur->next->next->val){
   
                cur->next->next = cur->next->next->next;
            }
            else{
   //两个结点值不相等:
                cur = cur->next;
            }
        }
        return preHead->next;
    }
};

力扣82题:删除排序链表中的重复元素II

class Solution {
   
public:
    ListNode* deleteDuplicates(ListNode* head) {
   
        ListNode* preHead = new ListNode(0, head);
        ListNode* cur = preHead;
        while(cur->next && cur->next->next){
   //链表最少还剩两个结点:
            //两个结点值相等:循环删掉相同的结点
            if(cur->next->val == cur->next->next->val){
   
                int tmp = cur->next->val;
                while(cur->next && cur->next->val == tmp){
   
                    cur->next = cur->next->next;
                }
            }
            //两个结点值不相等:
            else{
   
                cur = cur->next;
            }
        }
        return preHead->next;
    }
};

力扣第8题:字符串转换整数 (atoi)

剑指offer读书笔记4(面试题53-68)第67题

class Solution {
   
public:
    int myAtoi(string s) {
   
        int n = s.size();
        if(n == 0) return 0;
        //空格:
        int i = 0;
        while(i < n && s[i] == ' '){
   
            ++i;
        } 
        //符号位
        char mark;
        if(s[i] == '+' || s[i] == '-') mark = s[i++];
        //数字
        long num = 0;
        while(i < n && s[i] >= '0' && s[i] <= '9'){
   
            num = num * 10 + (s[i] - '0');
            ++i;
            if(mark == '-'){
   
                if(-num < INT_MIN) 
                    return INT_MIN;
            }
            else{
   
                if(num > INT_MAX) 
                    return INT_MAX; 
            } 
        }
        //返回
        if(mark == '-') num = -num;
        return (int)num;
    }
};

力扣22题:括号生成

dfs+回溯

相当于是深度优先遍历一个满二叉树,把满足左括号个数lc和右括号个数rc同时等于n的情况筛选出来,存到vector<string> res中。

代码1:(这个比较好理解)
(题解见括号生成 | 深度优先遍历 | 最简洁易懂的题解 【c++/java版】

class Solution {
   
    vector<string> res;
    string path;
    int n;
public:
    vector<string> generateParenthesis(int n) {
   
        this->n = n;
        dfs(0, 0);
        return res;
    }
private:
    void dfs(int lc, int rc){
   
        if(lc == n && rc == n){
   //左右括号的个数都刚刚好够
            res.push_back(path);
            return;
        }
        if(lc < n){
   //左括号个数还没够
            path.push_back('(');
            dfs(lc + 1, rc);
            path.pop_back();
        }
        if(rc < n && rc < lc){
   //右括号个数还没够并且少于左括号的个数
            path.push_back(')');
            dfs(lc, rc + 1);
            path.pop_back();
        }
    }
};

代码2:
(题解见虽然不是最秀的,但至少能让你看得懂!下面的评论)

class Solution {
   
    vector<string> res;
    string path;
public:
    vector<string> generateParenthesis(int n) {
   
        //if(n == 0) return {};
        dfs(0, 0, n);
        return res;
    }
private:
    void dfs(int left, int right, int n){
   
        if(left > n || right > left) return;//right > n || left > right
        if(path.size() == n * 2){
    res.push_back(path); return; }
        
        path.push_back('(');
        dfs(left + 1, right, n);
        path.pop_back();

        path.push_back(')');
        dfs(left, right + 1, n);
        path.pop_back();
    }
};

力扣31题:下一个排列

题解见下一个排列算法详解:思路+推导+步骤,看不懂算我输!,代码见它下面的评论。

思路:
从后往前遍历,遇到一个数nums[i]比它前面的数nums[i - 1]大,
从这个数开始到数组结束的部分进行排序,
然后遍历这部分内容,找到第一个比nums[i - 1]大的数nums[j],把二者交换,然后return;
如果遍历完整个数组都没有遇到一个数nums[i]比它前面的数nums[i - 1]大的情况,就说明这个数组是降序的,对它进行排序,然后return;

代码:

class Solution {
   
public:
    void nextPermutation(vector<int>& nums) {
   
        int n = nums.size();
        for(int i = n - 1; i > 0; --i){
   
        	//找到一个比它前面一个数大的数:
            if(nums[i] > nums[i - 1]){
   
            	//迭代器:
                //auto it = nums.end();
                vector<int>::iterator it = nums.end();
                //从nums.end()开始倒着走n - i步:找到指向nums[i]的迭代器
                for(int k = 0; k < n - i; ++k) --it;
                //排序:
                sort(it, nums.end());
                //找到第一个比nums[i - 1]大的数:
                for(int j = 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值