跳转至

面试算法准备

美团codetop

206. 反转链表

/**
 * 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* reverseList(ListNode* head) {
        ListNode *dummy = NULL;
        ListNode *l = dummy, *r = head;
        while (r) {
            ListNode *tmp = r->next;
            r->next = l;
            l = r;
            r = tmp;
        }
        return l;
    }
};

88. 合并两个有序数组

从后向前的双指针

class Solution {
public:
// 类似于归并排序中的一个小部分
// 要会用
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int l = m - 1, r = n - 1;
        int i = m + n - 1;
        while (l >= 0 && r >= 0) {
            if (nums1[l] > nums2[r]) {
                nums1[i] = nums1[l];
                i--;
                l--;
            }
            else {
                nums1[i] = nums2[r];
                i--;
                r--;
            }
        }
        while (l >= 0) {
            nums1[i] = nums1[l];
            i--;
            l--;
        }
        while (r >= 0) {
            nums1[i] = nums2[r];
            i--;
            r--;
        }
    }
};

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

class Solution {
public:
    // int quick_select(vector<int>& nums, int l, int r, int k) {
    //     if (l == r) return nums[l];
    //     int x = nums[(l + r) >> 1];
    //     int i = l - 1, j = r + 1;
    //     while (i < j) {
    //         do i++; while (nums[i] > x);
    //         do j--; while (nums[j] < x);
    //         if (i < j) swap(nums[i], nums[j]);
    //     }
    //     if (k <= j) return quick_select(nums, l, j, k);
    //     else return quick_select(nums, j + 1, r, k);
    // }
    void maxHeapify(vector<int>& nums, int i, int heapsize) {
        int largest = i;
        int left = 2 * i + 1, right = 2 * i + 2;
        if (left < heapsize && nums[left] > nums[largest]) {
            largest = left;
        }
        if (right < heapsize && nums[right] > nums[largest]) {
            largest = right;
        }
        if (i != largest) {
            swap(nums[i], nums[largest]);
            maxHeapify(nums, largest, heapsize);
        }
    }
    void buildMaxHeap(vector<int>& nums, int heapsize) {
        for (int i = heapsize - -1; i >= 0; i--) {
            maxHeapify(nums, i, heapsize);
        }
    }

    int findKthLargest(vector<int>& nums, int k) {
        int heapsize = nums.size();
        buildMaxHeap(nums, heapsize);
        for (int i = 0; i < k - 1; i++) {
            swap(nums[0], nums[heapsize - 1]);
            heapsize--;
            maxHeapify(nums, 0, heapsize);
        } 
        return nums[0];
    }

};

146. LRU 缓存

#include <bits/stdc++.h>
using namespace std;

class LRUCache {
public:
    struct Node {
        int key, value;
        Node *left, *right;
        Node(int key, int value) : key(key), value(value), left(nullptr), right(nullptr) {};
    };
    Node *R, *L;
    int n;
    unordered_map<int, Node*> hash;
    LRUCache(int capacity) {
        n = capacity;
        R = new Node(-1, -1);
        L = new Node(-1, -1);
        L->right = R;
        R->left = L;
    }
    int get(int key) {
        // 返回值
        // 更新链表
        if (hash.count(key)) {
            Node *p = hash[key];
            remove(p);
            insert(p);
            return p->value;
        }
        else return -1;
    }
    void put(int key, int value) {
        if (hash.count(key)) {
            Node *p = hash[key];
            p->value = value;
            remove(p);
            insert(p);
        }
        else {
            if (hash.size() == n) {
                Node *p = R->left;
                // 链表
                remove(p);
                // 哈希
                hash.erase(p->key);
                // 内存
                delete(p);
            }
            Node *p = new Node(key, value);
            insert(p);
            hash[key] = p;
        }
    }
    void remove(Node *p) {
        p->left->right = p->right;
        p->right->left = p->left;
    }
    void insert(Node *p) {
        p->right = L->right;
        p->left = L;
        L->right = p;
        p->right->left = p;
    }

    void check() {
        Node *curr = L;
        cout << "check!" << endl;
        while (curr != nullptr) {
            cout << curr->key << ' ';
            curr = curr->right;
        }
        cout << endl;
    }
};

int main () {
    LRUCache cache(2);
    cout << cache.get(1) << endl;
    cache.put(3, 3);
    // cache.check();
    cache.put(4, 4);
    // cache.check();
    cache.put(5, 5);
    // cache.check();
    cout << cache.get(5) << endl;
    cout << cache.get(3) << endl;
    return 0;
}

141. 环形链表

快慢指针建议用fast和slow

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

102. 二叉树的层序遍历

stack, 
    size()
    empty()
    push()  向栈顶插入一个元素
    top()  返回栈顶元素
    pop()  弹出栈顶元素

queue, 队列先进先出没有clear
    size()
    empty()
    push()  向队尾插入一个元素
    front()  返回队头元素
    back()  返回队尾元素
    pop()  弹出队头元素
    q = queue<int>(); 能够直接清空q而不需要用到clear
/**
 * 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) {
        if (!root) return {};
        vector<vector<int>> ans;
        queue<TreeNode*> q;
        q.push(root);
        while (!q.empty()) {
            vector<int> tmp;
            int n = q.size();
            while (n--) {
                TreeNode *curr = q.front();
                tmp.push_back(curr->val);
                if (curr->left) q.push(curr->left);
                if (curr->right) q.push(curr->right);
                q.pop();
            }
            ans.push_back(tmp);
        }
        return ans;
    }
};

21. 合并两个有序链表

!!!!链表题不要忘记递归!!!!!

/**
 * 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* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if (!list1) return list2;
        if (!list2) return list1;
        if (list1->next && list1->val == list1->next->val) return mergeTwoLists(list1->next, list2);
        if (list2->next && list2->val == list2->next->val) return mergeTwoLists(list2->next, list1);
        if (list2->next && list2->val == list2->next->val) list2 = list2->next;
        if (list1->val < list2->val) {
            list1->next = mergeTwoLists(list1->next, list2);
            return list1;
        }
        else if (list1->val > list2->val){
            list2->next = mergeTwoLists(list2->next, list1);
            return list2;
        }
        else {
            return mergeTwoLists(list1->next, list2);
        }
    }
};

143. 重排链表

/**
 * 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:
    void reorderList(ListNode* head) {
        ListNode *fast = head, *slow = head;
        while (fast && fast->next) {
            fast = fast->next->next;
            slow = slow->next;
        }
        fast = slow;
        slow = nullptr;
        while (fast) {
            ListNode* tmp = fast->next;
            fast->next = slow;
            slow = fast;
            fast = tmp;
        }
        fast = head;
        while (fast->next && slow->next) {
            ListNode* l = fast->next;
            ListNode* r = slow->next;
            fast->next = slow;
            slow->next = l;
            fast = l;
            slow = r;
        }
    }
};

92. 反转链表 II

/**
 * 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* reverseBetween(ListNode* head, int left, int right) {
        if (!head) return head;
        ListNode *dummy = new ListNode(-1, head);
        ListNode *curr = dummy;
        for (int i = 0; i < left - 1; i++) curr = curr->next;
        ListNode *l = dummy;
        for (int i = 0; i < left; i++) l = l->next;

        ListNode *r = l->next;
        for (int i = 0; i < right - left; i++) {
            ListNode *tmp = r->next;
            r->next = l;
            l = r;
            r = tmp;
        }
        // l是起点,r是接上去的点
        ListNode* tmp = curr->next;
        curr->next = l;
        tmp->next = r;
        return dummy->next;


    }
};

23. 合并 K 个升序链表

/**
 * 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* mergeTwoLists(ListNode* a, ListNode* b) {
        if (!a) return b;
        if (!b) return a;
        if (a->val < b->val) {
            a->next = mergeTwoLists(a->next, b);
            return a;
        }
        else {
            b->next = mergeTwoLists(b->next, a);
            return b;
        }
    }

    ListNode* merge(vector<ListNode*>& lists, int l, int r) {
        if (l == r) return lists[l];
        if (l > r) return nullptr;
        int mid = (l + r) >> 1;
        return mergeTwoLists(merge(lists, l, mid), merge(lists, mid + 1, r));
    }

    ListNode* mergeKLists(vector<ListNode*>& lists) {
        int n = lists.size();
        if (n == 0) return nullptr;
        return merge(lists, 0, n - 1);
    }
};

3. 无重复字符的最长子串

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char, int> hash;
        if (!s.size()) return 0;
        // 滑动窗口
        // vector<int> cnt(26);
        int ans = 0;
        int j = 0;
        int len = 0;
        for (int i = 0; i < s.size(); i++) {
            len++;
            hash[s[i]]++;
            while (hash[s[i]] > 1) {
                hash[s[j]] --;
                j++;
                len--;
            }
            ans = max(len, ans);
        }
        return ans;
    }
};

82. 删除排序链表中的重复元素 II

/**
 * 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) {
        ListNode *dummy = new ListNode(-1, head);
        ListNode *curr = dummy;
        while (curr && curr->next) {
            while (curr->next && curr->next->next && curr->next->val == curr->next->next->val) {
                int a = curr->next->val;
                while (curr->next) {
                    if (curr->next->val == a) {
                        curr->next = curr->next->next;
                    }
                    else break;
                }
            }
            // if (curr->next->next && curr->next->val != curr->next->next->val) {
                curr = curr->next;
            // }
            // else continue;
        }
        return dummy->next;
    }
};

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) {
        // x = a + b
        // 2x = a + b + nc
        // a  = n - 1 * c + c - b
        if (!head || !head->next || !head->next->next) return nullptr;
        ListNode *fast = head, *slow = head;
        while (fast->next && fast->next->next) {
            fast = fast->next->next;
            slow = slow->next;
            if (slow == fast) break;
        }
        if (slow != fast) return nullptr;
        slow = head;

        while (slow != fast) {
            slow = slow->next;
            fast = fast->next;
        }
        return fast;

    }
};

124. 二叉树中的最大路径和

/**
 * 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 ans = INT_MIN;
    int maxPathSum(TreeNode* root) {
        dfs(root);
        return ans;
    }
    int dfs(TreeNode* root) {
        if (!root) return 0;
        int left = max(dfs(root->left), 0);
        int right = max(dfs(root->right), 0);
        ans = max(ans, left + right + root->val);
        return max(left, right) + root->val;
    }
};

15. 三数之和

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        // 首先要从小到大排列,然后再进行双指针
        // 最后注意去重
        vector<vector<int>> ans;
        sort(nums.begin(), nums.end());
        int n = nums.size();
        for (int i = 0; i < n; i++) {
            if (i && nums[i] == nums[i - 1]) continue;
            int j = i + 1, k = n - 1;
            for (; j < k; j++) {
                // int sum = nums[i] + nums[j] + nums[k];
                if (j >= i + 2 && nums[j] == nums[j - 1]) {
                    continue;
                }
                while (nums[i] + nums[j] + nums[k - 1] >= 0 && k - 1 > j) {
                    k--;
                }
                if (nums[i] + nums[j] + nums[k] == 0) {
                    ans.push_back({nums[i], nums[j], nums[k]});
                }

            }
        }
        return ans;
    }
};

腾讯

53. 最大子数组和

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        // f[i] = f[i - 1] + nums[i] // nums[i]
        int n = nums.size();
        int res = INT_MIN;
        vector<int> f(n + 1);
        for (int i = 1; i <= n; i++) {
            f[i] = max(f[i - 1] + nums[i - 1], nums[i - 1]);
            res = max(f[i], res);
        }
        return res;
    }
};

415. 字符串相加

class Solution {
public:
    vector<int> add(vector<int>& A, vector<int>& B) {
        vector<int> C;
        for (int i = 0, t = 0; i < A.size() || i < B.size() || t; i ++ ) {
            if (i < A.size()) t += A[i];
            if (i < B.size()) t += B[i];
            C.push_back(t % 10);
            t /= 10;
        }
        return C;
    }

    string addStrings(string a, string b) {
        vector<int> A, B;
        for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
        for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0');
        auto C = add(A, B);
        string c;
        for (int i = C.size() - 1; i >= 0; i -- ) c += to_string(C[i]);
        return c;
    }
};

腾讯真题:寻找最长递增子序列,按字典序输出

#include <iostream>
#include <vector>
#include <algorithm>

void reconstruct_print(int end, const std::vector<int>& a, const std::vector<int>& p) {
    int x = end;
    std::vector<int> stack;
    for (; p[x] >= 0; x = p[x]) stack.push_back(a[x]);
    std::cout << a[x];
    for (int i = stack.size() - 1; i >= 0; i--) {
        std::cout << " " << stack[i];
    }
    std::cout << "\n";
}

int main() {
    std::vector<int> a = {1, 2, 8, 6, 4};
    int n = a.size();
    std::vector<int> dp(n, 1), parent(n, -1);
    int max_len = 0, best_end = 0;

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < i; ++j) {
            if (a[j] < a[i]) {
                if (dp[j] + 1 > dp[i]) {
                    dp[i] = dp[j] + 1;
                    parent[i] = j;
                } else if (dp[j] + 1 == dp[i] && a[j] < a[parent[i]]) {
                    // 更新parent为字典序最小的选择
                    parent[i] = j;
                }
            }
        }
        if (dp[i] > max_len) {
            max_len = dp[i];
            best_end = i;
        } else if (dp[i] == max_len && a[i] < a[best_end]) {
            // 选择一个字典序最小的结束点
            best_end = i;
        }
    }

    std::cout << "Length of LIS: " << max_len << "\n";
    std::cout << "LIS: ";

460. LFU 缓存

class LFUCache {
public:
    struct Node {
        Node *left, *right;
        int key, val;
        Node(int _key, int _val) {
            key = _key, val = _val;
            left = right = NULL;
        }
    };
    struct Block {
        Block *left, *right;
        Node *head, *tail;
        int cnt;
        Block(int _cnt) {
            cnt = _cnt;
            left = right = NULL;
            head = new Node(-1, -1), tail = new Node(-1, -1);
            head->right = tail, tail->left = head;
        }
        ~Block() {
            delete head;
            delete tail;
        }
        void insert(Node* p) {
            p->right = head->right;
            head->right->left = p;
            p->left = head;
            head->right = p;
        }
        void remove(Node* p) {
            p->left->right = p->right;
            p->right->left = p->left;
        }
        bool empty() {
            return head->right == tail;
        }
    }*head, *tail;
    int n;
    unordered_map<int, Block*> hash_block;
    unordered_map<int, Node*> hash_node;

    void insert(Block* p) {  // 在p的右侧插入新块,cnt是p->cnt + 1
        auto cur = new Block(p->cnt + 1);
        cur->right = p->right;
        p->right->left = cur;
        p->right = cur;
        cur->left = p;
    }

    void remove(Block* p) {
        p->left->right = p->right;
        p->right->left = p->left;
        delete p;
    }

    LFUCache(int capacity) {
        n = capacity;
        head = new Block(0), tail = new Block(INT_MAX);
        head->right = tail, tail->left = head;
    }

    int get(int key) {
        if (hash_block.count(key) == 0) return -1;
        auto block = hash_block[key];
        auto node = hash_node[key];
        block->remove(node);
        if (block->right->cnt != block->cnt + 1) insert(block);
        block->right->insert(node);
        hash_block[key] = block->right;
        if (block->empty()) remove(block);
        return node->val;
    }

    void put(int key, int value) {
        if (!n) return;
        if (hash_block.count(key)) {
            hash_node[key]->val = value;
            get(key);
        } else {
            if (hash_block.size() == n) {
                auto p = head->right->tail->left;
                head->right->remove(p);
                if (head->right->empty()) remove(head->right);
                hash_block.erase(p->key);
                hash_node.erase(p->key);
                delete p;
            }
            auto p = new Node(key, value);
            if (head->right->cnt > 1) insert(head);
            head->right->insert(p);
            hash_block[key] = head->right;
            hash_node[key] = p;
        }
    }
};

/**
 * Your LFUCache object will be instantiated and called as such:
 * LFUCache* obj = new LFUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */

