1.验证二叉搜索树
给定一个二叉树,判断其是否是一个有效的二叉搜索树。假设一个二叉搜索树具有如下特征:
节点的左子树只包含小于当前节点的数。节点的右子树只包含大于当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/validate-binary-search-tree
思路一:二叉搜索树中序遍历是一个递增序列。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isValidBST(TreeNode* root) {
        if(root == NULL) return true;
        //vector<int> t;
        dfs(root);
        for(int i =0;i < t.size() - 1;i++){
            if(t[i + 1] <= t[i]) return false;
        }
        return true;

    }   

    void dfs(TreeNode* root){
        if(root -> left) dfs(root->left);
        t.push_back(root -> val);
        if(root -> right) dfs(root->right);
    }
private:
    vector<int> t;
};

思路二:递归:设置一个区间,首先根节点的值应位于无穷大与无穷小之间,然后依次遍历左子树与右子树,因为左子树的值应都小于根节点,因此上界是根节点的值,而右子树下界是根节点的值。

class Solution {
public:
    bool helper(TreeNode* root, long long lower, long long upper) {
        if (root == nullptr) return true;
        if (root -> val <= lower || root -> val >= upper) return false;
        return helper(root -> left, lower, root -> val) && helper(root -> right, root -> val, upper);
    }
    bool isValidBST(TreeNode* root) {
        return helper(root, LONG_MIN, LONG_MAX);
    }
};

2.链表中倒数第K个节点
思路:双指针,先让第一个指针从头走k步,然后第二个指针与第一个指针一同开始走,当第一个指针z时,第二个指针就到了倒数第k个节点。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(pListHead==nullptr||k==0) return nullptr;
        ListNode* p1=pListHead;
        ListNode* p2=nullptr;
        for(int i=0;i<k-1;i++)
        {
            if(p1->next!=nullptr)
                p1=p1->next;
            else
                return nullptr;//k大于链表的长度
        }
        p2=pListHead;//只有合法时才将第二个指针指向头结点
        while(p1->next!=nullptr)
        {
            p2=p2->next;
            p1=p1->next;
        }
        return p2;
    }
};

3.反转链表
输入一个链表,将其反转,并返回新链表的表头。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead==nullptr||pHead->next==nullptr) return pHead;//边界情况
        ListNode *pReversedHead=nullptr;//用于记录最后一个节点
        ListNode *pNode=pHead;//当前节点
        ListNode *pPrev=nullptr;//当前节点的前一个节点
        while(pNode!=nullptr)
        {
            ListNode* pNext=pNode->next;
            if(pNext==nullptr)
                pReversedHead=pNode;//如果pNode到达尾结点,令此节点等于pNode
            pNode->next=pPrev;
            pPrev=pNode;
            pNode=pNext; //反转操作          
        }
        return pReversedHead;
    }
};

4.合并两个排序的链表
思路:递归思路和循环思路。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(pHead1==nullptr)
            return pHead2;
        if(pHead2==nullptr)
            return pHead1;
        ListNode* newHead=nullptr;
        if(pHead1->val<pHead2->val)
        {
            newHead=pHead1;
            newHead->next=Merge(pHead1->next,pHead2);
        }
        else if(pHead1->val>=pHead2->val)
        {
            newHead=pHead2;
            newHead->next=Merge(pHead1,pHead2->next);
        }
        return newHead;
    }
};