手撕力扣之翻转题:反转链表、反转链表 II、从尾到头打印链表、K 个一组翻转链表、回文链表、翻转二叉树、左旋转字符串

力扣206. 反转链表
反转一个单链表。
双指针法:

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* temp; // 保存cur的下一个节点
        ListNode* cur = head;
        ListNode* pre = NULL;
        while(cur) {
            temp = cur->next;  // 保存一下 cur的下一个节点,因为接下来要改变cur->next
            cur->next = pre; // 翻转操作
            // 更新pre 和 cur指针
            pre = cur;
            cur = temp;
        }
        return pre;
    }
};

递归法:

class Solution {
public:
    ListNode* reverse(ListNode* pre,ListNode* cur){
        if(cur == NULL) return pre;
        ListNode* temp = cur->next;
        cur->next = pre;
        // 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步
        // pre = cur;
        // cur = temp;
        return reverse(cur,temp);
    }
    ListNode* reverseList(ListNode* head) {
        // 和双指针法初始化是一样的逻辑
        // ListNode* cur = head;
        // ListNode* pre = NULL;
        return reverse(NULL, head);
    }

};

力扣092. 反转链表 II
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:1 ≤ m ≤ n ≤ 链表长度。

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        if(n == 1 || !head) return head; // 特殊情况处理(当然不写也行,写是为了找找感觉)

        ListNode *prev = NULL, *curr = head; // 定义prev和curr指针,用于翻转链表
        while(m > 1)
        {
            prev = curr;
            curr = curr -> next; // 将prev与curr定位到需要翻转的初始位置
            m --;
            n --; // 这里很重要!
        }
        ListNode *before = prev, *after = curr; // 定义prev前面一位和curr后面一位的指针,方便翻转完链表后重新连起来
        while(n > 0)
        {
            // 翻转链表四步大法
            ListNode* nextptr = curr -> next;
            curr -> next = prev;
            prev = curr;
            curr = nextptr;
            n --;
        }
        if(before) before -> next = prev; // 将链表重新连起来
        else head = prev; // 将链表重新连起来
        after -> next = curr; // 将链表重新连起来
        return head;
    }
};

力扣剑指 Offer 06. 从尾到头打印链表
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> res;
    vector<int> reversePrint(ListNode* head) {
        ListNode *pre = nullptr;
        ListNode *next = head;
        ListNode *cur = head;
        while(cur){
            next = cur->next;//保存当前结点的下一个节点
            cur->next = pre;//当前结点指向前一个节点,反向改变指针
            pre = cur;//更新前一个节点
            cur = next;//更新当前结点
        }
        while(pre){//上一个while循环结束后,pre指向新的链表头
            res.push_back(pre->val);
            pre = pre->next;
        }
        return res;
    }
};

作者:wangxiaole
链接:https://leetcode-cn.com/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/solution/csan-chong-jie-fa-reversefan-zhuan-fa-dui-zhan-fa-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

力扣025. K 个一组翻转链表
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

class Solution {
public:
    /**
     * 
     * @param head ListNode类 
     * @param k int整型 
     * @return ListNode类
     */
     //K个为1组,从某一组第一个元素到下一组第一个元素,进行反转
    ListNode* reverse(ListNode* first,ListNode* last)
    {
        ListNode* pre=nullptr;
        while(first!=last)
        {
            ListNode* next=first->next;
            first->next=pre;
            pre=first;
            first=next;
        }
        return pre;
    }
    ListNode* reverseKGroup(ListNode* head, int k) {
        // write code here
        if(!head)  return nullptr;
        ListNode* node=head;
        for(int i=0;i<k;i++)
        {
            if(!node)
                return head;  //此时题目是不满K个不反转;
                            //若要求不满K个反转,换成break,return head变成break;
            node=node->next;
        }
        ListNode* newList=reverse(head,node);
        head->next=reverseKGroup(node,k);
        return newList;
    }
};

力扣234. 回文链表
用快慢指针遍历的同时翻转前半部分,然后与后半部分比较即可。

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        ListNode *slow = head, *fast = head;
        while(fast != nullptr && fast->next != nullptr){
            fast = fast->next->next;
            slow = slow->next;
        }
        // 如果结点个数为奇数
        if(fast != nullptr){
            slow = slow->next;
        }

        ListNode *rev = reverse(slow);
        // rev长度 <= head长度,所以只用判断rev
        while(rev != nullptr){
            if(rev->val != head->val){
                return false;
            }
            rev = rev->next;
            head = head->next;
        }
        return true;
    }

private:
    // 迭代效率更高,这里用迭代
    ListNode* reverse(ListNode *list){
        ListNode *pre = nullptr, *cur = list;
        while(cur != nullptr){
            ListNode *next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }
};

作者:pedantic-mcleanbpp
链接:https://leetcode.cn/problems/palindrome-linked-list/solution/hui-wen-lian-biao-fan-zhuan-lian-biao-by-irf3/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

力扣226. 翻转二叉树:【递归法】详细讲解!

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == NULL) return root;
        swap(root->left, root->right);  // 中
        invertTree(root->left);         // 左
        invertTree(root->right);        // 右
        return root;
    }
};

作者:carlsun-2
链接:https://leetcode-cn.com/problems/invert-binary-tree/solution/226-fan-zhuan-er-cha-shu-di-gui-fa-die-dai-fa-xian/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

迭代法:

//前序遍历
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == NULL) return root;
        stack<TreeNode*> st;
        st.push(root);
        while(!st.empty()) {
            TreeNode* node = st.top();              // 中
            st.pop();
            swap(node->left, node->right);          
            if(node->right) st.push(node->right);   // 右
            if(node->left) st.push(node->left);     // 左
        }
        return root;
    }
};

作者:carlsun-2
链接:https://leetcode-cn.com/problems/invert-binary-tree/solution/226-fan-zhuan-er-cha-shu-di-gui-fa-die-d-hpgz/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
//层序遍历
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                swap(node->left, node->right); // 节点处理
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return root;
    }
};

作者:carlsun-2
链接:https://leetcode-cn.com/problems/invert-binary-tree/solution/226-fan-zhuan-er-cha-shu-di-gui-fa-die-d-hpgz/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

力扣剑指 Offer 58 - II. 左旋转字符串
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
法一:两个for循环

class Solution {
public:
    string reverseLeftWords(string s, int n) {
        string re = "";
        for(int i = n; i < s.length(); i++) re += s[i];
        for(int i = 0; i < n; i++) re += s[i];
        return re;
    }
};

法二:整体反转+局部反转

class Solution {
public:
    string reverseLeftWords(string s, int n) {
        reverse(s.begin(), s.begin() + n);
        reverse(s.begin() + n, s.end());
        reverse(s.begin(), s.end());
        return s;
    }
};

作者:carlsun-2
链接:https://leetcode-cn.com/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof/solution/yuan-di-ju-bu-fan-zhuan-zheng-ti-fan-zhuan-xiang-j/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值