作者yxc
链接https://www.acwing.com/activity/content/code/content/555766/
来源AcWing
著作权归作者所有商业转载请联系作者获得授权非商业转载请注明出处

704. 二分查找

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int l = 0, r = nums.size() - 1;
        while (l < r) {
            int mid = (l + r) >> 1;
            int x = nums[mid];
            if (x >= target) {
                r = mid;
            }
            else l = mid + 1;
        }
        if (nums[r] == target) {
            return r;
        }
        else return -1;
    }
};

8. 字符串转换整数 (atoi)

C++中想要读取前导空格,读取一整行需要使用getlien(std::cin, string)

比如

    string line;
    getline(cin, line);
    string string2;
    cin >> string2;
    cout << "answer:" << line << endl;
    cout << "answer:" << string2 << endl;

输出分别是
answer:     string
answer:string
class Solution {
public:
    int myAtoi(string s) {
        int i = 0;
        char f;
        int res = 0;
        while (s[i] == ' ') {
            i++;
        }

        if (s[i] == '-' || s[i] == '+') {
            f = s[i];
            i++;
        }
        while (i < s.size() && s[i] >= '0' && s[i] <= '9') {
            int toAdd = s[i] - '0';
            // res * 10 + toAdd < INT_MAX
            if (res > (INT_MAX - toAdd) / 10) {
                if (f == '-') return INT_MIN;
                // 无论是前面没有符号或者有+的,都是正数
                else return INT_MAX;
            }
            res = res * 10 + toAdd;
            i++;
        }
        if (f == '-') return -res;
        else return res;
    }
};

