Leetcode刷题实录

  • Note:仅记录个人leetcode刷题思路,不一定最优解~

1790. Check if One String Swap Can Make Strings Equal

题目描述:

You are given two strings s1 and s2 of equal length. A string swap is an operation where you choose two indices in a string (not necessarily different) and swap the characters at these indices.
Return true if it is possible to make both strings equal by performing at most one string swap on exactly one of the strings. Otherwise, return false.

题目难度:简单
个人思路:如果两个字符串长度不一样直接返回false,返回true的情况只有两种:1.s1和s2完全相同,2.s1有且只有2个字母与s2位置不同。

class Solution {
    
    
public:
    bool areAlmostEqual(string s1, string s2) {
    
    
        vector<int>inx; //记录s1和s2不同字符的位置
        if (s1 == s2){
    
     //如果两个字符串完全相同,直接返回true
            return true;
        }
        else{
    
     
        	//否则,如果两字符串长度不一样,返回false
            if (s1.size() != s2.size()){
    
    
                return false;
            }
            //遍历比较字符串s1和s2对应位置的字符
            for (int i = 0; i < s1.size(); i++){
    
    
                if (s1[i] == s2[i]){
    
     //如果对应位置字符相同,则继续遍历
                    continue;
                } 
                //如果两字符串对应位置字符不一样,则记录下不一样的下标位置
                inx.push_back(i);
            }
            //由于题目只要求计算交换一次的结果,也就是一个字符串只能有两个字符不一样,如果不一样的下标个数不等于2,说明无法仅交换一次实现字符串相等。
            if (inx.size()!=2){
    
    
                return false;
            }
            //如果不同的两个位置对应的字符交叉相等,说明能够实现交换一次使得两字符串相等,返回true。
            if ((s1[inx[0]]==s2[inx[1]])&&(s1[inx[1]]==s2[inx[0]])){
    
    
                return true;
            }
            else{
    
    
                return false;
            }
        }
    }
};

341. Flatten Nested List Iterator

题目描述:

Given a nested list of integers, implement an iterator to flatten it.
Each element is either an integer, or a list – whose elements may also be integers or other lists.
Example 1:
Input: [[1,1],2,[1,1]]
Output: [1,1,2,1,1]
Explanation: By calling next repeatedly until hasNext returns false,
the order of elements returned by next should be: [1,1,2,1,1].

题目难度:medium
解题思路:使用队列,先遍历nestedList,将每个int元素放入队列当中,之后在next函数中依次返回队头元素,同时pop队头元素。由于nestList的元素可能是int也可能是nestlist,所以遍历的时候用DFS依次将每个int元素送入队列即可。还有另外一种思路,使用栈stack,利用栈FILO特性,先将每个元素压入栈中,在出栈时再处理int和nestlist。

//递归解法
class NestedIterator {
    
    
public:
    NestedIterator(vector<NestedInteger> &nestedList) {
    
    
        dfs(nestedList);
    }
    //dfs遍历nestedList
    void dfs(vector<NestedInteger>& L){
    
    
            for (auto & l : L){
    
    
                if (l.isInteger()){
    
     //如果这个元素是整数,直接送入队列
                    d.push_back(l.getInteger());
                }
                else{
    
     //否则,将递归地遍历这个子列表
                    dfs(l.getList());
                }
            }
        }

    int next() {
    
     //返回队头元素同时弹出队头元素
        int it = d.front();
        d.pop_front();
        return it;
    }
    
    bool hasNext() {
    
     //只要队列不空说明还有元素没有输出
        return !(d.empty());
    }
    private:
    deque<int> d; //队列用于存放遍历结果
};

82. Remove Duplicates from Sorted List II

题目描述

Given the head of a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list. Return the linked list sorted as well.

题目难度:medium
解题思路:设置两个指针pre和cur,pre用于记录数值相同节点的前一个结点,cur表示当前结点。遍历整个链表,1.如果cur和下一个节点cur->next的val不相等,则同时移动pre和cur。2.如果cur和cur->next的val相等,移动cur到cur->next节点直到cur和cur->next节点值不相等为止,之后将pre->next指向cur->next,然后cur再移到下一个节点cur->next。

