DailyPractice.2023.10.14

文章目录

  • 1.[53. 最大子数组和]
  • 2.[142. 环形链表 II]
  • 3.[2. 两数相加]
  • 4.[19. 删除链表的倒数第 N 个结点]
  • 5.[21. 合并两个有序链表]
  • 6.[102. 二叉树的层序遍历]
  • 7.[104. 二叉树的最大深度]
  • 8.[17. 电话号码的字母组合]
  • 9.[46. 全排列]

1.[53. 最大子数组和]

53. 最大子数组和

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        // 1. dp[i] 包括下标i(以nums[i]为结尾)的最大连续子序列和为dp[i]
        // 2. dp[i] = max(nums[i],dp[i - 1] + nums[i]);  dp[i - 1] + nums[i],即:nums[i]加入当前连续子序列和
        // nums[i],即:从头开始计算当前连续子序列和
        // 3.  从递推公式可以看出来dp[i]是依赖于dp[i - 1]的状态,dp[0]就是递推公式的基础。
        // 4. 1 - n
        // 5. 方程
        if (nums.size() == 0) return 0;
     
        vector<int> dp(nums.size(),0);
        
        dp[0] = nums[0];
        int result = dp[0];
        for (int i = 1; i < nums.size(); i++) {
            dp[i] = max(dp[i - 1] + nums[i],nums[i]);
            if (result < dp[i]) {result = dp[i];}
        }
        return result;
    } 
};

时间复杂度: O ( N ) O(N) O(N)
空间复杂度: O ( 1 ) O(1) O(1)

2.[142. 环形链表 II]

142. 环形链表 II

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        if (head == nullptr || head -> next == nullptr)  return nullptr;
        while (fast && fast -> next) {
            fast = fast -> next -> next;
            slow = slow -> next;
            if (fast == slow) {
                ListNode* index1 = slow;
                ListNode* index2 = head;
                while (index1 != index2) {
                    index1 = index1 -> next;
                    index2 = index2 -> next;
                }
                return index2;
        }
        
    }
    return nullptr;
    }
};

时间复杂度: O ( N ) O(N) O(N)
空间复杂度: O ( 1 ) O(1) O(1)

3.[2. 两数相加]

2. 两数相加