300. 最长递增子序列

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        // 使用动态规划来做:
        // dp[i]代表的是以nums[i]为结尾的最长的递增子序列的长度
        // 所以对于i就要去遍历从0 ~ i - 1, 来确定dp[i]的值
        int res = 1;
        int n = nums.size();
        vector<int> dp(n, 1);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                if (nums[i] > nums[j]) {
                    dp[i] = max(dp[i], dp[j] + 1);
                    if (dp[i] > res) {
                        res = dp[i];
                    }
                }
            }
        }
        return res;

    }
};

46. 全排列

class Solution {
public:
    vector<bool> visited;
    vector<vector<int>> ans;
    vector<vector<int>> permute(vector<int>& nums) {
        int n = nums.size();
        visited = vector<bool>(n, false);
        vector<int> path;
        dfs(nums, path, 0);
        return ans;
    }
    void dfs (vector<int>& nums, vector<int>& path, int n) {
        if (n == nums.size()) ans.push_back(path);
        for (int i = 0; i < nums.size(); i++) {
            if (visited[i] == false) {
                path.push_back(nums[i]);
                visited[i] = true;
                dfs(nums, path, n + 1);
                visited[i] = false;
                path.pop_back();
            }
        }
    }
};
class Solution {
public:
    // 第二种方法用来保证不会再dfs已经经过的点:
    // 既然数组中的数字是定的,我们只需要每次dfs将我们想要的那个数字swap过来就行了
    vector<vector<int>> ans;
    vector<vector<int>> permute(vector<int>& nums) {
        dfs(nums, 0);
        return ans;
    }
    void dfs(vector<int>& nums, int n) {
        // n:正在确定nums的第几个位置
        if (n == nums.size()) ans.push_back(nums);
        for (int i = n; i < nums.size(); i++) {
            // n之前的位置都已经确定好了,不能动
            swap(nums[i], nums[n]);
            dfs(nums, n + 1);
            // 注意nums是动态维护的数组
            // 不要忘记撤销掉动态维护的数组
            swap(nums[i], nums[n]);
        }
    }
};