/**
 * 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* deleteDuplicates(ListNode* head) {
    
    
        if (!head || head->next == nullptr){
    
    
            return head;
        }
        ListNode* dummy = new ListNode(0, head);  //dummy节点指向head
        ListNode* pre = dummy;  //pre保存前一个节点位置
        ListNode* cur = head;  
        while(cur && cur->next != nullptr){
    
      //一直遍历直到链表尾部
            if (cur->val == cur->next->val){
    
      //相邻两节点val相等
                while(cur->next && cur->val == cur->next->val){
    
      //遍历找到最后一个相等的节点位置,如1,2,2,2,2,3 cur从下标1开始一直遍历到下标4(这里只是名义上的下标)
                    cur = cur->next;
                }
                pre->next = cur->next; //将pre的下一个节点连到最后一个相等节点的下一个节点
                cur = cur->next;  //cur从最后一个相等节点的下一个节点开始继续遍历
            }
            else{
    
    
                pre = cur;  //如果相邻两节点值不一样,同时移动pre和cur
                cur = cur->next;
            }
        }
    return dummy->next; 
    }
};

83. Remove Duplicates from Sorted List

题目描述:

Given the head of a sorted linked list, delete all duplicates such that each element appears only once. Return the linked list sorted as well.
Input: head = [1,1,2]
Output: [1,2]

题目难度:easy
解题思路:同上,不过简单一些。

class Solution {
    
    
public:
    ListNode* deleteDuplicates(ListNode* head) {
    
    
         ListNode* dummy = head;
         ListNode* pre = head;
         if (!head){
    
    
             return head;
         }
         while(dummy){
    
    
             if (dummy->next && dummy->val == dummy->next->val){
    
    
                 dummy = dummy->next;
             }
             else{
    
    
                 dummy = dummy->next;
                 pre->next = dummy;
                 pre = dummy;
             }
         }
         return head;
    }
};

61. Rotate List

题目描述:

Given the head of a linked list, rotate the list to the right by k places.
Input: head = [1,2,3,4,5], k = 2
Output: [4,5,1,2,3]

题目难度:medium
解题思路:先遍历链表得到链表长度,对k取余以链表长度。设置前后两个快慢指针,快指针先前进k步,然后两个指针同时前进直到快指针达到链表尾部为止。将快指针next连接到头节点head即可得到移动k步的链表.

class Solution {
    
    
public:
    ListNode* rotateRight(ListNode* head, int k) {
    
    
        if(!head){
    
    
            return head;
        }
        ListNode* dummy = head;
        ListNode* p1 = head;
        ListNode* p2 = head;
        ListNode* p = nullptr;
        int length = 0;
        //1。遍历链表,得到链表长度
        while(dummy){
    
    
            length++;
            dummy = dummy->next;
        }
        delete dummy;
        //若移动距离超出链表长度,取余
        k = k % length;
        //p1指针先前进k个节点
        while(k--){
    
    
            p1 = p1->next;
        }
        //然后p1和p2同时前进,直到p1到达链表末尾
        while(p1->next){
    
    
            p1 = p1->next;
            p2 = p2->next;
        }
        //p1连到头节点head,p2就是移动后的末尾节点,p2->next=nullptr
        p1->next = head;
        p = p2->next;
        p2->next = nullptr;
        return p;
    }
};

94. Binary Tree Inorder Traversal

题目描述:

Given the root of a binary tree, return the inorder traversal of its nodes’ values.

题目难度:medium
解题思路:两种,递归和非递归。非递归使用栈来存储遍历的节点。

/**
 * 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<int> inorderTraversal(TreeNode* root) {
    
    
        inorder(root);
    return this->res;
    }
    void inorder(TreeNode* t){
    
    
        if (!t){
    
    
            return ;
        }
        inorder(t->left);
        this->res.push_back(t->val);
        inorder(t->right);
    }
    private:
    vector<int>res;
};

//非递归
class Solution {
    
    
public:
    vector<int> inorderTraversal(TreeNode* root) {
    
    
        vector<int> res;
        if (!root){
    
       //空树
            return res;
        }
        stack<TreeNode*>s;
        TreeNode* node = root;
        while(node || !s.empty()){
    
      //遍历二叉树,第一次节点入栈后,若之后栈为空就结束遍历。
            while(node){
    
      //当前节点node不为空,说明没遍历到该子树的最左下角,
                s.push(node);  //此时将当前节点node入栈,同时遍历节点指向左孩子,
                node = node->left; //如此循环直到到达该子树的最左下角
            }
            //到达该子树最左下角,将栈顶元素的值存入数组
            res.push_back(s.top()->val);
            node = s.top()->right;  //遍历节点node指向栈顶元素的右孩子,遍历右孩子
            s.pop();  //弹出栈顶元素
        }
    return res;
    }
};

102. Binary Tree Level Order Traversal

题目描述:

Given the root of a binary tree, return the level order traversal of its nodes’ values. (i.e., from left to right, level by level).
Input: root = [3,9,20,null,null,15,7]
Output: [[3],[9,20],[15,7]]

题目难度:medium
解题思路:经典题目,用队列来模拟。首先判断节点,将根节点送入队列,记录每一层的节点个数,若有左右节点,则将其左右节点送入队列,同时弹出队头元素,每一层的节点的值作为res的一行。如此遍历直到队列内没有元素为止。

/**
 * 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;
        if (!root){
    
      //根节点为空,返回空数组
            return res;
        }
        queue<TreeNode*>q;
        TreeNode * node = root;
        q.push(node);            //根节点入队列
        while(!q.empty()){
    
           //一直遍历直到队列内没有元素
            vector<int> v;       //作为res的一个element
            int size = q.size(); //记录二叉树每一层的节点数
            while(size--){
    
           //遍历二叉树的某一层,size用于控制遍历的次数
                node = q.front(); 
                v.push_back(node->val); //取出队头元素的值
                if (node->left){
    
           //若存在,则将队头元素的左孩子加入队列
                    q.push(node->left);
                }
                if (node->right){
    
          //若存在,则将队头元素右孩子加入队列
                    q.push(node->right);
                }
                q.pop();          //弹出队头元素
                node = q.front(); //然后node指向下一个队头元素,直到遍历完这一层
            }
            res.push_back(v);     //将每一层的遍历结果v加入到最终结果中
        }
        return res;
    }
};

429.N叉树的层序遍历

题目描述:

Given an n-ary tree, return the level order traversal of its nodes’ values.
Nary-Tree input serialization is represented in their level order traversal, each group of children is separated by the null value (See examples).
Input: root = [1,null,3,2,4,null,5,6]
Output: [[1],[3,2,4],[5,6]]

题目难度:medium
解题思路:同上,不过就是改用一个循环来将孩子节点加入到队列中。

/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
    
    
public:
    vector<vector<int>> levelOrder(Node* root) {
    
    
        vector<vector<int>> res;
        if (!root){
    
    
            return res;
        }
        queue<Node*>q;
        Node* node = root;
        q.push(node);
        while(!q.empty()){
    
    
            vector<int> v;
            int size = q.size();
            while(size--){
    
    
                node = q.front();
                for (auto n : node->children){
    
     //不同之处,用for循环遍历孩子节点,其实二叉树也可以这样做
                    q.push(n);
                }
                v.push_back(node->val);
                q.pop();
                node = q.front();
            }
            res.push_back(v);
        }
        return res;
    }
};

78. Subsets

题目描述:

Given an integer array nums of unique elements, return all possible subsets (the power set).
The solution set must not contain duplicate subsets. Return the solution in any order.
Input: nums = [1,2,3]
Output: [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

题目难度:medium
解题思路:回溯法。首先先构建回溯递归树,就是先把可能的路径都画出来,找到状态变量和待选择的元素,做出选择,递归调用,递归返回后撤销选择。

class Solution {
    
    
public:
    vector<vector<int>>res;
    vector<int>path;
    vector<vector<int>> subsets(vector<int>& nums) {
    
    
        backtrace(nums, path, 0);
        return res;
    }
    void backtrace(vector<int>&nums, vector<int>&path, int start){
    
    
        res.push_back(path); //这里把可能的子集加入到res中
        //在待选择的列表中选择某一步进行递归
        for (int i = start; i < nums.size(); i++){
    
     
            path.push_back(nums[i]);  //选择nums[i]
            backtrace(nums, path, i+1);  //选择nums[i]之后递归选择nums[i+1]
            path.pop_back();  //撤销选择nums[i]
        }
    }
};

90. Subsets II

题目描述:

Given an integer array nums that may contain duplicates, return all possible subsets (the power set).
The solution set must not contain duplicate subsets. Return the solution in any order.
Input: nums = [1,2,2]
Output: [[],[1],[1,2],[1,2,2],[2],[2,2]]

题目难度:medium
解题思路:回溯法,不过与上面不一样的地方是,这里给的数组中可能含有重复的元素,需要对重复的元素进行剪枝,即不选择重复的元素。

class Solution {
    
    
public:
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
    
    
        sort(nums.begin(), nums.end()); //排序,方便去重
        backtrace(nums, path, 0);
        return res;
    }
    //回溯法
    void backtrace(vector<int>& nums, vector<int> &path, int start){
    
    
        res.push_back(path); //先添加路径
        for (int i = start; i < nums.size(); i++){
    
    
            if (i > start && nums[i]==nums[i-1]){
    
     //若与之前一个元素重复,则跳过
                continue;
            }
            path.push_back(nums[i]); //选择nums[i]加入到当前的路径
            backtrace(nums, path, i+1);  //在选择nums[i]的前提下,递归选择i+1及之后的元素
            path.pop_back();  //撤销选择nums[i]
        }
    }
private:
    vector<vector<int>> res;
    vector<int> path;
};

39. Combination Sum

题目描述:

Given an array of distinct integers candidates and a target integer target, return a list of all unique combinations of candidates where the chosen numbers sum to target. You may return the combinations in any order.
The same number may be chosen from candidates an unlimited number of times. Two combinations are unique if the frequency of at least one of the chosen numbers is different.
It is guaranteed that the number of unique combinations that sum up to target is less than 150 combinations for the given input.
Input: candidates = [2,3,6,7], target = 7
Output: [[2,2,3],[7]]
Explanation:
2 and 3 are candidates, and 2 + 2 + 3 = 7. Note that 2 can be used multiple times.
7 is a candidate, and 7 = 7.
These are the only two combinations.

题目难度:medium
解题思路:同上,不过这里需要判断路径的和sum与target的关系,若和sum大于target说明这条路径已经不满足条件,忽略这条路径,若sum==target说明这条路径满足条件,将这条路径加入到答案中,若路径和sum<target,则继续递归选择下一步直到满足递归停止条件。

class Solution {
    
    
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
    
    
        backtrace(candidates, path, target, 0, 0);
        return res;
    }
    void backtrace(vector<int>&nums, vector<int>&path, int target, int sum, int start){
    
    
        if (sum == target){
    
      //如果sum==target,说明这条路径的和已经满足条件,将这条路径加入答案res并返回。
            res.push_back(path);
            return;
        }
        //在选择的列表中进行选择
        for (int i = start; i < nums.size(); i++){
    
    
            //如果大于target,则说明这条路径之后的都不符合,跳过
            if (sum+nums[i] > target){
    
     
                continue;
            }
            path.push_back(nums[i]);
            backtrace(nums, path, target, sum+nums[i], i); //更新sum,递归到下一层
            path.pop_back(); //撤销选择nums[i]
        }
    }

private:
    vector<vector<int>>res;
    vector<int> path;
};

猜你喜欢

转载自blog.csdn.net/weixin_40313940/article/details/115117262