/**
/**
 * 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* addTwoNumbers(ListNode* l1, ListNode* l2) {
        
        ListNode* dummy = new ListNode(-1);
        ListNode* cur = dummy;
        ListNode* cur1 = l1;
        ListNode* cur2 = l2;
        int t = 0;
        while (cur1 || cur2 || t) {
            if (cur1) {
                t += cur1 -> val;
                cur1 = cur1 -> next;
            }
            if (cur2) {
                t += cur2->val;
                cur2 = cur2 -> next;
            }
            cur -> next = new ListNode(t % 10);
            cur = cur -> next;
            t /= 10;

        }
        return dummy -> next;
    }
};

时间复杂度: O ( m a x ( m , n ) ) O(max(m,n)) O(max(m,n)),其中 m和 n分别为两个链表的长度。我们要遍历两个链表的全部位置,而处理每个位置只需要 O(1) 的时间。
空间复杂度: O ( 1 ) O(1) O(1)

4.[19. 删除链表的倒数第 N 个结点]

19. 删除链表的倒数第 N 个结点

/**
 * 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* removeNthFromEnd(ListNode* head, int n) {
        if (head == nullptr || n == 0) return nullptr;

        ListNode* dummy = new ListNode(-1);
        dummy -> next = head;
        ListNode* x = findListNode(dummy,n + 1);
        x -> next = x -> next -> next;
        return dummy -> next;
    }
    ListNode* findListNode(ListNode* head,int k) {
        ListNode* slow = head;
        ListNode* fast = head;
        while (k -- && fast) {
            fast = fast -> next;
        }
        while (fast) {
            slow = slow -> next;
            fast = fast -> next;
        }
        return slow;
    }
};

时间复杂度: O ( L ) O(L) O(L),其中 L 是链表的长度。
空间复杂度: O ( 1 ) O(1) O(1)

5.[21. 合并两个有序链表]

21. 合并两个有序链表

lass Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if (list1 == nullptr) return list2;
        if (list2 == nullptr) return list1;
        ListNode* dummy = new ListNode(-1);
        ListNode* cur = dummy;
        ListNode* cur1 = list1;
        ListNode* cur2 = list2;
        while (cur1 && cur2) {
            if (cur1 -> val > cur2 -> val) {
                cur -> next = cur2;
                cur2 = cur2 -> next;
            }
            else {
                cur -> next = cur1;
                cur1 = cur1 -> next;
            }
            cur = cur -> next;
        }
        if (cur1) cur -> next = cur1;
        if (cur2) cur -> next = cur2;
        return dummy -> next;
    }
};

时间复杂度: O ( n + m ) O(n+m) O(n+m),其中 n 和 m 分别为两个链表的长度。因为每次循环迭代中,l1 和 l2 只有一个元素会被放进合并链表中, 因此 while 循环的次数不会超过两个链表的长度之和。所有其他操作的时间复杂度都是常数级别的,因此总的时间复杂度为 O(n+m)。

空间复杂度: O ( 1 ) O(1) O(1)。我们只需要常数的空间存放若干变量。

6.[102. 二叉树的层序遍历]

102. 二叉树的层序遍历

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        queue<TreeNode*> q;
        if (root == nullptr) return res;
        q.push(root);
        while (q.size()) {
            vector<int> temp;
            int size = q.size();
            for (int i = 0; i < size; i++) {
                auto t = q.front();
                temp.push_back(t -> val);
                q.pop();
                if (t -> left) q.push(t -> left);
                if (t -> right) q.push(t -> right);
            }
            res.push_back(temp);
        }
        return res;
     }
};
  • 时间复杂度 O(N) : N 为二叉树的节点数量,即 BFS 需循环 N 次。
  • 空间复杂度 O(N) : 最差情况下,即当树为平衡二叉树时,最多有 N/2 个树节点同时在 queue 中,使用 O(N)大小的额外空间。

7.[104. 二叉树的最大深度]

104. 二叉树的最大深度

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int maxDepth(TreeNode* root) {
        if(root == nullptr) return 0;
        return max(maxDepth(root -> left),maxDepth(root -> right)) + 1;
    }
};
  • 时间复杂度 O(N) : N 为二叉树的节点数量,即 BFS 需循环 N 次。
  • 空间复杂度 O(N) : 最差情况下,即当树为平衡二叉树时,最多有 N/2 个树节点同时在 queue 中,使用 O(N)大小的额外空间。

8.[17. 电话号码的字母组合]

17. 电话号码的字母组合

class Solution {
public:
const string letterMap[10] = {
        "", // 0
        "", // 1
        "abc", // 2
        "def", // 3
        "ghi", // 4
        "jkl", // 5
        "mno", // 6
        "pqrs", // 7
        "tuv", // 8
        "wxyz", // 9
};
vector<string> result;
string s;
    void process(int index,string digits) {
        if (index == digits.size()) {
            result.push_back(s);
            return ;
        }
        int digit = digits[index] - '0';
        string letters = letterMap[digit];
        for (int i = 0; i < letters.size(); i++) {
            s.push_back(letters[i]);
            process(index + 1,digits);
            s.pop_back();
        }
    }
    vector<string> letterCombinations(string digits) {
        if (digits.size() == 0) {
            return result;
        }
        process(0,digits);
        return result;
    }
};

时间复杂度: O ( 3 m × 4 n ) O(3^m×4^n) O(3m×4n)

空间复杂度: O ( m + n ) O(m+n) O(m+n),其中 m 是输入中对应 3 个字母的数字个数,n 是输入中对应 4 个字母的数字个数,m+n是输入数字的总个数。除了返回值以外,空间复杂度主要取决于哈希表以及回溯过程中的递归调用层数,哈希表的大小与输入无关,可以看成常数,递归调用层数最大为 m+n。

9.[46. 全排列]

46. 全排列

class Solution {
public:
vector<vector<int>> res;
vector<int> path;
    void process(int index,vector<int>& nums,vector<bool> &used) {
        if (path.size() == nums.size()) {
            res.push_back(path);
            return;
        }
        for (int i = 0; i < nums.size(); i++) {
            if (used[i] == false) {
                used[i] = true;
                path.push_back(nums[i]);
                process(index + 1,nums,used);
                used[i] = false;
                path.pop_back();
            }
        }
    }
    vector<vector<int>> permute(vector<int>& nums) {
        if (nums.size() == 0) return res;
        vector<bool> used(nums.size(),false);
        process(0,nums,used);
        return res;
    }
};

时间复杂度: O ( N ! N ) O(N!N) O(N!N): N为数组 nums 的长度;时间复杂度和数组排列的方案数成线性关系,即复杂度为 O(N!);数组拼接操作 join() 使用 O(N);因此总体时间复杂度为 O(N!N) 。
空间复杂度: O ( N ) O(N) O(N) : 全排列的递归深度为 N ,系统累计使用栈空间大小为 O(N) 。

你可能感兴趣的:(c++)