470. 用 Rand7() 实现 Rand10()

// The rand7() API is already defined for you.
// int rand7();
// @return a random integer in the range 1 to 7

class Solution {
public:
    int rand10() {
        // 1234567
        // 8910111213
        // 保证在1 ~ 49之间完全是均匀的
        int t = rand7() + (rand7() - 1) * 7;
        if (t > 40) return rand10();
        return t % 10  + 1;
    }
};

25. K 个一组翻转链表

/**
 * 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* reverseKGroup(ListNode* head, int k) {
        ListNode *dummy = new ListNode(-1, head);
        ListNode *curr = dummy;
        while (curr) {
            ListNode *tmp = curr;
            for (int i = 0; i < k; i++) {
                tmp = tmp->next;
                if (!tmp) return dummy->next;
            }

            ListNode *left = curr->next, *right = curr->next->next;
            for (int i = 0; i < k - 1; i++) {
                ListNode *third = right->next;
                right->next = left;
                left = right;
                right = third;
            }
            curr->next->next = right;
            curr->next = left;



            for (int i = 0; i < k; i++) {
                curr = curr->next;
            }
        }
        return dummy->next;
    }
};

1. 两数之和

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> hash;
        for (int i = 0; i < nums.size(); i++) {
            int aim = target - nums[i];
            if (hash.find(aim) != hash.end()) {
                return {hash[aim], i};
            }
            else hash[nums[i]] = i;
        }
        return {};
    }
};

携程

5. 最长回文子串(需要重新刷)

dp法:

class Solution {
public:
    string longestPalindrome(string s) {
        // 动态规划f[i][j] = f[i + 1][j - 1]
        int n = s.size();
        if (n < 2) return s;
        vector<vector<bool>> f(n, vector<bool>(n));
        for (int i = 0; i < n; i++) {
            // 所有一个字母的都是回文
            f[i][i] = true;
        }
        int maxLen = 1;
        int start = 0;
        // 循环的话一定要从长度最小的开始
        for (int len = 2; len <= n; len++) {
            for (int i = 0; i + len - 1 < n; i++) {
                int j = i + len - 1;
                if (s[i] != s[j]) {
                    f[i][j] = false;
                }
                else {
                    if (len <= 3) {
                        f[i][j] = true;
                    }
                    else {
                        f[i][j] = f[i + 1][j - 1];
                    }
                }
                if (f[i][j] && len > maxLen) {
                    maxLen = len;
                    start = i;
                }
            }
        }
        return s.substr(start, maxLen);
    }
};

中心扩展法:中心要么是1个要么是2个

class Solution {
public:
    int palindrome(string &s, int l, int r, int n) {
        while (l >= 0 && r < n && s[l] == s[r]) l--, r++;
        return r - l - 1;
    }
    string longestPalindrome(string s) {
        int n = s.size();
        int start = 0, len = 0;
        int i = 0, j = 0;
        while (i < n && j < n) {
            if (s[i] == s[j]) {
                int l = palindrome(s, i, j, n);
                if (l > len) {
                    start = i - (l - 1) / 2;
                    len = l; 
                }
            }
            if (i == j) j++;
            else i++;
        }
        return s.substr(start, len);
    }
};